
Fuzzer de DOM
Escrito y mantenido por Ivan Fratric, [email protected]
Copyright 2017 Google Inc. Todos los derechos reservados.
Licenciado bajo la Apache License, Versión 2.0 (la "Licencia"); no puede utilizar este archivo excepto en cumplimiento de la Licencia. Puede obtener una copia de la Licencia en
http://www.apache.org/licenses/LICENSE-2.0
Salvo que lo exija la ley aplicable o se haya acordado por escrito, el software distribuido bajo la Licencia se distribuye "TAL CUAL", SIN GARANTÍAS NI CONDICIONES DE NINGÚN TIPO, ya sean expresas o implícitas. Consulte la Licencia para conocer el lenguaje específico que rige los permisos y las limitaciones bajo la Licencia.
Para ver la información de uso, ejecute el siguiente comando:
python3 generator.py --help
Para generar una única muestra .html, ejecute:
python generator.py --file <output file>
Para generar una única muestra .html usando una plantilla que haya escrito:
python generator.py --file <output file> --template <your custom template file>
Para generar varias muestras con una sola llamada, ejecute:
python generator.py --output_dir <output directory> --no_of_files <number of output files>
Las muestras generadas se colocarán en el directorio especificado y se nombrarán como fuzz-<number>.html, por ejemplo, fuzz-00001.html, fuzz-00002.html, etc. La generación de varias muestras es más rápida porque los archivos de gramática de entrada solo necesitan cargarse y analizarse una vez.
generator.py contiene el script principal. Utiliza grammar.py como biblioteca y contiene código auxiliar adicional para el fuzzing de DOM.
grammar.py contiene el motor de generación, que es en su mayoría independiente de la aplicación y, por lo tanto, puede usarse en otros fuzzers basados en generación (es decir, no DOM). Como puede usarse como biblioteca, su uso se describe en una sección separada más abajo.
Los archivos .txt contienen definiciones de gramática. Hay 3 archivos principales, html.txt, css.txt y js.txt, que contienen las gramáticas de HTML, CSS y JavaScript, respectivamente. Estos archivos de gramática raíz pueden incluir contenido de otros archivos.
Para usar el motor de generación con una gramática personalizada, puede utilizar el siguiente código Python:
from grammar import Grammar
my_grammar = Grammar()
my_grammar.parse_from_file('input_file.txt')
result_string = my_grammar.generate_symbol('symbol_name')
Las siguientes secciones describen la sintaxis de los archivos de gramática.
Domato se basa en un motor que, dada una gramática libre de contexto en un formato simple especificado a continuación, genera muestras a partir de esa gramática.
Una gramática se describe como un conjunto de reglas en el siguiente formato básico:
<symbol> = a mix of constants and <other_symbol>s
Cada regla de gramática contiene un lado izquierdo y un lado derecho separados por el carácter igual. El lado izquierdo contiene un símbolo, mientras que el lado derecho contiene los detalles sobre cómo puede expandirse ese símbolo. Al expandir un símbolo, todos los símbolos del lado derecho se expanden recursivamente, mientras que todo lo que no es un símbolo simplemente se copia a la salida. Tenga en cuenta que una sola regla no puede abarcar varias líneas del archivo de entrada.
Considere el siguiente ejemplo simplificado de una parte de la gramática CSS:
<cssrule> = <selector> { <declaration> }
<selector> = a
<selector> = b
<declaration> = width:100%
Si indicamos al motor de gramática que analice esa gramática y genere 'cssrule', podríamos obtener:
a { width:100% }
o
b { width:100% }
Tenga en cuenta que hay dos reglas para el símbolo 'selector'. En tales casos, cuando se le pide al generador que genere un 'selector', seleccionará la regla a usar al azar. También es posible especificar la probabilidad de la regla usando el atributo 'p', por ejemplo:
<selector p=0.9> = a
<selector p=0.1> = b
En este caso, la cadena 'a' se generaría con más frecuencia que 'b'.
Además de la probabilidad, hay otros atributos que pueden aplicarse a los símbolos. Estos se enumeran en una sección separada.
Considere otro ejemplo para generar muestras html:
<html> = <lt>html<gt><head><body><lt>/html<gt>
<head> = <lt>head<gt>...<lt>/head<gt>
<body> = <lt>body<gt>...<lt>/body<gt>
Tenga en cuenta que, dado que '<' y '>' tienen un significado especial en la sintaxis de la gramática, aquí usamos <lt> y <gt> en su lugar. Estos símbolos están integrados y no necesitan ser definidos por el usuario. En una sección separada se proporciona una lista de todos los símbolos integrados.
Para generar código de lenguaje de programación se puede usar una sintaxis similar, pero hay un par de diferencias. Cada línea de la gramática del lenguaje de programación corresponderá a una línea de la salida. Debido a eso, la sintaxis de la gramática será más libre para permitir expresar construcciones en varios lenguajes de programación. En segundo lugar, cuando se genera una línea, además de emitir la línea, pueden crearse una o más variables, y esas variables pueden reutilizarse al generar otras líneas. De nuevo, echemos un vistazo al ejemplo simplificado:
!varformat fuzzvar%05d
!lineguard try { <line> } catch(e) {}
!begin lines
<new element> = document.getElementById("<string min=97 max=122>");
<element>.doSomething();
!end lines
Si indicamos al motor que genere 5 líneas, podríamos obtener algo como:
try { var00001 = document.getElementById("hw"); } catch(e) {}
try { var00001.doSomething(); } catch(e) {}
try { var00002 = document.getElementById("feezcqbndf"); } catch(e) {}
try { var00002.doSomething(); } catch(e) {}
try { var00001.doSomething(); } catch(e) {}
Tenga en cuenta que
<new element> en lugar de <element>. Esto le indica al generador que cree una nueva variable de tipo 'element' en lugar de generar el símbolo 'element'.<string> es uno de los símbolos integrados, por lo que no es necesario definirlo.Todo lo que esté después del primer carácter '#' en la línea se considera un comentario, por ejemplo:
#This is a comment
La sintaxis de la gramática tiene una forma de indicar al fuzzer qué reglas no son recursivas y pueden usarse de forma segura incluso si se ha alcanzado el nivel máximo de recursión. Esto se hace con el atributo ‘nonrecursive’. A continuación se muestra un ejemplo.
!max_recursion 10
<test root=true> = <foobar>
<foobar> = foo<foobar>
<foobar nonrecursive> = bar