
CTF pwn challenge writeup, der CVE-2021-4034 (pkexec) mittels Heap-Manipulation ausnutzt, mit Ghidra-basiertem Reverse Engineering und einer benutzerdefinierten shelly.so-Hilfsbinärdatei.
Dies ist eine CTF-Pwn-Challenge, die ich in C geschrieben habe und die vom Benutzer erfordert, die CVE-2021-4034-Schwachstelle auszunutzen. Die Spieler erhalten 2 Binärdateien im challenge-Verzeichnis in diesem Repository. Die chal-Binärdatei implementiert die CTF-Challenge und shelly.so ist eine Hilfsbinärdatei.
Zum Zeitpunkt der Erstellung dieses Writeups ist das Dockerfile noch nicht vollständig. Das Dockerfile ist erforderlich, um diese Challenge während eines Live-CTFs bereitzustellen, aber nicht lokal: Sie können diese Challenge dennoch lokal emulieren, indem Sie die Benutzerberechtigungen einrichten und die anfälligen Pakete wie folgt installieren:
libpolkit-gobject-1-0=0.105-26ubuntu1 libpolkit-agent-1-0=0.105-26ubuntu1 policykit-1=0.105-26ubuntu1.flag.txt-Datei, die root:root gehört, im aktuellen Verzeichnis.challenge-Ordner in das aktuelle Verzeichnis herunter.chal als unprivilegierter Benutzer aus.Das Ausführen der chal-Binärdatei gibt uns eine vage Vorstellung davon, was diese Binärdatei tut:```
WELCOME TO THE HUB CTRL+ALT+DELICIOUS
We're not just a sandwich hub. We are the beacon of flavors, serving a symphony in every byte
Spielt man mit der Eingabegröße in der `Add`-Funktion und den Indizes der `Cancel`-Funktionen herum, erhält man nichts Besonderes (kein Überlauf oder Segmentierungsfehler). Dennoch ein paar interessante Dinge:
- Es scheint, als ob die Bestellungen in einer Liste (vielleicht einer verketteten Liste) abgelegt werden und sie 0-indexiert sind?
- Es gibt diese `Bestellnummer: 0x7ffde93681f0`, die offenbar eine Speicherstelle auf dem Stack ausgibt?
- Außerdem erstellt das Programm ein Verzeichnis mit unserem Eingabenamen zusammen mit 3 ausführbaren Dateien, von denen eine die uns gegebene Hilfsbinärdatei ist:```sh
peasant@Tin-VM:~/Desktop$ ls
chal chal.c Dockerfile shelly.so solve.py tin
peasant@Tin-VM:~/Desktop$ ls -l tin/
total 28
-rwxrwx--- 1 peasant vboxsf 5 Feb 4 14:33 notes
-rwxrwx--- 1 peasant vboxsf 20 Feb 4 14:33 recipe
-rwxr-x--- 1 peasant vboxsf 16488 Feb 4 14:33 shelly.so
peasant@Tin-VM:~/Desktop$ cat tin/notes
0000
peasant@Tin-VM:~/Desktop$ cat tin/recipe
aaaa
bbbb
cccc
dddc
Die ausführbaren Dateien enthalten unsere Eingabe.
Sie können mit den anderen Funktionen herumspielen und hoffen, auf einige Fehler zu stoßen (was wahrscheinlich ist), aber ich komme direkt zur Sache und öffne das Programm in Ghidra.
Beim Vergleichen der Zeichenfolgen, die während der Programmausführung erscheinen, und der Zeichenfolgen, die in Ghidra vorhanden sind, können wir einige der FUN_*-Funktionen in vertraute Namen umbenennen:```C
undefined8 main(void)
{ int iVar1; size_t sVar2; undefined2 *puVar3; long in_FS_OFFSET; int opt; int local_1c; char *local_18; long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28); local_18 = "/recipe"; print("WELCOME TO THE HUB CTRL+ALT+DELICIOUS\n"); print( "We're not just a sandwich hub. We are the beacon of flavors, serving a symphony in every by te\n\n" ); while( true ) { print("1. ENTER THE HUB\n"); print("2. QUIT\n"); __isoc99_scanf(&DAT_001030c5,&opt); getc(stdin); if (opt != 1) break; printf("Order number: %p\n",&local_18); print("Enter your name: "); __isoc99_scanf(&DAT_0010334f,&DAT_00105120); sVar2 = strlen(&DAT_00105120); puVar3 = (undefined2 *)malloc(sVar2 + 2); DAT_00105100 = puVar3; *puVar3 = 0x2f2e; *(undefined *)(puVar3 + 1) = 0; strcpy((char *)(DAT_00105100 + 1),&DAT_00105120); iVar1 = FUN_001022f0(DAT_00105100,&DAT_00105060); if (iVar1 == -1) { mkdir((char *)DAT_00105100,0x1c0); } DAT_00105140 = 0; order_cnt = 0; for (local_1c = 0; local_1c < 10; local_1c = local_1c + 1) { *(undefined8 *)(&ptr_array + (long)local_1c * 8) = 0; } main_menu(); } print("Come again :)\n");
Das `printf("Order number: %p\n",&local_18);` **gibt einen Speicherort einer lokalen Variable auf dem Stack aus.**
Eine schnelle Überprüfung in gdb zeigt uns, dass die geleakte Adresse die Adresse des Zeigers auf die konstante Zeichenkette `/recipe` ist:```gdb
...
Order number: 0x7fffffffdfc0
...
gef➤ x/gx 0x7fffffffdfc0
0x7fffffffdfc0: 0x0000555555559020
gef➤ x/s 0x0000555555559020
0x555555559020: "/recipe"
Wir sehen einen mkdir-Aufruf, der ein Verzeichnis mit unserem eingegebenen Namen im aktuellen Verzeichnis erstellt.