
Klassischer stack-basierter Pufferüberlauf im Savant Web Server 3.1, der die Remote-Speicherkorruption aus den frühen 2000er Jahren durch eine präparierte HTTP-Anfrage demonstriert.
Klassischer Stack-basierter Pufferüberlauf im Savant Web Server 3.1, der eine Fernspeicherverfälschung aus den frühen 2000ern durch eine präparierte HTTP-Anfrage demonstriert (eine Sicherheitslücke von 2002, die von einem Anfänger mehr verlangt als die meisten Pufferüberlauf-CVEs aus dem Jahr 2025).
Dieses Repository ist Teil des Materials, das ich beim Unterrichten von Memory Corruption Exploitation verwende (neben meiner regulären Arbeit unterrichte ich auch in verschiedenen Cybersicherheitskursen, wo ich helfe, die nächste Generation von Reverse Engineers auszubilden). Wenn ich im Unterricht Stack-basierte Pufferüberläufe behandle, arbeite ich mit realen Fällen statt mit Beispielen aus Spielzeug-Land, und dieser CVE ist einer, den ich speziell dann wieder hervorkrame, wenn ich Studenten herausfordern möchte, die bereits etwas Erfahrung mit grundlegenden EIP-Überschreibungen haben.
Der Grund ist, dass die Jahreszahl in einer CVE-Kennung nichts darüber aussagt, wie schwierig die Ausnutzung ist. Die meisten Studenten nehmen an, dass ältere CVEs einfacher sein müssen – ein einfacher Overflow, ein JMP ESP, fertig. Dieser hier beweist das Gegenteil. Einige CVEs, die ich aus dem Jahr 2025 unterrichte, sind grundlegend einfacher als dieser, weil die Sicherheitslückenklasse simpler ist oder die Einschränkungen geringer sind. CVE-2002-1120 erfordert das Verständnis von Dingen, die einige moderne Exploits nicht verlangen: warum bestimmte Opcodes in bestimmten Teilen der Anfrage nicht verwendet werden können, wie man einen bedingten Sprung konstruiert, der immer ausgelöst wird, wenn der unbedingte blockiert ist, wie man Shellcode ausliefert, wenn er nicht dort hinpasst, wo man ihn normalerweise platzieren würde, und wie ein Egghunter ein Platzproblem löst, das den Exploit sonst unmöglich machen würde.
Es ist der CVE, den ich zuweise, wenn ich sehen möchte, ob jemand wirklich versteht, was er tut.
Diese Sicherheitslücke betrifft Savant 3.1, einen kostenlosen Windows-HTTP-Server aus dem Jahr 2002. Was sie 2025 noch studierenswert macht, ist nicht das Alter, sondern die Kombination von Einschränkungen, die sie einführt, und die Techniken, die zur Umgehung erforderlich sind:
Jede dieser Einschränkungen ist eine Lektion für sich.
Savant ist ein kostenloser Open-Source-Windows-HTTP-Server, der ursprünglich dazu entwickelt wurde, jeden Desktop-Computer in einen Webserver zu verwandeln. Er lauscht auf TCP-Port 80 und verarbeitet standardmäßige HTTP-GET-Anfragen. Der Überlauf tritt im Handler auf, der den URI-Pfad in einen Stack-Puffer fester Größe kopiert, ohne dessen Länge zu validieren.
Wichtige technische Details:
Savant verarbeitet eingehende HTTP-GET-Anfragen und kopiert den URI-Pfad in einen Stack-Puffer fester Größe, ohne dessen Länge zu prüfen. Eine vereinfachte Version der verwundbaren Logik sieht so aus:
char uri_buffer[270];
strcpy(uri_buffer, uri_path);
Senden einer GET-Anfrage mit einem URI von ungefähr 271 Bytes überschreibt die gespeicherte Rücksprungadresse auf dem Stack. Der Überlauf ist begrenzt: Das Senden von deutlich mehr führt zu einem Absturz, bei dem EIP nicht mehr kontrolliert wird, daher ist das nutzbare Fenster schmal.
Die Ausnutzung ist komplexer als eine standardmäßige EIP-Überschreibung aufgrund zweier zusätzlicher Eigenschaften des Servers: Das HTTP-Methodenfeld wird ebenfalls in den Speicher kopiert und ausgeführt, und der Body der HTTP-Anfrage wird in einem separaten Heap-Bereich anstelle des Stacks gespeichert (beide Eigenschaften werden zu wesentlichen Teilen der Exploit-Kette).
Der Absturz kann durch Senden einer GET-Anfrage mit einem ausreichend langen URI reproduziert werden. Es ist keine Authentifizierung erforderlich. Beispiel mit Python:
import socket
HOST = '127.0.0.1'
PORT = 80
payload = b"A" * 271
request = (
b"GET /" + payload + b" HTTP/1.1\r\n"
b"Host: 127.0.0.1\r\n"
b"Connection: close\r\n"
b"\r\n"
)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.send(request)
s.close()
Bei Ausführung unter einem Debugger zeigt der Absturz, dass EIP mit vom Benutzer kontrollierten Daten überschrieben wurde:
EIP = 41414141
was bestätigt, dass die gespeicherte Rücksprungadresse durch den Überlauf beschädigt wurde.
Das Ziel dieses Repositorys ist es nicht nur, den Absturz zu demonstrieren, sondern den gesamten Ausnutzungsprozess Schritt für Schritt durchzugehen, einschließlich jeder Einschränkung, die diesen Fall schwieriger macht als eine standardmäßige EIP-Überschreibung, und jeder Entscheidung, die getroffen wurde, um diese zu umgehen.
Um die Haupt-README übersichtlich zu halten, befinden sich die detaillierten Ausnutzungsnotizen, Skripte und Debugger-Schritte im Ordner Vulnerability 📂 dieses Repositorys.
Dort finden Sie den vollständigen Workflow, der zur Ausnutzung dieser CVE verwendet wurde, einschließlich: