C-Funktion aufrufen, ohne sie zu benennen
Calling a function in C without naming it
Ein Student und sein Freund wollten eine einzige Lösung finden, die jede Programmieraufgabe im automatischen Bewertungssystem ihrer Schule löst. Das System prüft, welche Funktionen erlaubt sind, und blockiert execve. Also umgingen sie ASLR, indem sie den Offset zwischen printf und mmap ausnutzten, eine ausführbare Seite mit mmap anlegten und dort handgeschriebenen x86-Assemblercode platzierten, der jeden Syscall ausführt. So erlangten sie Shell-Zugriff und meldeten die Sicherheitslücke.
In C ist Unsicherheit ein Feature, also können wir einfach Unions verwenden.
- ashdnazg
Unsere Universität war weit weniger vorsichtig und ließ unsere Abgaben einfach im selben Netzwerk wie alles andere laufen, allerdings unter einem Benutzer mit kaum Berechtigungen.
Als die automatischen Tests meine Abgabe zum Absturz brachten, nutzte ich einfach `system`, um die Testeingabe in mein Home-Verzeichnis zu dumpen. Ich vergaß jedoch, die Berechtigungen zu setzen, sodass ich nicht wirklich darauf zugreifen konnte! Nach ein paar weiteren Abgaben mit zusätzlichen chmods, bei denen ich jedes Mal etwas anderes vermasselte, gelang es mir, meinen Bug zu reproduzieren, ihn zu beheben, erneut abzugeben und alle (oder die meisten) Beweise zu beseitigen.
- Kevin_Flynn
Da wir wissen, dass unser Code mit ASan kompiliert wird, entschieden wir uns, den Offset zwischen printf, einer immer erlaubten Funktion, und mmap, einer Funktion, die uns beliebige Assembly-Code-Ausführung ermöglicht, durchsickern zu lassen. So können wir die Überprüfungen der Schule umgehen und jeden Syscall aufrufen, in unserem Fall execve, um Shell-Zugriff zu erhalten.
Wir haben nicht weiter untersucht und das mögliche Problem einfach der Schule gemeldet.
Ich sehe keinen trivialen Weg, das zu patchen.
Der Fehler scheint im Abgabesystem zu liegen.
Das Abgabesystem könnte deinen Code gegen eine Trampolin-Bibliothek bauen/neu linken, bei der der Rumpf jeder zu verbietenden Funktion durch Fehlerberichterstattung und Abbruch ersetzt wird. In deinem Beispiel würde es Folgendes abfangen:
char *code =
notmmap.fn(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
und dich daran hindern, das PROT_EXEC-Flag während der Ausführungsphase der Abgabevalidierung zu verwenden.
Laut KI gilt unter Linux: "... ein seccomp-BPF-Filter, der auf jeden Prozess angewendet wird, bevor er das Programm ausführt. Er kann das prot-Argument von mmap inspizieren und EPERM zurückgeben, wenn PROT_EXEC gesetzt ist."
Zusätzlich gilt unter Linux: "systemd bietet MemoryDenyWriteExecute=yes für Dienste. Das ist weniger restriktiv als jedes ausführbare Mapping zu verbieten: Es zielt auf beschreibbare+ausführbare Mappings und verwandte Wege ab, Speicher ausführbar zu machen."
( WENN ... ich den Artikel richtig gelesen habe )
ps. Reiche die vorgeschlagenen Lösungen bei deinem Abteilungsleiter oder einer anderen Autoritätsperson ein, die dir vielleicht etwas zukommen lässt, damit deine sta […]
- PeterWhittaker
Klingt, als müsste die Schule die Dinge in eine seccomp-Denylist einpacken. Potenziell nicht trivial, aber potenziell interessant.