Albert Nadal Garriga Observacions d'un Lleidatà Cerverí. Enginyer informàtic. Emprenedor idealista. Catalanista enfeinat.

yada_header
YADA: Yet Another DoS Attack

YADA és un petit programa informàtic escrit en C que vaig programar a principis de l’any 2005, pocs mesos abans d’acabar la carrera d’enginyeria informàtica. La funcionalitat del programa consisteix en provocar la denegació de servei (DoS) a serveis que empren la pila TCP/IP com a capa de transport (http, ftp, dns, imap, smtp, ldap, pop, ssh, sip, xmpp, etc…). La idea de fer el programa no era altra que comprobar la manca de seguretat dels antics protocols de xarxa que a data d’avui encara es segueixen utilitzant amb normalitat mentre esperem com lentament s’implanta la versió 6 del protocol IP (IPv6).

YADA es pot descarregar prement aquí. Per usar-lo primer cal compilar-lo en una màquina Linux amb un compilador de C com el GCC.

gcc yada.c -o yada

El programa només funciona dins d’una LAN sense gateways ni routers, ja que la vulnerabilitat afecta principalment al protocol ARP (Address Resolution Protocol) encarregat de la ressolució d’adeces IP a adreces MAC. D’aquesta manera, un cop compilat, cal obtenir la nostra IP i la màscara de la xarxa mitjançant la comanda ifconfig.

En aquest exemple la IP és la 192.168.1.128 i la màscara de la xarxa és la 255.255.255.0 (0xffffff00). Així doncs ara només resta indicar la IP o nom del servidor i el port del servei a atacar. En el cas que es tracti d’un servidor de pàgines web aleshores el port a atacar serà el 80.

./yada 192.168.1.128 255.255.255.0 webmail.mycompany.lan 80

Per entendre com funciona el programa, cal primer entendre com funciona el protocol ARP. Aquest protocol s’encarrega d’obtenir les adreces MAC dels terminals d’una LAN a partir de les respectives adreces IP. Quan dos terminals d’una xarxa local volen establir una connexió TCP/IP necessiten saber les seves respectives adreces MAC per poder fer possible la comunicació a nivell d’stack Ethernet. No explicaré els detalls del protocol, en qualsevol cas recomano consultar-ne la documentació.

YADA es composa de tres processos que funcionen concurrentment:

1) Enviament massiu de peticions de connexió TCP/IP al servidor.
2) Captura de paquets TCP provinents del servidor i destinats a algun dels equips que YADA emula. El paquets que ho satisfan són respostos amb la corresponent confirmació ACK (corresponent a l’última part del handshake TCP).
3) Captura de paquets ARP REQUEST provinents del servidor i destinats a algun dels equips que YADA emula. Els paquets que ho satisfan són respostos amb un paquet ARP REPLY fals.

Inicialment es genera una llista amb centenars d’adreces IP falses però vàlides. Han de sér adreces vàlides que han pertànyer a la mateixa xarxa local. Es generen a partir de l’adreça local i la màscara de xarxa que l’usuari especifica en arrencar el programa. Si les adreces no són vàlides, els switches, routers o el propi servidor descartaran els paquets i no s’aconseguiran les connexions massives.

La llista d’adreces IP, un cop generada, s’ordena. Així les cerques sobre aquesta es poden fer dicotòmicament, és a dir, amb un cost logarítmic O(n*log(n)). Això és important ja que els paquets que viatgen per la xarxa s’han de capturar i processar en temps real, i per tant les operacions s’han de fer el més ràpid possible.

Tot seguit s’inicien dos fils d’execució (threads). Cada thread captura els paquets de la xarxa que passen per la targeta de xarxa del terminal. Un dels threads captura paquets Ethernet IP i l’altre captura paquets Ethernet ARP. El procés que captura paquets IP només ha de comprovar que l’adreça d’origen dels paquets es correspongui amb la del servidor i tinguin activat el flag SYN-ACK. Si aquesta primera condició es satisfà aleshores es comprova que l’adreça de destí pertanyi a alguna de les adreces de la llista. Si aquesta segona condició també es satisfà aleshores s’envia un paquet TCP amb el flag ACK activat amb el camp d’adreça d’origen la IP falsa corresponent, i el camp d’adreça destí la IP del servidor. Amb aquest thread es generen connexions TCP/IP massives.

El procés anterior no funciona si no es duen a terme les corresponents ressolucions d’adreces de hardware (MAC). El servidor no donarà mai per vàlid un intent de connexió d’un terminal sense conèixer-ne abans la seva adreça MAC. Quan el programa envia un paquet de petició de connexió TCP i el servidor el reb, aquest últim comprova si en coneix l’adreça MAC del terminal que la solicita. L’esperat és que no la tingui, ja que la IP usada és falsa, i per tant el servidor respondrà ràpidament amb un paquet ARP REQUEST preguntant quina és l’adreça MAC del terminal que fa la petició.

Per tant, el segon thread captura paquets ARP REQUEST. Quan es captura un paquet d’aquest tipus cal comprovar quina és la seva adreça IP d’origen i mirar si concorda amb la del servidor. Si aquesta condició es satisfà aleshores cal mirar si l’adreça IP que es vol resoldre coincideix amb alguna de la llista d’adreces IP falses. Si aquesta segona condició es satisfà aleshores cal enviar un paquet ARP REPLY fals al servidor indicant que la MAC de la IP en qüestió és la del nostre terminal. De fet, no caldria usar la MAC real del nostre equip, tot i que si no es fa així aleshores es podria donar el cas que algun router de la xarxa descarti el paquet.

Un cop iniciats aquests dos threads, YADA inicia la fase de d’enviament massiu de peticions de connexió TCP cap al servidor, usant sempre com a adreces IP origen les adreces de la llista de manera seqüencial. El fil d’execució principal del programa és el que es mostra a continuació:

generar_llavor_aleatoritzacio();
obtenir_mac(mac);
obtenir_ip_xarxa(ip_xarxa, mascara, ip_local);
for(m=0; m<num_tandes ; m++)
{
          generar_ip_falses(llistat_ip_falses);
          ordenar_ip_falses(llistat_ip_falses);
          pid1=esnifar_paquets_ip(llistat_ip_falses);
          pid2=esnifar_paquets_arp(llistat_ip_falses, mac);
          for(n=0; n<NUM_IP_FALSES; n++)
          {
                    enviar_solicitut_conexio_tcp(sock, llistat_ip_falses[n], ip_desti, port_desti);
                    esperar(TEMPS_ESPERA); //1000 -> 1 Segon
          }
          aturar_snifers(pid1, pid2);
}
tancar_aplicacio(sock, argv[1]);

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>