Exploiten ist leicht. Wissen, wonach man sucht, nicht

PentestingVom SwarmAttacker-Team bei JolocorpVeröffentlicht 8 Min Lesezeit

Schwarze Roboter-Hornisse richtet einen roten Laser auf einen Punkt eines weiten Radargitters: das Signal beim Pentesting finden

Vor einer Sache hat uns beim automatisierten Penetrationstesten auf einem aktuellen Frontier-Modell niemand gewarnt: den Exploit zu schreiben, stellte sich als der einfache Teil heraus. Setz SwarmAttacker auf eine verwundbare Web-App an und bitte es, einen funktionierenden Befehl oder eine präparierte Anfrage zu erzeugen, und es tut es. Sauber. Der Ärger beginnt einen Schritt früher, in dem Teil, der es nie in ein Tutorial schafft: herauszufinden, was du überhaupt vor dir hast.

Wir sind jedes Ziel durchgegangen, das der Agent verfehlt hat, und erwarteten, das Modell dabei zu ertappen, wie es an der Syntax scheitert oder zur falschen Technik greift. Das haben wir nicht gefunden. Kein einziges Mal ging ein Ziel verloren, weil der Agent den Code nicht schreiben konnte. Wenn er scheiterte, scheiterte er aus einem leiseren Grund: die richtige Idee wurde nie gebildet oder nie weit genug verfolgt.

Richtige Klasse, falsche Technik: wo automatisiertes Pentesten stockt

Über die ganze Suite hinweg war SwarmAttacker fast immer im richtigen Bereich. Es benannte die Schwachstellenklasse korrekt. Es baute häufig einen funktionierenden Fuß in der Tür auf. Es wusste, dass ein Login-Formular vermutlich injizierbar war, es wusste, wohin Benutzereingaben flossen, es kannte die Form des Problems. Was es nicht immer konnte, war, auf die genaue Technik zu kommen, die das Ziel verlangte.

Zu wissen, dass ein Ziel eine SQL-Injection hat, ist nicht dasselbe wie zu wissen, dass es eine blinde, boolesche ist.

Diese Lücke klingt klein. Sie ist es nicht. Der Abstand zwischen „hier ist eine Injection“ und „hier ist die präzise, blinde, Ein-Bit-nach-dem-anderen- Technik, die die Daten tatsächlich extrahiert“ ist der Ort, an dem ein echter Teil unserer Fehlschläge wohnte. Der Exploit war die ganze Zeit in Reichweite. Die Diagnose war die Wand.

Wo die Wand am höchsten ist: blinde SQL-Injection

Wenn du das in einer einzigen Zahl sehen willst, schau dir die blinde SQL-Injection an. Über die ganze Suite hinweg war es die schlechteste Klasse, mit der es der Agent zu tun hatte, gelöst nur 1 von 3. Alles andere in dieser Familie, die lauten, gesprächigen Schwachstellen, fegte der Agent nahezu weg.

Der Grund ist genau das Diagnoseproblem, auf die Spitze getrieben. Ein reflektiertes Cross-Site-Scripting-Bug schreit dich an: Du sendest eine Sonde, der Payload springt direkt zurück in die Seite, und das Signal ist unverkennbar. Command Injection ist dasselbe, lass eine Sonde laufen und die eigene Ausgabe des Ziels sagt dir, dass es funktioniert hat. Blinde SQLi hat keine solche Höflichkeit. Es gibt nichts zu lesen. Die Seite sieht identisch aus, ob deine Vermutung richtig oder falsch war. Die Antwort muss eine Wahr-oder-falsch-Inferenz nach der anderen wiederaufgebaut werden, und diese lange, brüchige Schleife, fragen, warten, einen so subtilen Unterschied deuten, dass er Rauschen sein könnte, anpassen, wieder fragen, ist genau der Ort, an dem der Agent am häufigsten den Faden verlor.

Laute Signale werden weggefegt; das blinde nicht

Schwachstellenklassen mit einer offensichtlichen Antwort sind nahezu perfekt. Die blinde SQL-Injection, wo es nichts Sichtbares zu lesen gibt, ist der einzige schwache Ausreißer.

XSS
22/23
IDOR
14/14
SSTI
12/13
Command Inj.
11/11
Blinde SQLi
1/3
GelöstFehlgeschlagen

Warum hat die Websuche die schweren Fehlschläge nicht gerettet?

