El exploit es fácil. Saber qué buscar es lo difícil
PentestingPor el equipo de SwarmAttacker en JolocorpPublicado 8 min de lectura

Esto es lo que nadie nos advirtió sobre las pruebas de penetración automatizadas en un modelo de frontera actual: escribir el exploit resultó ser la parte fácil. Apunta SwarmAttacker a una aplicación web vulnerable y pídele que produzca un comando funcional o una petición preparada, y lo hace. Con limpieza. El problema empieza un paso antes, en la parte que nunca llega a un tutorial: averiguar qué es lo que estás mirando siquiera.
Repasamos cada objetivo que el agente falló, esperando encontrar al modelo trabándose con la sintaxis o echando mano de la técnica equivocada. No encontramos eso. Ni una sola vez se escapó un objetivo porque el agente no supiera escribir el código. Cuando falló, falló por una razón más callada: la idea correcta nunca se formó, o nunca se persiguió lo suficiente.
Clase correcta, técnica equivocada: dónde se atasca el pentesting automatizado
A lo largo de la suite, SwarmAttacker estaba casi siempre en la zona correcta. Nombraba la clase de vulnerabilidad correctamente. Con frecuencia levantaba un punto de apoyo funcional. Sabía que un formulario de login probablemente era inyectable, sabía por dónde fluía la entrada del usuario, conocía la forma del problema. Lo que no siempre lograba era dar con la técnica exacta que el objetivo exigía.
Saber que un objetivo tiene una inyección SQL no es lo mismo que saber que es una ciega, basada en booleanos.
Ese hueco suena pequeño. No lo es. La distancia entre "aquí hay una inyección" y "aquí está la técnica precisa, ciega, bit a bit, que de verdad extrae los datos" es donde vivió una buena parte de nuestros fallos. El exploit estuvo al alcance todo el tiempo. El diagnóstico era el muro.
Donde el muro es más alto: inyección SQL ciega
Si quieres verlo en un solo número, mira la inyección SQL ciega. En toda la suite fue la peor clase a la que se enfrentó el agente, resuelta solo en 1 de 3. Todo lo demás en esa familia, las vulnerabilidades ruidosas y habladoras, el agente casi las barrió.
La razón es exactamente el problema del diagnóstico, afilado hasta una punta. Un fallo de cross-site scripting reflejado te grita: envías una sonda, el payload rebota directamente de vuelta a la página, y la señal es inconfundible. La inyección de comandos es igual: lanzas una sonda y la propia salida del objetivo te dice que funcionó. La SQLi ciega no tiene esa cortesía. No hay nada que leer. La página tiene el mismo aspecto tanto si tu conjetura era correcta como si era errónea. La respuesta hay que reconstruirla una inferencia de verdadero-o-falso cada vez, y ese bucle largo y frágil (preguntar, esperar, interpretar una diferencia tan sutil que podría ser ruido, ajustar, preguntar de nuevo) es precisamente donde el agente perdía el hilo con más frecuencia.
Las señales ruidosas se barren; la ciega no
Las clases de vulnerabilidad con una respuesta obvia son casi perfectas. La inyección SQL ciega, donde no hay nada visible que leer, es el único caso débil y atípico.
¿Por qué la búsqueda web no rescató los fallos difíciles?
El arreglo obvio es darle al agente búsqueda web, y lo hicimos. En estos fallos difíciles rara vez rescató nada. Eso nos sorprendió hasta que miramos por qué. El cuello de botella nunca fue que el modelo no supiera la respuesta: la respuesta a "cómo se explota una inyección ciega basada en booleanos" está escrita en cien sitios. El cuello de botella era que el agente no lograba formular una pregunta lo bastante precisa a partir de su propia salida de herramientas turbia.
La búsqueda recompensa una consulta afilada. "El endpoint de restablecer contraseña devuelve un 200 tanto para tokens válidos como inválidos, y la longitud de la respuesta difiere en dos bytes" es una pregunta que se puede responder. "Algo aquí me da mala espina" no lo es. Cuando el agente ya podía articular el problema, normalmente no necesitaba buscar. Cuando no podía, ninguna cantidad de búsqueda ayudaba, porque no tenía nada afilado que buscar.
La respuesta del enjambre: paciente, luego en paralelo
Si el diagnóstico es la parte difícil, entonces lo peor que puedes hacer es lanzar una multitud de workers sobre un objetivo antes de que nadie lo entienda. Cincuenta sondas en paralelo contra una vulnerabilidad que nadie ha leído correctamente solo producen cincuenta informes confiadamente erróneos. Por eso SwarmAttacker está construido para ir despacio antes de enjambrar.
Durante los primeros ~10 minutos de una ejecución mantiene deliberadamente cada oleada pequeña, solo 4 workers, para poder ver cada sonda al volver, leerla y replanificar a menudo. Esta es la fase de lectura, la parte donde averigua qué está mirando en realidad. Solo cuando tiene pistas reales se despliega más ancho, 6 workers por oleada, para presionar la ventaja, todo dentro de un límite estricto de 40 minutos.
Ese ritmo deja una huella en los tiempos. Los tiempos de resolución son bimodales. Hay un gran pico temprano en la franja baja a media de los diez y pico, las capturas de un solo disparo donde la señal era ruidosa y el agente la leyó de inmediato. Luego un segundo pico, más tardío, pasados los 20 minutos: los objetivos que necesitaron un segundo acto de inferencia cuidadosa y paciente antes de soltar nada. La mediana cae en 15 minutos, y la mayoría de resoluciones entran antes de los 20, pero la cola difícil, los objetivos ciegos, callados y cargados de diagnóstico, llega despacio.
Los tiempos de resolución son bimodales
Un pico temprano en la franja baja a media de los diez y pico para las capturas de un solo disparo, y luego un segundo pico pasados los 20 minutos para los objetivos que necesitan un segundo acto de inferencia cuidadosa.
Lo que esto cambia
Durante años el modelo mental de un atacante automatizado fue una máquina de código: el peligro era que se volviera bueno escribiendo exploits. En un modelo moderno, ese barco zarpó en silencio, y no era la parte interesante. La parte interesante y aún sin resolver es la percepción: leer la salida de las herramientas cuando no sabes qué aspecto se supone que debe tener la señal, y estrechar una vaga sensación de "aquí hay algo" hasta una técnica exacta.
Esa es la apuesta que hace toda la arquitectura. Si quieres los detalles de por qué la estructuramos como oleadas paciente-luego-en-paralelo en lugar de un gran enjambre, está en cómo funciona. Y si quieres el desglose completo clase por clase, incluidas las clases que barrió y las que se resistieron, está todo en los resultados. La versión corta: el modelo ya sabe escribir el exploit. Enseñarle a saber qué está buscando es la frontera de ahora.


