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!