Die naheliegende Lösung ist, dem Agenten Websuche zu geben, und das haben wir getan. Bei diesen schweren Fehlschlägen rettete sie selten etwas. Das überraschte uns, bis wir uns ansahen, warum. Der Engpass war nie, dass das Modell die Antwort nicht kannte, die Antwort auf „wie exploitet man eine boolesche, blinde Injection“ steht an hundert Stellen geschrieben. Der Engpass war, dass der Agent aus seinem eigenen trüben Tool-Output keine präzise genug formulierte Frage bilden konnte.

Suche belohnt eine scharfe Anfrage. „Der Passwort-Reset-Endpunkt gibt für gültige und ungültige Tokens eine 200 zurück, und die Antwortlänge unterscheidet sich um zwei Bytes“ ist eine Frage, die du beantworten kannst. „Irgendwas fühlt sich hier falsch an“ ist es nicht. Wenn der Agent das Problem bereits formulieren konnte, musste er meist nicht suchen. Wenn er es nicht konnte, half kein noch so großes Suchen, weil er nichts Scharfes hatte, wonach er suchen konnte.

Die Antwort des Swarms: erst geduldig, dann parallel

Wenn die Diagnose der schwere Teil ist, dann ist das Schlimmste, was du tun kannst, eine Menge Worker auf ein Ziel loszulassen, bevor es irgendjemand verstanden hat. Fünfzig parallele Sonden gegen eine Schwachstelle, die niemand richtig gelesen hat, produzieren nur fünfzig selbstsicher falsche Berichte. Also ist SwarmAttacker so gebaut, dass es langsam wird, bevor es schwärmt.

In den ersten ~10 Minuten eines Runs hält es jede Welle bewusst klein, nur 4 Worker, damit es jede Sonde zurückkommen sehen, sie lesen und oft neu planen kann. Das ist die Lesephase, der Teil, in dem es herausarbeitet, was es eigentlich vor sich hat. Erst wenn es echte Anhaltspunkte hat, fächert es breiter auf, 6 Worker pro Welle, um den Vorteil auszunutzen, alles innerhalb eines harten Limits von 40 Minuten.

Dieser Rhythmus hinterlässt einen Fingerabdruck im Timing. Die Lösungszeiten sind bimodal. Es gibt einen großen frühen Buckel im niedrigen bis mittleren Zehnerbereich, die Ein-Schuss-Erfolge, bei denen das Signal laut war und der Agent es sofort richtig las. Dann ein zweiter, späterer Buckel jenseits von 20 Minuten: die Ziele, die einen zweiten Akt sorgfältiger, geduldiger Inferenz brauchten, bevor sie etwas hergaben. Der Median liegt bei 15 Minuten, und die meisten Lösungen sind vor 20 durch, aber der schwere Schwanz, die blinden, stillen, diagnoselastigen Ziele, kommt langsam herein.

Lösungszeiten sind bimodal

Ein früher Buckel im niedrigen bis mittleren Zehnerbereich für Ein-Schuss-Erfolge, dann ein zweiter Buckel jenseits von 20 Minuten für die Ziele, die einen zweiten Akt sorgfältiger Inferenz brauchen.

0
10
20
30
Minuten
Median 15 MinLimit 40 Min
0
Fehlschläge durch einen schlechten Exploit
1 / 3
blinde SQLi, die schlechteste Klasse
15 min
mediane Lösungszeit

Was das verändert

Jahrelang war das mentale Modell eines automatisierten Angreifers eine Code-Maschine: Die Gefahr war, dass er gut im Schreiben von Exploits würde. Auf einem modernen Modell ist dieses Schiff still davongesegelt, und es war gar nicht der interessante Teil. Der interessante, noch ungelöste Teil ist die Wahrnehmung, Tool-Output zu lesen, wenn du nicht weißt, wie das Signal aussehen soll, und ein vages Gefühl von „hier ist etwas“ auf eine genaue Technik einzugrenzen.

Das ist die Wette, die die ganze Architektur eingeht. Wenn du die Details dazu willst, warum wir es als geduldig-dann-parallele Wellen statt als einen großen Schwarm strukturiert haben, findest du das in wie es funktioniert. Und wenn du die vollständige Aufschlüsselung Klasse für Klasse willst, inklusive der Klassen, die es wegfegte, und derer, die zurückschlugen, steht das alles in den Ergebnissen. Die Kurzfassung: Das Modell kann den Exploit bereits schreiben. Ihm beizubringen, zu wissen, wonach es sucht, ist jetzt die Grenze.