Bastionado, seguridad en sistemas: Consulta DNS con Snort pre { background:#eeeeee; border:1px solid #A6B0BF; font-size:120%; line-height:100%; overflow:auto; padding:10px; color:#000000 } pre:hover { border:1px solid #efefef; } code { font-size:120%; text-align:left; margin:0;padding:0; color: #000000;} .clear { clear:both; overflow:hidden; }

Bienvenido al blog

Bienvenidos al blog de seguridad en sistemas

viernes, 22 de febrero de 2013

Consulta DNS con Snort

Recientemente un usuario del blog pregunto por qué en las reglas de detección de Malware con Snort, cuando se quiere detectar la consulta DNS hacia ciertos dominios sospechosos, se emplean ciertos caracteres y condiciones como la comprobación "byte_test:1, !&, 0xF8, 2;".

Para explicarlo vamos a tomar como ejemplo la siguiente regla VRT para la detección del malware Gauss:
alert udp $HOME_NET any -> any 53 (msg:"BLACKLIST DNS request for known malware domain bestcomputeradvisor.com - Gauss"; flow:to_server; byte_test:1,!&,0xF8,2; content:"|13|bestcomputeradvisor|03|com|00|"; fast_pattern:only; metadata:impact_flag red, policy balanced-ips drop, policy security-ips drop, service dns; reference:url,gauss.crysys.hu/; reference:url,www.securelist.com/en/blog/208193767
En la regla anterior lo único que se esta comprobando es que se trate de una consulta DNS al dominio "bestcomuteradvisor.com". Para evitar falsos positivos se emplean tres restricciones en la creación de la misma:

La primera es comprobar que se trate de un paquete UDP al puerto 53 procedente desde nuestra red interna.

La segunda comprobación radica en el pripio "content" donde se tiene en cuenta el valor hexadecimal de inicio y final de la consulta DNS. Como sabemos un dominio esta separado por "." por ejemplo: "correo.empresa.es". Los paquetes DNS en vez de indicar este punto lo que hacen es indicar mediante un byte (dos números hexadecimales) la cantidad de caracteres que le preceden. 

En el ejemplo vemos que comprueba que haya primero un "13" en hexadecimal, es decir, que la parte del dominio que viene a continuación sean 19 caracteres (13 en hexadecimal). Si contamos el número de caracterers de la cadena "bestcomuteradvisor" tiene efectivamente 19. Luego comprueba que viene 3 caracteres pertenecientes a "com". Ademas comprueba que la consulta DNS termina siempre con el valor "00", indicando que no hay más caracteres en el dominio a consultar. 

La tercera y última, es donde tenemos el famoso "byte_test:1, !&, 0xF8, 2;". ¿Qué es esto del byte_test? No es nada mas ni nada menos que algo que nos permite coger una cantidad de bytes del paquete a partir de una posición y comprobar si coincide con otro valor. 

En "byte_test" lo primero que tenemos que mirar es el último campo, en nuestro caso 2. Esto indica la posición dentro del paquete donde nos situaremos, teniendo en cuenta que siempre el primer byte vale 0. Por tanto el valor 2 del cuarto campo nos indica que se situará en el 3 byte del paquete. Es muy importante entender que en Snort siempre que nos refiramos a posiciones del paquete ya se ha descontado lo empleado por las cabeceras de enlace, red y transporte. Por tanto el 3 byte ya implica haber descontado la cabecera IP y la cabecera UDP, es decir, ya se está trabajando sobre la cabecera DNS. 

Este el motivo por el cual cuando se emplea filtros BPF en herramientas como TCPdump, donde se tiene que hacer referencia al protocolo. Tomando el ejemplo anterior, en vez de buscar el 3 byte, se buscará en el 11 byte a partir del inicio de la cabecera UDP (udp[10]). Si la cabecera UDP de normal son 8 byte, comprende por tanto udp[0-7], el 1 byte del protocolo DNS es udp[8], el segundo udp[9] y el tercero es udp[10]. Por eso indicar en Snort el 3 byte con "2" es lo equivalente a indicar udp[10] en filtros BPF, recordar que en ambos caso se empieza contando siempre desde 0.

Por tato con "byte_test:1, !&, 0xF8, 2;" nos situamos en el 3 byte del protocolo DNS. Luego se debe mirar el primer campo de byte_test, en este caso 1. Esto indica cuantos byte vamos a coger a partir de la posición "2". En este caso su valor es 1 y por tanto un 1 byte es lo que se coge. En pocas palabras vamos a trabajar con el 3 byte del protocolo DNS. Si buscamos en google la cabecera DNS podremos obtener imagenes explicativas, como por ejemplo la obtenida de www.troyjessup.com:


Como vemos el byte que se está comprobando esta formado por lo siguientes campos:
  • Bit 7: QR
  • Bit 6-3: OpCode
  • Bit 2: AA
  • Bit 1: TC
  • Bit 0: RD
Ahora se debe coger el segundo campo del byte_test cuyo valor es "!&", esto implica que con el valor del paquete se va a proceder a realizar una operación binaria "AND negada" sobre el valor indicado en el tercer campo de byte_test: "0xF8". Si se cumple la condición la condición sera correcta, si no se cumple, la condición no será correcta y por tanto no encajar en la regla.

Siempre que se empleen operaciones binarias de tipo AND u OR lo que se busca es que el valor de un campo sea uno en concreto o que al menos algunos de los campos tenga un valor. En nuestro caso lo que se esta buscando es F8, en binario "1111 1000". Por tanto se va a trabajar con los bits del 7 al 3 asignados al campo QR y OpCode. 

Si la comprobación fuera únicamente una operación AND ("&") la regla lo que estaría inentado comprobar es que el campo QR valga 1 y que el campo OpCode valga "1111". Pero al ser un AND negado lo que hace es lo contrario, busca que ambos campos valgan 0. Si se revisa el protocolo DNS ambos campos valen 0 cuando se trata de una consulta DNS (query). Por tanto "byte_test:1, !&, 0xF8, 2;"  lo único que hace es verificar que se trata de una consulta DNS.

Saludos hexadecimales.








No hay comentarios:

Publicar un comentario