0:00:00.000,0:00:16.070 35C3 Vorspannmusik 0:00:16.070,0:00:25.390 Herald: Gut dann wollen jetzt beginnen.[br]Wer von euch hat schon mal eine E-Mail 0:00:25.390,0:00:33.960 gekriegt mit einem Anhang? Wer von euch[br]hat eine E-Mail bekommen mit einem Anhang 0:00:33.960,0:00:40.410 von einer euch unbekannten Person? Das[br]sind erstaunlich wenige, so 20 Prozent. 0:00:40.410,0:00:47.671 Wer von euch hat den schon mal aufgemacht?[br]3, 4. Wer von euch kennt jemanden, der schon 0:00:47.671,0:00:55.620 mal einen Anhang aufgemacht hat? Ja[br]deutlich mehr. Wer von euch musste die 0:00:55.620,0:01:03.420 Probleme beseitigen, die dadurch[br]entstanden sind? Ja auch so 10 20 Prozent 0:01:03.420,0:01:12.170 würde ich sagen. Ja es ist natürlich eine[br]ganz gute Idee, sich zu überlegen, ob man 0:01:12.170,0:01:16.220 denn jetzt eine Rechnung oder ein Angebot[br]auf machen möchte, was man von einer 0:01:16.220,0:01:22.580 völlig unbekannten Person aus dem Internet[br]bekommen hat. Und was da passiert, wenn 0:01:22.580,0:01:26.659 man es tatsächlich täte, das wird uns[br]jetzt haggl erläutern. Applaus. 0:01:26.659,0:01:30.990 Applaus 0:01:30.990,0:01:46.450 Haggl: Was? Das sollte so nicht aussehen,[br]Moment, warum sagt mir das keiner? 0:01:46.450,0:02:15.700 So, hallo, dann können wir jetzt ja anfangen.[br]Ja also danke für die schöne Einleitung. 0:02:15.700,0:02:20.690 Schön, dass ihr alle da seid, dass ihr so[br]zahlreich erschienen seid. Wie in jedem 0:02:20.690,0:02:27.160 Jahr eigentlich, gab es auch in 2018 - ich[br]schiebe mal eben die Maus da weg - 2018 0:02:27.160,0:02:31.300 wieder ein paar schöne Beispiele, oder[br]schön ist in Anführungszeichen zu setzen, 0:02:31.300,0:02:33.560 Beispiele von Sicherheitslücken, die[br]ziemlich gravierend sind und die 0:02:33.560,0:02:40.000 geschlossen werden, glücklicherweise,[br]gingen direkt am Anfang des Jahres los. Im 0:02:40.000,0:02:43.670 Januar wurden im Firefox und mithin auch[br]im tor-Browser, der ja drauf basiert, ein 0:02:43.670,0:02:49.910 paar Sicherheitslücken geschlossen, [br]für die man nur eine Webseite besuchen 0:02:49.910,0:02:53.910 musste und dann sind da intern irgendwelche[br]Buffer Overflows passiert und im 0:02:53.910,0:02:58.450 schlimmsten Fall konnten Angreifer damit[br]halt beliebigen Code ausführen. Ein 0:02:58.450,0:03:01.860 weiteres Ding aus diesem Jahr, da habe ich[br]leider keine schöne Pressemitteilung zu 0:03:01.860,0:03:07.150 gefunden, nur so einen CVE-Artikel. Der[br]Adobe Reader, mal wieder, übrigens guckt 0:03:07.150,0:03:12.989 mal wie viele Sicherheitslücken der hat,[br]das ist enorm. Da war auch was drin mit 0:03:12.989,0:03:17.560 einem Buffer Overflow und ebenfalls[br]arbitrary code execution. Heißt, ein 0:03:17.560,0:03:20.930 Angreifer kann beliebigen Code auf dem[br]Rechner ausführen. Drittes Beispiel, gar 0:03:20.930,0:03:26.099 nicht so lange her, ist eigentlich im[br]letzten Jahr gewesen, und zwar die beiden 0:03:26.099,0:03:31.190 Würmer Petya und WannaCry. Das waren so[br]sympathische Ransomwares, die die 0:03:31.190,0:03:35.959 Festplatte verschlüsseln und den Besitzer[br]dann auffordern, Bitcoins zu überweisen, an 0:03:35.959,0:03:40.200 eine bestimmte Adresse, damit der Rechner[br]wieder frei geschaltet werden kann. Auch 0:03:40.200,0:03:45.780 die waren beide, also Teil der Angriffe,[br]die die genutzt haben, funktionierten über 0:03:45.780,0:03:50.060 Buffer Overflows. Man sieht also, es ist[br]ein Thema mit dem man sehr viel machen 0:03:50.060,0:03:55.110 kann und deswegen reden wir da jetzt ein[br]bisschen darüber. Das ist der grobe 0:03:55.110,0:03:57.760 Fahrplan, es gibt jetzt so eine kleine[br]Vorstellungsrunde, ich sage etwas zu mir, 0:03:57.760,0:04:02.349 frage was über euch, sag was zum Vortrag.[br]Danach machen wir ein paar Grundlagen, die 0:04:02.349,0:04:05.830 zum Teil sehr technisch und zäh sind, ich[br]bitte das zu entschuldigen, aber ganz ohne 0:04:05.830,0:04:12.090 geht es leider nicht. Und dann erkläre[br]ich, wie halt der Exploit funktioniert, so 0:04:12.090,0:04:16.289 ein Stack Buffer Overflow Exploit und zum[br]Schluss gibt es, wenn die Demo-Götter uns 0:04:16.289,0:04:20.320 weiter gewogen sind, eine Demonstration,[br]wo ich meinen eigenen Rechner halt mit 0:04:20.320,0:04:28.630 einem verwundbaren Programm übernehme.[br]Also über mich: Ich bin im Chaos und 0:04:28.630,0:04:34.050 Hackspace Siegen aktiv und treibe da so[br]ein bisschen mein Unwesen, habe so halb 0:04:34.050,0:04:38.120 den Hut für "Chaos macht Schule" und die[br]Cryptoparties auf. Wenn es sich nicht 0:04:38.120,0:04:42.639 vermeiden lässt, mache ich noch[br]Infrastruktur und ähnliche Geschichten. In 0:04:42.639,0:04:46.530 meinem sonstigen Leben bin ich[br]Informatiker, ich programmiere kleine 0:04:46.530,0:04:52.430 Mikrocontroller für Soundsysteme, ich[br]mache Judo und bin Musiker. Meine 0:04:52.430,0:04:57.190 Lieblingsspeise ist Dal. An dieser stelle[br]herzlichen Dank an das Küchenteam, die uns 0:04:57.190,0:05:01.240 während dem Aufbau sehr gut verpflegt[br]haben, unter anderem mit Dal. So, bisschen 0:05:01.240,0:05:07.130 was über euch. Ein kurzes Funktionscheck:[br]Wer hört mir zu und ist in der Lage und 0:05:07.130,0:05:13.490 gewillt, seinen Arm zu heben bei Fragen,[br]die zutreffen? Das sind ungefähr alle, 0:05:13.490,0:05:17.180 cool. Dann: Wer weiß, wie so ein Rechner[br]aufgebaut ist, Stichwort 0:05:17.180,0:05:21.880 Rechnerarchitektur, Rechenwerk,[br]Steuerwerk, so was? Das sind auch 0:05:21.880,0:05:27.130 erstaunlich viele, okay. Wer hat schon mal[br]programmiert? Im Idealfall mit C, das sind 0:05:27.130,0:05:34.030 ungefähr alle. Wer hat schon mal gehört,[br]was ein Stack ist? Was ein Buffer Overflow 0:05:34.030,0:05:41.610 ist? Wer hat sich bei allem gemeldet? Ihr[br]werdet euch langweilen! lacht Der 0:05:41.610,0:05:46.600 Vortrag ist nämlich, ich habe versucht,[br]ihn möglichst einfach zu halten, weil 0:05:46.600,0:05:49.470 inspiziert inspiriert, entschuldigung,[br]inspiriert ist er von einem 0:05:49.470,0:05:52.560 Arbeitskollegen, den ich eigentlich für[br]sehr kompetent halte, und der sich auch 0:05:52.560,0:05:56.759 auskennt mit Mikrocontrollern, mit[br]Assemblycode und der mich irgendwann mal 0:05:56.759,0:06:01.411 fragte, oder mehr im Nebensatz beiläufig[br]erwähnte, dass er nicht verstünde, wie 0:06:01.411,0:06:07.610 denn eigentlich sein kann, dass ein PDF[br]einen Rechner übernehmen kann. Challenge 0:06:07.610,0:06:11.190 accepted habe ich mir gedacht, das muss[br]man doch irgendwie erklären können. Und 0:06:11.190,0:06:15.419 dann habe ich den Vortrag gemacht, habe[br]hier in den Talk eingereicht in Pretalx, 0:06:15.419,0:06:18.539 der wurde dann halt paar Wochen später[br]auch angenommen, dann habe ich mir den 0:06:18.539,0:06:21.330 Vortrag, den ich zwei Wochen vorher[br]zusammengeschraubt hatte, noch einmal 0:06:21.330,0:06:24.683 angeschaut und geprüft, ob er den[br]Anforderungen entspricht, die ich mir 0:06:24.683,0:06:28.550 selber gesetzt habe, festgestellt oh mein[br]Gott, er ist viel zu technisch. Deswegen 0:06:28.550,0:06:31.980 habe ich den weiter abgespeckt und[br]versucht, alle nicht nötigen Details, alle 0:06:31.980,0:06:34.919 nicht nötigen Fachwörter, alles raus zu[br]streichen, was man nicht unbedingt 0:06:34.919,0:06:40.350 braucht, um das Prinzip eines Stack Buffer[br]Overflows oder ein Exploit dessen zu 0:06:40.350,0:06:46.139 verstehen. Der Vortrag ist vor 20 Minuten[br]fertig geworden, ich habe ihn noch nie 0:06:46.139,0:06:50.759 Probe gehalten, ich habe gestern bei der[br]Demo zweimal meinen Rechner abgeschossen, 0:06:50.759,0:06:55.710 insofern bin ich selber sehr gespannt, was[br]jetzt passiert. Also fangen wir an. 0:06:55.710,0:06:59.790 Grundlagen: Wie funktioniert ein Rechner?[br]Wenn man es ganz ganz ganz ganz grob 0:06:59.790,0:07:05.169 vereinfacht ausdrückt, gibt es irgendwo[br]einen Prozessor, da kommen auf der einen 0:07:05.169,0:07:11.680 Seite Daten rein, nämlich Programmdaten,[br]und auf der anderen Seite kommen Daten 0:07:11.680,0:07:15.860 rein und raus, nämlich die Nutzdaten, die[br]ich verarbeiten möchte. Das kann, weiß 0:07:15.860,0:07:20.550 ich, ein Office-Dokument sein, ein PDF[br]oder halt auch Daten aus dem Internet wie 0:07:20.550,0:07:27.889 HTML-Seiten, bei Web-Browsern sind das halt[br]die Daten die rein und raus gehen. Daten 0:07:27.889,0:07:35.030 werden intern im Rechner in dem Speicher[br]abgelegt und zwar in Paketen von acht 1en 0:07:35.030,0:07:39.639 und 0en. 1en und 0en sind Bits, das wissen[br]ja wahrscheinlich alle. So ein Paket von 0:07:39.639,0:07:45.420 acht davon nennt man ein Byte. Jedes Byte[br]hat eine Adresse im Speicher. Und der Witz 0:07:45.420,0:07:49.389 ist, dass das hier so, dass was da[br]gezeichnet ist, nicht ganz korrekt ist, 0:07:49.389,0:07:53.660 denn Programme und Daten liegen im[br]gleichen Speicher. Das heißt, ich kann es 0:07:53.660,0:07:57.900 theoretisch schaffen, den Prozessor dazu[br]zu bringen, Programme auszuführen aus dem 0:07:57.900,0:08:02.240 Speicherbereich, wo eigentlich Daten[br]liegen sollten. Das ist schon eigentlich 0:08:02.240,0:08:10.139 wie letztendlich so ein Buffer Overflow[br]Exploit funktioniert. Wenn ich den 0:08:10.139,0:08:13.580 Prozessor da in der Mitte doch noch mal[br]ein bisschen aufbohre, dann sehe ich, dass 0:08:13.580,0:08:18.849 er da drin so einen Registersatz hat. Man[br]nennt das so, Register. Das ist so ein 0:08:18.849,0:08:23.940 bisschen vergleichbar mit dem, man könnte[br]sagen, das Kurzzeitgedächtnis von 0:08:23.940,0:08:28.580 Menschen, man sagt Menschen ja nach, sie[br]könnten sich so größenordnungsmäßig 7 0:08:28.580,0:08:33.829 Dinge gleichzeitig merken, kurzzeitig. So[br]ähnlich ist das bei einem Prozessor auch, 0:08:33.829,0:08:38.829 der hat einen sehr begrenzten Satz von[br]Registern, also Speicherzellen, die sehr 0:08:38.829,0:08:43.159 schnell sind, aber halt auch sehr teuer[br]sind. Deswegen baut man da nicht so viele 0:08:43.159,0:08:46.399 von, das sind die Register. Und dann merkt[br]er sich halt zum Beispiel, wo er im 0:08:46.399,0:08:54.069 Programm gerade steht. Also wo im[br]Programmspeicher er gerade steht oder wo 0:08:54.069,0:08:59.420 der Stack gerade steht. Der Stack ist ein[br]besonderer Speicherbereich im 0:08:59.420,0:09:04.869 Datenspeicher, also eigentlich kein[br]Programmspeicher, der verwendet wird um 0:09:04.869,0:09:10.009 Dinge längerfristig abzulegen, also man[br]könnte sagen Langzeitgedächtnis. Naja es 0:09:10.009,0:09:14.410 stimmt nicht ganz, aber grob. Und der[br]Stack ist wirklich, der Name ist Programm, 0:09:14.410,0:09:17.550 ist wie ein Stapel, ich lege unten was[br]drauf, dann lege ich was oben drauf, lege 0:09:17.550,0:09:20.879 etwas weiteres oben drauf, und ich lege[br]auch Dinge oder hole Dinge genau in der 0:09:20.879,0:09:26.829 umgekehrten Reihenfolge wieder runter.[br]Also wie ein Stapel Papier eigentlich. Der 0:09:26.829,0:09:31.850 wird gebraucht, um bestimmte Features von[br]Programmiersprachen zu implementieren, das 0:09:31.850,0:09:35.749 werden wir gleich noch sehen. Wenn jetzt[br]also so ein Programm abläuft, also links 0:09:35.749,0:09:39.970 sieht man einen Ausschnitt aus dem[br]Programmspeicher. Also ich habe da jetzt 0:09:39.970,0:09:43.759 byteweise mal irgendwelche random[br]Zahlen hingemalt. Naja es sind keine 0:09:43.759,0:09:47.670 random Zahlen, es ist tatsächlich ein Teil[br]eines Shell-Codes. Also von dem Ding, was 0:09:47.670,0:09:52.259 ich gleich benutze, um meinen Rechner[br]aufzumachen. Die sind jetzt von oben nach 0:09:52.259,0:09:56.009 unten byteweise aufgelistet und man würde[br]jetzt sehen, also Speicheradressen gehen 0:09:56.009,0:09:59.750 jetzt hier von oben nach unten. Das heißt,[br]oben sind die niedrigen Speicheradressen, 0:09:59.750,0:10:03.300 unten sind die hohen Speicheradressen. Und[br]die werden einfach der Reihe nach 0:10:03.300,0:10:07.329 durchgezählt, jedes Byte hat halt so eine[br]Adresse. Und so weiß der Prozessor genau, 0:10:07.329,0:10:11.379 wenn er gesagt bekommt, macht mal hier an[br]der und der Stelle im Programmcode weiter, 0:10:11.379,0:10:15.940 dann springt er halt dahin und liest[br]weiter. Und zwar sieht das so aus, da 0:10:15.940,0:10:22.259 werden halt Dinge, also dass der Opcode[br]oder der Befehl, der gerade ausgeführt 0:10:22.259,0:10:25.389 werden soll, wird eingelesen und wird[br]ausgeführt und der könnte dann zum 0:10:25.389,0:10:30.910 Beispiel so etwas machen wie ein Datum aus[br]dem Registersatz in den Stack legen oder 0:10:30.910,0:10:34.720 auf den Stack oben drauf legen. Im[br]nächsten Schritt wird dann etwas anderes 0:10:34.720,0:10:38.639 oben draufgelegt und dann wird da wieder[br]was runtergeholt und wieder zurück in das 0:10:38.639,0:10:41.899 Register geschrieben, möglicherweise noch[br]irgendwomit verrechnet und so, hangelt er 0:10:41.899,0:10:48.230 sich halt durch den Code durch. Von oben[br]nach unten. Man sieht auch, es muss nicht 0:10:48.230,0:10:54.369 unbedingt immer alles, jedes Ding muss[br]nicht auch ein Befehl sein, da sind auch 0:10:54.369,0:10:59.499 Daten dazwischen. In diesem Fall halt das,[br]was auf den Stack gelegt wurde. Aber im 0:10:59.499,0:11:02.110 Prinzip funktioniert das so. Ein Rechner[br]geht einfach der Reihe nach die Befehle 0:11:02.110,0:11:04.470 durch. Es gibt dann halt auch[br]Sprungbefehle, die sagen können: springe 0:11:04.470,0:11:08.790 mal irgendwie zurück oder springe mal vor,[br]aber im Prinzip ist das alles was ein 0:11:08.790,0:11:16.660 Rechner macht. Okay, der Shell Code, den[br]ich gleich benutzen werde, sieht so aus. 0:11:16.660,0:11:21.660 Das ist offensichtlich ein Programm, was[br]den laufenden Prozess beendet und eine 0:11:21.660,0:11:26.929 Shell mit dem Namen "sh" startet. Nun ist[br]das natürlich nicht so offensichtlich, so 0:11:26.929,0:11:29.509 will ja keiner Code schreiben. Deswegen[br]haben sich Leute einfallen lassen: Hey, 0:11:29.509,0:11:33.930 wir müssen irgendwie es schaffen, was[br]lesbareres zu bekommen und außerdem würden 0:11:33.930,0:11:36.499 wir ganz gerne, wenn wir ein Programm[br]geschrieben haben, das nicht für jeden 0:11:36.499,0:11:40.249 Prozessor dieser Welt neu schreiben[br]müssen. Weil das da ist Code, der nur auf 0:11:40.249,0:11:45.860 diesem Prozessor, in diesem Fall ein x86[br]Prozessor ,läuft. Wenn ich versuche, den 0:11:45.860,0:11:49.399 auf einem ARM-Prozesor laufen zu lassen,[br]dann sagt er: Kenne ich nicht den Befehl, 0:11:49.399,0:11:56.309 mache ich nicht. Beides erreicht man mit[br]sogenannten höheren Programmiersprachen. 0:11:56.309,0:12:03.350 Eine davon ist C. Das gleiche Programm[br]sieht in C so aus. Und hier kann man schon 0:12:03.350,0:12:06.450 einigermaßen erkennen, okay hier ist[br]irgendwie ein String drin, offensichtlich 0:12:06.450,0:12:12.879 also eine Zeichenkette die auf /bin/sh[br]zeigt. Das ist für Leute, die Unix kennen, 0:12:12.879,0:12:17.739 die Standard Shell. Also ein[br]Kommandozeileninterpreter. Und darunter ist 0:12:17.739,0:12:22.660 eine Zeile, naja die ist wirklich sehr[br]kryptisch, die muss man schon kennen. Es 0:12:22.660,0:12:26.489 ruft halt das Programm auf. Aber wie[br]gesagt, Menschen, die sich damit ein 0:12:26.489,0:12:29.759 bisschen auskennen, die können so etwas[br]direkt auf Anhieb lesen, das da oben 0:12:29.759,0:12:35.389 natürlich nicht. Dieser Code wird jetzt in[br]einen sogenannten Compiler reingeschmissen 0:12:35.389,0:12:43.069 und der Compiler macht dann aus dem[br]Unteren ungefähr das Obere wieder. Zudem 0:12:43.069,0:12:47.129 gibt es dann, wenn man schon so eine[br]schöne Abstraktion hat, noch 0:12:47.129,0:12:51.230 Programmbibliotheken, dass man nicht jeden[br]Scheiß neu machen muss. So was wie: öffne 0:12:51.230,0:12:55.120 mir eine Datei und lies den Inhalt. Das[br]will ich ja nicht jedes mal auf der Ebene 0:12:55.120,0:12:59.989 neu programmieren. Deswegen lege ich mir[br]dafür schöne Bibliotheken an, mit 0:12:59.989,0:13:04.920 Funktionen. Funktionen sind Teile also[br]wieder verwertbare Programmteile, die 0:13:04.920,0:13:08.829 einen definierten Satz von[br]Eingabeparametern haben. Also ich kann 0:13:08.829,0:13:13.579 einer Datei-öffnen-Funktionen[br]beispielsweise mitgeben, wo die Datei sich 0:13:13.579,0:13:16.929 befindet im Dateisystem und ob ich sie[br]lesend schreiben (öffnen) möchte oder schreibend 0:13:16.929,0:13:23.480 oder beides. Dann haben die einen[br]Funktionsrumpf. Das ist der Teil der 0:13:23.480,0:13:27.259 Funktionen, der was macht. Der also das[br]tut, was die Funktion tun soll mit den 0:13:27.259,0:13:31.259 Eingangsparametern und dann gibt es noch[br]einen Return-Wert, dass ist also ein 0:13:31.259,0:13:34.129 Rückgabewert, den die Funktion dann zurück[br]gibt, wenn sie fertig ist mit was immer 0:13:34.129,0:13:38.860 sie getan hat. Und auf diese Weise baut[br]man sich halt Bibliotheken und verwendet 0:13:38.860,0:13:41.929 die halt immer wieder. Dieses execve ganz[br]unten ist beispielsweise eine 0:13:41.929,0:13:47.799 Bibliotheksfunktion. Und das war im[br]Prinzip schon alles, was wir für den 0:13:47.799,0:13:59.829 Exploit wissen müssen. Wenn nämlich jetzt[br]so eine Funktionen aufgerufen wird. Nehmen 0:13:59.829,0:14:05.639 wir mal an, wir hätten eine Funktion, die[br]drei Parameter hat, einer davon ist, ach 0:14:05.639,0:14:09.509 Quatsch. Zwei Parameter hat,[br]entschuldigung, und drei lokale Variablen. 0:14:09.509,0:14:13.379 Achso, Variable habe ich gar nicht[br]erklärt. Variablen ist auch ein Konzept 0:14:13.379,0:14:17.970 von Programmiersprachen. Da kann ich halt[br]Speicheradressen sprechende Namen geben. 0:14:17.970,0:14:24.329 Dass ich halt als Programmierer sehen kann,[br]wo ich was abgelegt habe. Und Funktionen 0:14:24.329,0:14:29.160 können lokale Variablen haben. Davon[br]beliebig viele und die werden eben über 0:14:29.160,0:14:32.350 einen Stack abgebildet, genauso wie die[br]Funktionsparameter über einen Stack 0:14:32.350,0:14:36.399 abgebildet werden und der Rückgabewert[br]weiß ich jetzt gerade nicht, da will ich 0:14:36.399,0:14:40.699 nichts falsches sagen. Könnte sein, dass[br]der auch über einen Stack läuft, bin ich 0:14:40.699,0:14:45.160 mir aber gerade nicht sicher. Nein, ich[br]glaube, läuft er nicht, whatever. Wenn ich 0:14:45.160,0:14:48.509 jetzt mir eine Funktion vorstelle, die[br]zwei Parameter hat und drei lokale 0:14:48.509,0:14:54.860 Variablen. Davon soll eine ein Buffer[br]sein, dann passiert, wenn die Funktion 0:14:54.860,0:14:59.769 aufgerufen wird, folgendes: Zuerst werden[br]die Funktionsargumente oder Parameter auf 0:14:59.769,0:15:06.009 den Stack gelegt, und zwar in umgekehrter[br]Reihenfolge. Fragt nicht, ist so. Danach 0:15:06.009,0:15:10.589 wird die momentane Adresse oder die[br]nächste Adresse auf den Stack gelegt, 0:15:10.589,0:15:15.220 damit das Programm weiß, wenn es aus der[br]Funktion zurückkommt, wo es weitermachen 0:15:15.220,0:15:21.419 muss, weil es folgt ja ein Sprung. Dann[br]kommt noch was, das uns nicht interessiert 0:15:21.419,0:15:26.689 und dann kommen die lokalen Variablen der[br]Funktion selber. In diesem Fall eine 0:15:26.689,0:15:30.119 Variable, dann kommt ein Buffer und dann[br]kommt noch eine Variable. An dieser Stelle 0:15:30.119,0:15:32.333 ist sehr schön zu erklären, was ein[br]Buffer ist. Ein Buffer ist 0:15:32.333,0:15:39.489 eigentlich nichts anderes als eine[br]Variable, die aber mehr Speicher hat. 0:15:39.489,0:15:44.029 Also das ist jetzt nicht eine Zahl,[br]sondern es sind beispielsweise 512 Zahlen 0:15:44.029,0:15:49.720 der gleichen Größe. Das ist ein Buffer.[br]Das hier wäre zum Beispiel jetzt ein 0:15:49.720,0:15:56.350 Buffer der Größe 5. 5 Bytes groß. Die[br]können beliebig groß sein, wobei beliebig 0:15:56.350,0:16:00.519 ist nicht ganz richtig. Hängt von der[br]Speichergröße ab, wie ich gestern gelernt 0:16:00.519,0:16:07.569 habe, bei der Demo. lacht Ja, aber im[br]Prinzip sind die nicht begrenzt und das 0:16:07.569,0:16:09.930 Schlimme ist, man muss sich wenn man so[br]low level programmiert, selber darum 0:16:09.930,0:16:15.679 kümmern, dass man die Grenzen einhält und[br]nicht zu viel da rein schreibt. Und dann 0:16:15.679,0:16:23.089 sind wir schon beim Programm. Das Rechte[br]ist das C Program, was ich exploite. Das 0:16:23.089,0:16:28.160 ist relativ überschaubar, oben diese Zeile[br]"int main", das kann man ignorieren, dass 0:16:28.160,0:16:32.879 braucht man halt, um C zu sagen: hier[br]beginnt das Programm, hier geht es los und 0:16:32.879,0:16:37.529 es ist aber wichtig zu wissen, dass main[br]bereits eine Funktion ist. Also vorher 0:16:37.529,0:16:44.419 passieren noch andere Dinge, die wir nicht[br]genauer betrachten, die mir aber sehr 0:16:44.419,0:16:49.119 viele Steine in den Weg gelegt haben[br]gestern. lacht Die rufen am Ende dann 0:16:49.119,0:16:55.209 halt diese Funktion main auf. Es ist also[br]ein ganz normaler Funktionsaufruf. Die 0:16:55.209,0:16:58.239 Funktion main hat jetzt eine lokale[br]Variable, nämlich den Buffer der Größe 0:16:58.239,0:17:02.279 256. Das ist nicht mehr ganz aktuell, in[br]der Demo, die ich gleich zeige, ist er ein 0:17:02.279,0:17:07.620 bisschen größer, spielt aber keine Rolle.[br]Danach gibt es eine Bibliotheksfunktion 0:17:07.620,0:17:15.420 string copy, strcpy. Die kopiert, was[br]immer in argv[1] liegt. Da muss man jetzt 0:17:15.420,0:17:20.079 dazu sagen, das ist ein[br]Kommandozeilenparameter. Wenn ich ein 0:17:20.079,0:17:23.250 Programm aufrufe auf der Kommandozeile,[br]kann ich dem noch Argumente mitgeben und 0:17:23.250,0:17:27.289 das erste Argument, was ich dem mitgebe in[br]diesem Fall, würde halt in den Buffer 0:17:27.289,0:17:33.840 kopiert. Danach wird eine nette Nachricht[br]ausgegeben "Hallo, was immer in dem Buffer 0:17:33.840,0:17:38.520 steht" und dann folgt das return. Sprich,[br]die Funktionen kehrt zurück und dieser 0:17:38.520,0:17:43.130 ganze Stack wird abgeräumt und der[br]Prozessor springt dahin, an die Stelle, 0:17:43.130,0:17:48.110 deren Adresse jetzt in return links rot[br]markiert steht. Also weil vorher hat sich 0:17:48.110,0:17:51.620 ja das Programm gemerkt, wo es nachher hin[br]zurück muss, indem es die Adresse extra da 0:17:51.620,0:17:56.470 hingelegt hat. Und wenn ich jetzt zu viele[br]Daten in diesen Buffer rein schreibe, der 0:17:56.470,0:18:01.039 ist links verkürzt dargestellt, also[br]jetzt die letzten 5 Bytes von diesem 256 0:18:01.039,0:18:05.519 Bytes Buffer, wenn ich jetzt zu viele[br]Daten da reinschreibe, dann kommt 0:18:05.519,0:18:10.080 irgendwann der Punkt, wo ich halt die[br]letzten paar Bytes überschreibe. Dann 0:18:10.080,0:18:13.000 überschreibe ich das Ding, was uns nicht[br]interessiert und irgendwann überschreibe 0:18:13.000,0:18:19.149 ich die Return-Adresse. Was jetzt[br]passiert, erst mal noch nichts. Dann kommt 0:18:19.149,0:18:26.350 das return 0 und was das return macht: Es[br]lädt was immer an dieser stelle steht 0:18:26.350,0:18:29.669 zurück in den instruction pointer, also an[br]die Stelle, wo sich der Prozessor intern 0:18:29.669,0:18:34.880 merkt, wo das Programm gerade steht und[br]macht an der Stelle weiter. Wenn ich es 0:18:34.880,0:18:41.820 jetzt schaffe, in diesen Buffer meinen[br]Shell Code reinzuladen, also das kleine 0:18:41.820,0:18:45.810 Programmstück, was ihr eben gesehen habt,[br]was das laufende Programm beendet und ein 0:18:45.810,0:18:49.230 neues Programm, nämlich einen[br]Kommandozeileninterpreter startet, wenn 0:18:49.230,0:18:53.060 ich das jetzt schaffe das da oben rein zu[br]schreiben und zudem noch es schaffe, an 0:18:53.060,0:19:00.429 die Return-Adresse den Anfang von diesem[br]Code reinzuschreiben, dann passiert genau, 0:19:00.429,0:19:04.280 was nicht passieren darf: Nämlich das[br]Programm macht, was ich ihm vorher gesagt 0:19:04.280,0:19:10.620 habe und was ich vorher in diesem Buffer[br]reingeschrieben habe. Und jetzt kommt der 0:19:10.620,0:19:16.130 Punkt, an dem es interessant wird. Jetzt[br]muss ich erst mal meine Maus wiederfinden, 0:19:16.130,0:19:41.529 dass habe ich mir alles anders[br]vorgestellt. Sieht man das? Das ist ein 0:19:41.529,0:19:57.440 bisschen klein. Könnt ihr das[br]lesen, nein oder? Da hinten, könnt ihr 0:19:57.440,0:20:05.570 das da hinten lesen? Nein. Bis gerade eben[br]konnte ich auch noch die Größe von meinem 0:20:05.570,0:20:15.070 Terminal verstellen. Das scheint jetzt[br]nicht mehr zu gehen. Aha, geht nur auf dem 0:20:15.070,0:20:26.139 linken Bildschirm, aus Gründen! Könnt ihr[br]das jetzt einigermaßen lesen? Gut. Also 0:20:26.139,0:20:36.639 ich habe hier dieses Programm, ich habe[br]das mal vorbereitet. Es macht, was es 0:20:36.639,0:20:40.500 soll, es liest halt den ersten Parameter[br]ein, also "vuln" ist das Programm, das 0:20:40.500,0:20:44.129 verwundbar ist. Ich habe ihm den Parameter[br]"haggl" mit gegeben, also sagt das "Hallo, 0:20:44.129,0:20:49.740 haggl", alles cool. Wenn ich jetzt aber[br]Dinge da rein schreibe, die ein bisschen 0:20:49.740,0:21:09.529 länger sind, beispielsweise so etwas. Ich[br]hoffe, das ist die richtige Syntax um in 0:21:09.529,0:21:14.669 Python Dinge auf der Kommandozeile direkt[br]auszuführen. Ja. Dann kriege ich einen 0:21:14.669,0:21:18.179 segmentation fault. Ein segmentation fault[br]ist der nette Hinweis vom 0:21:18.179,0:21:22.360 Betriebssystemen: Kollege, du hast gerade[br]Speicher lesen und/oder schreiben wollen, 0:21:22.360,0:21:29.750 auf den du keinen Zugriff hast. Wenn Leute[br]die Exploits schreiben, so etwas kriegen, 0:21:29.750,0:21:33.360 also das ist das was normalerweise das[br]kennt wahrscheinlich jeder, was passiert 0:21:33.360,0:21:36.190 wenn ein Programm einfach so ohne[br]irgendetwas zu sagen abstürzt, dann ist 0:21:36.190,0:21:40.809 das oft ein segmentation fault. Das ist[br]für die meisten Menschen sehr nervig, weil 0:21:40.809,0:21:43.460 man dann das Programm neu starten muss,[br]gegebenenfalls Daten verloren gegangen 0:21:43.460,0:21:47.600 sind. für Leute, die Exploits schreiben,[br]ist das der heilige Gral, weil 0:21:47.600,0:21:52.770 segmentation faults sind oft ein Indiz[br]dafür, dass es da gerade einen Buffer 0:21:52.770,0:21:56.200 Overflow gegeben hat. Und ein Buffer[br]Overflow, damit kann man eine Menge 0:21:56.200,0:22:10.760 anfangen. Man kann beispielsweise einen[br]Shell Code reinladen. xxd -p shellcode, 0:22:10.760,0:22:15.539 das ist das Ding, was wir eben in den[br]Slides gesehen haben. Das ist also dieses 0:22:15.539,0:22:21.840 Programm in Maschinencode, was das[br]laufende Programm beendet und eine Shell 0:22:21.840,0:22:29.780 startet. Und wenn ich die jetzt da rein[br]injecte, also anstatt jetzt diesem 0:22:29.780,0:22:39.150 Pythonding oder dem einfachen String[br]haggl, dieses Teil jetzt da rein pipe, 0:22:39.150,0:22:44.380 dann bekomme ich eine Shell. Und zwar eine[br]Shell, die nicht die andere Shell ist, 0:22:44.380,0:22:50.120 sondern eine neue Shell ist. An der Stelle[br]habe ich es geschafft. Jetzt bin ich halt 0:22:50.120,0:22:55.730 drin und kann hier auf dem System[br]beliebige Dinge machen. Das ist erstmal so 0:22:55.730,0:23:01.320 noch nicht so schlimm und das ist ja auch[br]ein sehr akademisches Beispiel, weil ich 0:23:01.320,0:23:03.860 es alles selber geschrieben habe. Ich muss[br]auf dem eigenen Rechner sein, ich bin eh 0:23:03.860,0:23:08.330 schon der Benutzer, aber interessant wird[br]es natürlich, wenn so eine Verwundbarkeit 0:23:08.330,0:23:11.920 irgendwo an der Stelle sitzt, die auf das[br]Netzwerk horcht. Wenn man von außen 0:23:11.920,0:23:16.529 irgendwie Pakete einschleusen kann, die so[br]etwas hervorrufen. Und ich dann irgendwie 0:23:16.529,0:23:20.340 eine Shell oder ähnliches bekomme. Auch[br]interessant wird es, wenn das ein Dienst 0:23:20.340,0:23:24.070 ist, der aus Gründen mit root-Rechten[br]laufen muss. Dann habe ich nämlich auf 0:23:24.070,0:23:28.690 einmal eine root-Shell. Und so weiter und[br]so fort. Also man kann da eine Menge 0:23:28.690,0:23:36.110 lustige Sachen mit machen. Ich habe noch[br]etwas anderes vorbereitet. Und zwar, wenn 0:23:36.110,0:23:40.050 ich jetzt einen Debugger über das Ding[br]laufen lassen. Ein Debugger ist ein 0:23:40.050,0:23:45.340 Programm, mit dem ich zur Laufzeit rein[br]gucken kann, in den Speicher, und schauen 0:23:45.340,0:23:49.019 kann, was denn der Prozess so gerade da[br]macht, und was wo an welcher Stelle im 0:23:49.019,0:23:53.410 Speicher geschrieben wird. Hier sehe ich[br]jetzt noch mal den Quellcode von dem 0:23:53.410,0:23:56.310 Programm. Das ist das gleiche wie eben,[br]bis auf das der Buffer ein bisschen größer 0:23:56.310,0:24:03.510 ist. Das spielt aber keine große Rolle und[br]ich habe zwei breakpoints gesetzt. 0:24:03.510,0:24:07.049 Breakpoint heißt, das Programm oder der[br]Debugger vielmehr, hält das Programm an 0:24:07.049,0:24:12.550 der Stelle an, damit man halt schauen[br]kann, was an bestimmten Speicheradressen 0:24:12.550,0:24:18.440 steht. Und einer ist hier auf dieser Zeile[br]stringcopy, Zeile 6. Also der macht, hält 0:24:18.440,0:24:23.809 an bevor das reinkopiert wurde, und der[br]nächste breakpoint hält kurz vor dem 0:24:23.809,0:24:27.240 return an. Und da müsste ich halt dann[br]schon sehen, was im Buffer passiert ist. 0:24:27.240,0:24:31.759 Wenn ich das Programm jetzt laufen lasse,[br]mit den richtigen Argumenten, das ist 0:24:31.759,0:24:36.360 alles schon hoffentlich konfiguriert, ja,[br]dann sehe ich hier, das es ist ein 0:24:36.360,0:24:40.090 Ausschnitt aus dem Buffer, und zwar die[br]letzten, irgendwo in den letzten paar 0:24:40.090,0:24:45.249 hundert Bytes, da steht ziemlich[br]zufälliger Quatsch drin. Keine Ahnung, was 0:24:45.249,0:24:50.259 das ist das. Das hat irgend ein Prozess[br]vorher, oder vielleicht möglicherweise 0:24:50.259,0:24:56.169 auch der init Prozess, also das was vor[br]meinem eigentlichen main Programm läuft, 0:24:56.169,0:25:02.929 da hingelegt, keine Ahnung, weiß ich[br]nicht. Und die return Adresse steht im 0:25:02.929,0:25:07.090 Moment noch auf dieser lustigen,[br]kryptischen Zahl. Das wird irgendwas sein, 0:25:07.090,0:25:11.700 was, nachdem main beendet wurde, also die[br]Funktion main beendet wurde, 0:25:11.700,0:25:18.361 wahrscheinlich noch irgendwie Speicher[br]aufräumt oder so etwas. So, jetzt sind wir 0:25:18.361,0:25:22.500 also an der Stelle stringcopy, also es ist[br]noch nichts passiert. Wenn ich jetzt zum 0:25:22.500,0:25:31.460 nächsten breakpoint weiterlaufe, dann seht[br]ihr? Hier oben sind ganz viele 0x90 0:25:31.460,0:25:35.071 Instruktionen. Das sind die Anweisungen[br]für den Prozessor: mach mal nichts, warte 0:25:35.071,0:25:39.929 mal einen Takt lang. Und davon habe ich[br]ganz viele da rein geschrieben und 0:25:39.929,0:25:45.409 irgendwann kommt dann hier dieser Shell[br]Code. Das war das Ding, was eben das 0:25:45.409,0:25:50.710 Programm beendet und die Shell startet.[br]Und ich kann auch schon sehen, die return 0:25:50.710,0:25:53.870 Adresse ist jetzt überschrieben worden mit[br]einer Adresse, die ich selber gewählt 0:25:53.870,0:25:59.211 habe. Und diese Adresse, die zielt[br]irgendwo oben vor den Shell Code in diese 0:25:59.211,0:26:04.770 ganzen no-operation Instruktionen, das[br]nennt man eine NOP-slide. Das macht man, 0:26:04.770,0:26:07.460 um ein bisschen zu puffern und ein[br]bisschen Platz zu haben und ein bisschen 0:26:07.460,0:26:10.779 Freiheit zu haben, weil wenn so ein[br]Prozess gestartet wird, dann hängen da 0:26:10.779,0:26:16.450 oben über dem Stack noch ganz viele andere[br]Sachen und die können sich, nicht zur 0:26:16.450,0:26:19.149 Laufzeit, die können sich aber auch von[br]Programmausführung zu Programmausführung 0:26:19.149,0:26:23.779 ändern. Wenn ich zum Beispiel eine neue[br]Variable definiere oder whatever. 0:26:23.779,0:26:26.629 Jedenfalls habe ich die Sachen nicht immer[br]exakt an der gleichen Speicheradresse und 0:26:26.629,0:26:29.260 deswegen macht man gerne so einen NOP-[br]slide. Also man nimmt seinen Shell Code, 0:26:29.260,0:26:32.720 packt den irgendwo in die Mitte, packt[br]davor ganz viele NOPs, wo der Rechner 0:26:32.720,0:26:35.389 einfach so durchtingelt und nichts tut,[br]und dann irgendwann an dem Shell Code 0:26:35.389,0:26:39.400 ankommt und dahinter packt man ganz viele[br]return Adressen, die oben in diese NOP- 0:26:39.400,0:26:44.850 Slide reinspringen. Das heißt, egal ob ich[br]den Bereich vor dem Shell Code treffe oder 0:26:44.850,0:26:47.870 den Bereich hinter dem Shell Code treffe,[br]es passiert immer was passieren muss, 0:26:47.870,0:26:52.110 nämlich er springt im ungünstigsten Fall[br]von hinterm Shell Code zu vor dem Shell 0:26:52.110,0:26:55.960 Code und hangelt sich dann durch bis zum[br]Shell Code, der dann das tut, was er tut. 0:26:55.960,0:27:08.669 Und das ist der Buffer Overflow Exploit.[br]Demo Time! Ja wobei, wie ich schon sagte, 0:27:08.669,0:27:12.620 das ist ein sehr akademisches Beispiel,[br]weil ich das alles halt sehr, um es 0:27:12.620,0:27:18.750 einfach zu halten, sehr klein gehalten[br]habe. In der Realität würde man sagen, es 0:27:18.750,0:27:22.081 ist ja keiner so blöd, wenn da irgendwas[br]in den Puffer rein schreibt, nicht zu 0:27:22.081,0:27:25.049 checken, wie groß denn der Puffer ist und[br]mal zu gucken, ob man überhaupt noch da 0:27:25.049,0:27:33.639 rein schreiben darf. Das stimmt auch,[br]meistens. lacht Das Problem ist: selbst, 0:27:33.639,0:27:38.340 wenn es immer gemacht würde, habe ich oft[br]das Problem, dass ich das zu der Zeit, wo 0:27:38.340,0:27:40.929 ich das Programm schreibe, noch gar nicht[br]wissen kann, wie groß dieser Buffer sein 0:27:40.929,0:27:43.950 muss, weil ich es erst zur Laufzeit[br]mitbekomme, wie viele Pakete da jetzt 0:27:43.950,0:27:47.769 gleich ankommen, wenn es zum Beispiel ein[br]Netzwerkdienst ist. Das heißt, die Größe 0:27:47.769,0:27:50.799 von so einem Buffer wird oft berechnet und[br]wenn ich jetzt bei der Berechnung der 0:27:50.799,0:27:53.881 Größe irgend einen Fehler habe, der dazu[br]führt, dass ich eine falsche Größe raus 0:27:53.881,0:27:58.139 bekomme, die dann dazu führt, dass der[br]Rechner, oder das Programm vielmehr, 0:27:58.139,0:28:03.260 denkt, der Buffer ist riesig groß, dann[br]schreibt das Ding halt weiter. Das ist 0:28:03.260,0:28:12.340 eine Sache, die oft ausgenutzt wird und[br]Daten kommen halt eben, let's face it, 0:28:12.340,0:28:18.389 meistens nicht von der Kommandozeile, aber[br]stattdessen kommen die aus Dateien, die 0:28:18.389,0:28:22.539 ich irgendwie manipulieren kann oder sogar[br]aus dem Netzwerk. Da habe ich natürlich 0:28:22.539,0:28:28.259 dann beliebige Angriffsvektoren. Das[br]heißt, was in der Realität passieren 0:28:28.259,0:28:32.910 würde, also jetzt beispielsweise bei[br]diesen drei Dingern die wir da hatten: Das 0:28:32.910,0:28:40.119 Erste war ja der Firefox Browser. Da würde[br]man vermutlich ein Bild beispielsweise 0:28:40.119,0:28:45.139 sich zusammen bauen, was irgendwie den[br]Bild Standard nicht ganz erfüllt oder wo 0:28:45.139,0:28:52.880 irgendwo ein Byte falsch ist, so dass, wenn[br]der Browser das Bild lädt, sich irgendwo 0:28:52.880,0:28:57.220 verhaspelt und irgendwo es zu einem Buffer[br]Overflow kommt, weil z. B. ein Puffer zu 0:28:57.220,0:29:02.650 klein ausgelegt wird. Oder ich kann[br]versuchen, es über Javascript Dinge zu 0:29:02.650,0:29:07.679 machen, aber das ist eigentlich noch was[br]anderes. Im zweiten Fall, von dem Adobe 0:29:07.679,0:29:12.659 Reader, sind es auch oft tatsächlich[br]irgendwelche Bilder. Das Problem bei dem 0:29:12.659,0:29:15.850 Adobe Reader ist halt so ein bisschen das[br]der so eine eierlegende Wollmilchsau ist. 0:29:15.850,0:29:22.140 Ich kann mit dem Teil ja beliebige[br]Bildformate anzeigen lassen, Text mit 0:29:22.140,0:29:25.509 eigenen Schriften, dass wäre auch ein[br]Angriffsvektor, wenn ich da eine eigene 0:29:25.509,0:29:28.789 Schrift einbauen und die Schrift halt[br]irgendwie so baue, dass beim Einlesen und 0:29:28.789,0:29:33.970 beim Parsen und Bauen dieser Schrift der[br]Reader irgendwie einen Buffer Overflow 0:29:33.970,0:29:39.889 kriegt. Bis hin zu 3D Elemente, ich habe[br]gehört, sie haben teile von Flash in den 0:29:39.889,0:29:45.350 Adobe Reader eingebaut, damit man damit[br]dann 3D Modelle irgendwie anzeigen und 0:29:45.350,0:29:50.299 auch schön drehen kann. Was man ja alles[br]braucht, alles im gleichen Programm, gute 0:29:50.299,0:29:55.309 Idee! Naja jedenfalls, auch da bieten sich[br]verschiedenste Angriffsvektoren und was 0:29:55.309,0:30:00.940 man machen würde ist halt eine Datei[br]bauen, die halten den Fehler ausnutzt und 0:30:00.940,0:30:07.510 einen Buffer Overflow erzeugt. Der Angriff[br]den ich hier gezeigt habe, der ist heute 0:30:07.510,0:30:11.919 aus verschiedenen Gründen nicht mehr[br]möglich. Ich musste drei Dinge abschalten 0:30:11.919,0:30:16.220 um den überhaupt laufen lassen zu können.[br]Das Eine ist, wie ihr euch wahrscheinlich 0:30:16.220,0:30:19.340 jetzt schon gedacht habt, naja dann könnte[br]ich doch einfach sagen ich habe einen 0:30:19.340,0:30:22.879 bestimmten Programmspeicher, ich habe[br]einen bestimmten Datenspeicher und was im 0:30:22.879,0:30:26.480 Datenspeicher liegt, darf niemals nicht vom[br]Prozessor ausgeführt werden. Das gibt es. 0:30:26.480,0:30:31.779 Das nennt sich "write XOR execute" und ist[br]seit einigen Jahren im Kernel und sogar in 0:30:31.779,0:30:36.710 Hardware drin. Wenn es angeschaltet ist.[br]Das musste ich ausschalten, dann gibt es 0:30:36.710,0:30:41.580 noch die Möglichkeit sogenannte Stack[br]Canaries, also Kanarienvögel, in den Stack 0:30:41.580,0:30:46.919 einzubauen. Das ist so ein Magic Byte, was[br]da reingeschrieben wird, und ein bisschen 0:30:46.919,0:30:50.669 Code, was vor dem rückkehren der Funktion[br]noch einmal testet, ob dieses Byte, was 0:30:50.669,0:30:57.100 ich da reingeschrieben habe, also zwischen[br]den lokalen Variablen und der 0:30:57.100,0:31:01.499 Returnadresse, moment ich mache das mal[br]eben grafisch, damit man das sehen kann, 0:31:01.499,0:31:05.070 genau, also an diese Stelle, die jetzt da[br]schwarz markiert ist, zwischen dem Return 0:31:05.070,0:31:10.149 und dem Buffer, würde man ein zur Laufzeit[br]gewähltes beliebiges Byte reinschreiben 0:31:10.149,0:31:14.419 und bevor man aus der Funktion[br]zurückkehrt, würde man testen, ob dieses 0:31:14.419,0:31:18.690 Byte, was man da vorher reingeschrieben[br]hat, noch das gleiche ist wie vorher. Wenn 0:31:18.690,0:31:21.090 nicht, ist ein Buffer Overflow passiert[br]und dann lässt man das Programm besser 0:31:21.090,0:31:26.239 sofort abstürzen, anstatt abzuwarten, was[br]jetzt kommt. Das ist ein Stack Canary. 0:31:26.239,0:31:33.040 Auch das musste ich ausschalten. Und das[br]Dritte ist bei modernen Betriebssystemen, 0:31:33.040,0:31:35.690 mittlerweile haben es glaube ich alle[br]drin, ist das so, dass jeder Prozess mit 0:31:35.690,0:31:42.509 einem zufälligen Speicherlayout läuft. Das[br]heißt, ich kann nicht mehr wirklich sagen 0:31:42.509,0:31:46.360 wo meine Dinge im Speicher liegen und das[br]macht es sehr sehr schwierig, weil ich ja 0:31:46.360,0:31:51.619 irgendwo an den Shell Code, an das Ende[br]vom Shell Code, eine Adresse schreiben 0:31:51.619,0:31:55.960 muss, die vorne in diese NOP slide[br]reinführt. Und wenn ich absolut keine 0:31:55.960,0:31:59.009 Ahnung habe, wo diese Adresse ist, also[br]ich kann nicht mehr durch Vergrößern des 0:31:59.009,0:32:02.179 Buffers oder durch mehr NOPs einfügen kann[br]ich das irgendwann nicht mehr schaffen, 0:32:02.179,0:32:06.330 weil es einfach so zufällig ist, dass ich[br]keine Chance mehr habe herauszufinden, wo 0:32:06.330,0:32:10.889 zur Laufzeit denn dieser Shell Code liegt,[br]und wenn ich nicht weiß wo der liegt, kann 0:32:10.889,0:32:15.399 ich da nicht rein springen, kann ich also[br]keinen Buffer Overflow Exploit machen. 0:32:15.399,0:32:19.080 Diese drei Dinge gibt es heute, die sind[br]in der Regel, also zwei davon macht der 0:32:19.080,0:32:23.049 Compiler, das Dritte macht das[br]Betriebssystem, und die musste ich jetzt 0:32:23.049,0:32:27.369 alle umgehen, um das überhaupt[br]demonstrieren zu können. Aber die zugrunde 0:32:27.369,0:32:32.049 liegenden Probleme bestehen weiterhin, die[br]sind nämlich: Speichermanagement ist 0:32:32.049,0:32:36.570 fehleranfällig, Menschen machen immer[br]Fehler, ist oft auch nicht so 0:32:36.570,0:32:41.149 übersichtlich, Datenformate sind zu[br]komplex, Programme müssen zu viel 0:32:41.149,0:32:45.679 gleichzeitig können und das führt alles[br]dazu, dass halt immer mehr Fehler 0:32:45.679,0:32:48.649 passieren. Je höher die Komplexität ist,[br]desto höher ist natürlich die 0:32:48.649,0:32:53.629 Wahrscheinlichkeit, das ich Fehler mache.[br]Und das ist nicht gefixt und die 0:32:53.629,0:32:58.460 Programmiersprachen, die man dafür[br]verwendet, sind eigentlich einer Zeit 0:32:58.460,0:33:03.639 entstammend, in der das Internet noch ein[br]freundlicher Ort war. Man kannte sich und 0:33:03.639,0:33:09.100 da hat man über Security nicht so richtig[br]nachgedacht. Es gibt außerdem Nachfolger 0:33:09.100,0:33:13.419 von dieser Praxis, also diese Praxis, die[br]ich jetzt hier gezeigt habe, geht halt 0:33:13.419,0:33:16.679 nicht, aber es gibt Nachfolger davon, also[br]Modifikationen davon, die sind ein 0:33:16.679,0:33:20.350 bisschen gewiefter, ein bisschen[br]trickreicher und die schaffen es dann, 0:33:20.350,0:33:23.760 unter Umständen eben doch noch so etwas[br]nicht zu bekommen. Also das funktioniert 0:33:23.760,0:33:30.230 heute immer noch, wie ihr halt an den[br]Nachrichten gesehen habt. Oft werden auch 0:33:30.230,0:33:37.519 nicht alle Gegenmaßnahmen ergriffen, das[br]ist halt Teil der Betriebssystemhersteller 0:33:37.519,0:33:43.799 bzw. Benutzer. An der Stelle danke ich und[br]Fragen? 0:33:43.799,0:33:53.259 Applaus 0:33:53.259,0:34:01.999 Herald: Herzlichen Dank haggl für diesen[br]wundervollen Vortrag! So, Frage-Antwort- 0:34:01.999,0:34:07.580 Runde, es gibt zwei Mikrofone, die sind[br]dort und dort, beleuchtet, wer eine Frage 0:34:07.580,0:34:15.349 hat, stellt sich bitte hinter die[br]Mikrofone und ich rufe dann auf. Keine 0:34:15.349,0:34:24.600 Fragen? Das scheint ein ganz schön[br]umfangreicher Vortrag gewesen zu sein. 0:34:24.600,0:34:30.210 Haggl: Keine Fragen, oder seid ihr[br]bedient? Keine Fragen, weil es zu viele 0:34:30.210,0:34:38.109 gäbe, oder keine Fragen, weil es gar keine[br]mehr gibt? Achso, eine Entweder-Oder-Frage 0:34:38.109,0:34:41.800 kann man nicht mit Handzeichen[br]beantworten, das ist schwierig. lacht 0:34:41.800,0:34:46.310 Herald: Dort steht jemand, bitte.[br]Frage: Ich hätte mal eine Frage und zwar: 0:34:46.310,0:34:51.139 Ich habe die Stelle nicht gefunden, wo die[br]Return-Adresse ausgerechnet wird und 0:34:51.139,0:34:54.210 reingeschrieben wird, also der Return-[br]Wert. 0:34:54.210,0:34:57.369 Haggl: Ja, die konntest du auch nicht[br]finden, weil ich die garnicht gezeigt 0:34:57.369,0:35:16.890 habe. Ich habe dazu noch ein kleines[br]Pythonskript, das das alles macht. Das ist 0:35:16.890,0:35:21.381 diese hier. Also der der Shellcode, den[br]ich vorher gezeigt habe, das ist wirklich 0:35:21.381,0:35:28.569 nur der Part, der halt execve aufruft mit[br]/bin/sh und der wird halt hier eingelesen 0:35:28.569,0:35:33.350 in diesem Pythonskript und dann baue ich[br]mit dem Pythonskript halt eben ganz viele 0:35:33.350,0:35:37.250 NOPs davor, das ist an der Stelle, also[br]hier berechne ich erstmal wie lange diese 0:35:37.250,0:35:41.250 NOP-slide sein soll und packe halt[br]den NOP-slide davor, dann kommt noch ein 0:35:41.250,0:35:45.010 bisschen Padding und Alignment, damit[br]das alles richtig hinten rauskommt, dass 0:35:45.010,0:35:50.819 die Rücksprungadresse auch an der[br]richtigen Stelle liegt im stack. Genau und 0:35:50.819,0:35:55.511 hier oben habe ich halt diese Target-[br]Adresse und die kriegst du halt nur raus, 0:35:55.511,0:35:58.230 wenn du das Programm einmal laufen lässt[br]und mit dem Debugger schaust, na wo ist 0:35:58.230,0:36:02.180 denn der Buffer. Und dann kannst du halt[br]irgendwie eine Adresse in der Mitte von 0:36:02.180,0:36:07.849 dem Buffer aussuchen, den Shellcode[br]dahinter packen, ein par NOPs davor, dann 0:36:07.849,0:36:13.660 tut es das schon. So weit die Theorie, die[br]Praxis, habe ich schmerzhaft gelernt, ist 0:36:13.660,0:36:18.730 ein bisschen komplizierter. Genau, also[br]mehr macht dieses Skript auch nicht, es 0:36:18.730,0:36:20.710 nimmt den Shellcode, packt NOPs davor,[br]return-Adresse dahinter, fertig. 0:36:20.710,0:36:26.460 Frage: Ist die Adresse eine relative oder[br]eine absolute Adresse? 0:36:26.460,0:36:33.410 Haggl: Das ist eine absolute Adresse. Und[br]das ist halt das Ding, an der Stelle 0:36:33.410,0:36:37.130 greift halt dieses address space layout[br]randomization, also dieser 0:36:37.130,0:36:40.440 Abwehrmechanismus vom Betriebssystem, der[br]dafür sorgt, dass jedes mal, wenn ich das 0:36:40.440,0:36:45.470 Programm aufrufe, diese Adresse nicht mehr[br]stimmt. Das kann ich euch demonstrieren. 0:36:45.470,0:37:01.960 Wenn ich jetzt dieses Ding, was nämlich[br]der make Befehl macht, weil, wenn ich 0:37:01.960,0:37:06.280 dieses make exploit mache, was ich euch[br]eben gezeigt habe, da wird vorher noch mit 0:37:06.280,0:37:11.520 diesem Befehl hier für den nächsten[br]Prozess, dieses address space layout 0:37:11.520,0:37:16.730 randomization ausgeschaltet. Standardmäßig[br]ist das an im Linux Kernel und wenn ich 0:37:16.730,0:37:22.800 das nicht mache, sondern einfach nur das[br]Programm aufrufe und da meine payload 0:37:22.800,0:37:31.620 reinschiebe, dann gibt es zwar auch einen[br]segmentation fault, natürlich, aber es 0:37:31.620,0:37:38.230 gibt halt, ich kriege halt keine shell.[br]Und das ist genau aus dem Grund, weil der 0:37:38.230,0:37:41.829 buffer nicht an der Stelle liegt, wo ich[br]ihn vermutet habe und deswegen meine 0:37:41.829,0:37:46.309 Rücksprungadresse irgendwo im Speicher[br]zeigt, da springt er dann hin und, ups, 0:37:46.309,0:37:54.020 gibts einen segmentation fault. Die beiden[br]anderen Dinge könnte ich auch noch eben 0:37:54.020,0:37:58.550 zeigen, ich weiß nicht, wir haben noch[br]Zeit oder? Die beiden an Dinge könnte ich 0:37:58.550,0:38:02.820 eben auch noch zeigen, also was man machen[br]muss, um die beiden anderen 0:38:02.820,0:38:06.940 Sicherheitsmechanismen abzuschalten. Da[br]muss man das Programm nämlich mit diesen 0:38:06.940,0:38:17.760 beiden "-z execstack", das ist dieses was[br]den Softwarecheck ausschaltet, ob ich 0:38:17.760,0:38:23.109 gerade im stack versuche Programme, also[br]generell im Datenspeicher, nein im stack, 0:38:23.109,0:38:28.410 versuche, Programme auszuführen. Das muss[br]man ausschalten. Und dann gibt es noch 0:38:28.410,0:38:32.119 diesen stack protector, dass ist ein stack[br]canarie, dass wird auch standardmäßig 0:38:32.119,0:38:37.590 eingebaut. Muss man also auch explizit[br]ausschalten, um das möglich zu machen. Das 0:38:37.590,0:38:41.339 heißt , Programme, die mit modernen[br]compilern und modernen compiler flags 0:38:41.339,0:38:45.730 kompiliert wurden, sollten trade mark[br]eigentlich nicht so leicht verwundbar 0:38:45.730,0:38:50.450 sein. Und wenn dann noch address space[br]layout randomization dazu kommt, dann ist 0:38:50.450,0:38:54.799 das schon relativ gut, da muss man schon[br]echt eine Menge Zeug machen, um dann noch 0:38:54.799,0:39:01.710 irgendwie reinzukommen. Aber es geht halt[br]trotzdem. 0:39:01.710,0:39:05.750 Herald: Gut ich sehe da drüben an dem[br]Mikrofon noch jemanden, der wartet, bitte. 0:39:05.750,0:39:11.960 Frage: Kann man nicht einfach relative[br]Adressen verwenden, um ASLR auszuhebeln 0:39:11.960,0:39:17.491 und wenn nein, warum nicht?[br]Haggl: Was meinst du mit relativ, relativ 0:39:17.491,0:39:23.410 wozu?[br]Frage: Naja, also ich meine, ah nein, ich 0:39:23.410,0:39:30.430 habe es gerafft, okay.[br]Haggl: Aber im Prinzip bist du auf dem 0:39:30.430,0:39:35.839 richtigen Weg, also was man halt machen[br]kann, ist, man kann herausfinden, wo die 0:39:35.839,0:39:40.940 libc zum Beispiel anfängt. Und wenn ich[br]weiß, wo die libc anfängt, dann weiß ich 0:39:40.940,0:39:45.440 auch, wenn ich zudem noch die Version von[br]der libc kenne, die da reingelinkt wurde, 0:39:45.440,0:39:50.420 weiß ich dann auch, wo bestimmte Dinge aus[br]der libc im Speicher liegen. Und sobald 0:39:50.420,0:39:55.369 ich das habe, kann ich halt dann anfangen,[br]mir wieder Dinge zusammenzubauen. Das geht 0:39:55.369,0:39:57.290 aber dann eher in Richtung return oriented[br]programming. 0:39:57.290,0:40:06.680 Herald: Gut, sieht aus, als sei die Frage[br]beantwortet, gibt es noch weitere Fragen? 0:40:06.680,0:40:10.530 Das scheint nicht der Fall zu sein, aus[br]dem Internet scheint auch keine Frage zu 0:40:10.530,0:40:21.480 kommen. Dann würde ich hiermit den Vortrag[br]schließen, herzlichen Dank haggl! 0:40:21.480,0:40:27.380 Applaus 0:40:27.380,0:40:33.275 35c3 Abspannmusik 0:40:33.275,0:40:47.000 Untertitel erstellt von c3subtitles.de[br]im Jahr 2020. Mach mit und hilf uns!