
Biblioteca de Python para Turbo Intruder que añade soporte de posición de payload y tipos de ataque Sniper/Clusterbomb/Pitchfork con generación de pruebas basada en etiquetas para fuzzing HTTP.

Haptyc es una librería de Python construida para agregar soporte de posiciones de carga útil y tipos de ataque Sniper/Clusterbomb/Batteringram/Pitchfork en Turbo Intruder. Si bien Haptyc logra estos objetivos bastante bien, también introduce una forma más simple de expresar secuencias de prueba en general. Aunque esta librería fue diseñada para Turbo Intruder, no tiene dependencias estrictas con Turbo Intruder y se puede usar en cualquier lugar donde se requiera generación de pruebas en un contexto de Python. Desafortunadamente, en este momento, dado que Haptyc fue creado para un intérprete de Jython, solo es compatible con Python 2.7 (sin embargo, cambios futuros solucionarán esto).
Las etiquetas de Haptyc son etiquetas que un evaluador puede usar para anotar una carga útil de entrada original. Un evaluador puede usar múltiples etiquetas para rodear piezas clave de datos en una solicitud HTTP y envolverlas como una carga útil posicional. Cuando se generan pruebas, Haptyc analiza todas las etiquetas en la carga útil original y genera pruebas de acuerdo con las funciones asociadas a los nombres de las etiquetas. Cuando Haptyc evalúa una etiqueta de Haptyc, ejecuta la función de etiqueta asociada (esto se llama una Transformación de Haptyc) para una carga útil de prueba que se coloca en la posición de la etiqueta correspondiente en la solicitud. Cada función de etiqueta recibe un argumento data y un argumento state. El argumento data puede contener los datos internos de la etiqueta o puede contener alguna otra secuencia de carga útil de prueba. El argumento state es un objeto de estado asociado a la etiqueta donde se puede almacenar el estado entre iteraciones de prueba. Revisemos un ejemplo.
Carga útil original:
GET /animal/[+GuessAnimal]dog[+end] HTTP/1.1
Clase Haptyc y Transformación Haptyc:
from haptyc import *
original = "GET /animal/[+GuessAnimal]dog[+end] HTTP/1.1"
class TestLogic(Transform):
@ApplyList(["snake","cat","owl","lion"])
def test_GuessAnimal(self, data, state):
return data + "?original=" + self.inner() + "&attempt=" + str(state.iter)
TestFactory = TestLogic(original)
for test in TestFactory:
print(test)
Pruebas generadas:
GET /animal/snake?original=dog&attempt=0 HTTP/1.1
GET /animal/cat?original=dog&attempt=1 HTTP/1.1
GET /animal/owl?original=dog&attempt=2 HTTP/1.1
GET /animal/lion?original=dog&attempt=3 HTTP/1.1
En el ejemplo anterior vemos cómo se pueden expresar pruebas de manera sencilla usando Haptyc. Primero se importa la librería Haptyc. Segundo, hemos definido los datos originales con nuestras anotaciones de etiquetas Haptyc (GuessAnimal). Luego, se define la clase TestLogic que extiende la clase Transform. Dentro de esta clase, cada método que comience con test_ se registrará como una etiqueta Haptyc para su evaluación en la carga útil original. Usamos un decorador de lógica para aplicar la lógica de estado para esta transformación Haptyc. En este caso, usamos el decorador @ApplyList(list) para indicarle a Haptyc que genere una prueba para cada elemento de la lista especificada y coloque ese elemento en la transformación Haptyc como el argumento data. Dentro de la transformación, devolvemos una versión mutada de data para insertarla de nuevo en la posición de la etiqueta. En este caso, la mutación es el elemento de la lista como data concatenado con los datos rodeados por la etiqueta (dog) y luego concatenado con el valor iter en el objeto state. Finalmente, el resto del código Python muestra cómo se crea el objeto TestFactory y se generan todas las pruebas en un bucle for. Este es un ejemplo de un ataque estándar de tipo sniper que apunta a una única posición de carga útil. A continuación, veamos otros tipos de ataques.
Carga útil original:
GET /animal?type=[%type]dog[%end]&name=[%name]fido[%end] HTTP/1.1
Clase Haptyc y Transformación Haptyc:
from haptyc import *
original = "GET /animal?type=[%type]dog[%end]&name=[%name]fido[%end] HTTP/1.1"
class TestLogic(Transform):
@ApplyList("snake","cat","owl","lion")
def test_type(self, data, state):
return data
@ApplyList("Frank", "Lisa", "Jin", "Tooth")
def test_name(self, data, state):
return data
TestFactory = TestLogic(original)
for test in TestFactory:
print(test)
Pruebas generadas:
GET /animal?type=snake&name=Frank HTTP/1.1
GET /animal?type=snake&name=Lisa HTTP/1.1
GET /animal?type=snake&name=Jin HTTP/1.1
GET /animal?type=snake&name=Tooth HTTP/1.1
GET /animal?type=cat&name=Frank HTTP/1.1
GET /animal?type=cat&name=Lisa HTTP/1.1
GET /animal?type=cat&name=Jin HTTP/1.1
GET /animal?type=cat&name=Tooth HTTP/1.1
GET /animal?type=owl&name=Frank HTTP/1.1
GET /animal?type=owl&name=Lisa HTTP/1.1
GET /animal?type=owl&name=Jin HTTP/1.1
GET /animal?type=owl&name=Tooth HTTP/1.1
GET /animal?type=lion&name=Frank HTTP/1.1
GET /animal?type=lion&name=Lisa HTTP/1.1
GET /animal?type=lion&name=Jin HTTP/1.1
GET /animal?type=lion&name=Tooth HTTP/1.1
El Ejemplo 1 mostró cómo evaluar transformaciones al estilo sniper usando la anotación '+' en la etiqueta [+tag][+end]. El Ejemplo 2 muestra cómo podemos usar 2 transformaciones/posiciones para realizar un ataque de estilo clusterbomb. Como se puede ver, usamos dos etiquetas de transformación separadas llamadas [%type][%end] y [%name][%end]. El signo '%' le indica a Haptyc que evalúe estas transformaciones en estilo clusterbomb: por cada carga útil en la primera transformación, crea una prueba con la carga útil de la segunda transformación. El número de pruebas es el producto de la cantidad de pruebas de cada transformación involucrada.
Usando exactamente el mismo código Python, podemos cambiar el estilo de ataque de clusterbomb a pitchfork cambiando '%' por '#'. Los ataques de estilo pitchfork colocarán las cargas útiles de posición en paralelo. El número de pruebas es la menor cantidad de pruebas de todas las transformaciones involucradas.
Carga útil original:
GET /animal?type=[#type]dog[#end]&name=[#name]fido[#end] HTTP/1.1
Pruebas generadas:
GET /animal?type=snake&name=Frank HTTP/1.1
GET /animal?type=cat&name=Lisa HTTP/1.1
GET /animal?type=owl&name=Jin HTTP/1.1
GET /animal?type=lion&name=Tooth HTTP/1.1
Carga útil original:
GET /animal?type=dog&id=[+idor]0[+end]&process=[@randbool]False[@end] HTTP/1.1
Clase Haptyc y Transformación Haptyc:
from haptyc import *
import random
original = "GET /animal?type=dog&id=[+idor]0[+end]&process=[@randbool]False[@end] HTTP/1.1"
class TestLogic(Transform):
@ApplyIteration(10)
def test_idor(self, data, state):
return str(state.iter)
def per_randbool(self, data):
return random.choice(["True", "False"])
TestFactory = TestLogic(original)
for test in TestFactory:
print(test)
Pruebas generadas:
GET /animal?type=dog&id=0&process=False HTTP/1.1
GET /animal?type=dog&id=1&process=True HTTP/1.1
GET /animal?type=dog&id=2&process=False HTTP/1.1
GET /animal?type=dog&id=3&process=True HTTP/1.1
GET /animal?type=dog&id=4&process=False HTTP/1.1
GET /animal?type=dog&id=5&process=True HTTP/1.1
GET /animal?type=dog&id=6&process=False HTTP/1.1
GET /animal?type=dog&id=7&process=True HTTP/1.1
GET /animal?type=dog&id=8&process=False HTTP/1.1
GET /animal?type=dog&id=9&process=False HTTP/1.1