Massachusetts Institute of Technology. Vorlesung # 6.858. "Sicherheit von Computersystemen." Nikolai Zeldovich, James Mickens. 2014 Jahr
Computer Systems Security ist ein Kurs zur Entwicklung und Implementierung sicherer Computersysteme. Die Vorträge behandeln Bedrohungsmodelle, Angriffe, die die Sicherheit gefährden, und Sicherheitstechniken, die auf jüngsten wissenschaftlichen Arbeiten basieren. Zu den Themen gehören Betriebssystemsicherheit, Funktionen, Informationsflussmanagement, Sprachsicherheit, Netzwerkprotokolle, Hardwaresicherheit und Sicherheit von Webanwendungen.
Vorlesung 1: „Einführung: Bedrohungsmodelle“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 2: „Kontrolle von Hackerangriffen“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 3: „Pufferüberläufe: Exploits und Schutz“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 4: „Trennung von Privilegien“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 5: „Woher kommen Sicherheitssysteme?“
Teil 1 /
Teil 2Vorlesung 6: „Chancen“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 7: „Native Client Sandbox“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 8: „Netzwerksicherheitsmodell“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 9: „Sicherheit von Webanwendungen“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 10: „Symbolische Ausführung“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 11: „Ur / Web-Programmiersprache“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 12: Netzwerksicherheit
Teil 1 /
Teil 2 /
Teil 3Vorlesung 13: „Netzwerkprotokolle“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 14: „SSL und HTTPS“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 15: „Medizinische Software“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 16: „Seitenkanalangriffe“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 17: „Benutzerauthentifizierung“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 18: „Privates Surfen im Internet“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 19: „Anonyme Netzwerke“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 20: „Sicherheit von Mobiltelefonen“
Teil 1 /
Teil 2 /
Teil 3Vorlesung 21: „Tracking-Daten“
Teil 1 /
Teil 2 /
Teil 3 Student: Architekturunterstützung ist also die ideale Lösung?
Professor: Ja, auch dafür gibt es Methoden. Dies ist jedoch etwas kompliziert, da wir, wie Sie sehen können, den Taint-Status neben der Variablen selbst hervorgehoben haben. Wenn Sie also über die Unterstützung nachdenken, die das Gerät selbst bietet, kann es sehr schwierig sein, das Layout der Hardware zu ändern, da hier alles in Silizium eingebrannt ist. Wenn es jedoch auf einer hohen Ebene in der virtuellen Dalvic-Maschine möglich ist, kann man sich vorstellen, dass es möglich sein wird, Variablen und ihre Infektion auf Hardwareebene nebeneinander zu platzieren. Wenn Sie also das Layout in Silizium ändern, können Sie wahrscheinlich die Arbeit erledigen.
Student: Was macht TaintDroid mit Informationen, die auf Git-Zweigberechtigungen und Zweigberechtigungen aufbauen?
Professor: Wir werden gleich darauf zurückkommen, also halten Sie einfach an diesem Gedanken fest, bis wir dazu kommen.
Student: Ich frage mich, ob hier Pufferüberläufe auftreten können, weil sich diese Dinge - Variablen und ihre Infektionen - stapeln.
Professor: Das ist eine gute Frage. Man würde hoffen, dass es in einer Sprache wie Java keinen Pufferüberlauf gibt. Im Fall der C-Sprache kann jedoch etwas Katastrophales passieren, denn wenn Sie einen Pufferüberlauf durchgeführt und dann die Taint-Tags für die Variablen neu geschrieben haben, werden deren Nullwerte in den Stapeln festgelegt und die Daten fließen frei in das Netzwerk.
Student: Ich denke, dass das alles vorhergesagt werden kann?
Professor: absolut wahr. Das Problem der Pufferüberläufe kann mit Hilfe von "Canaries" - Stapelindikatoren gelöst werden. Wenn Sie diese Daten auf dem Stapel haben, möchten Sie nicht, dass sie nicht überschrieben werden, oder Sie möchten nicht, dass die bereits überschriebenen Werte auf irgendeine Weise geknackt werden. Sie haben also absolut Recht - Sie können einfach Pufferüberläufe verhindern.
Kurz gesagt, Taint Tracking kann auf dieser niedrigen x86 / ARM-Ebene bereitgestellt werden, obwohl es etwas teuer und schwierig sein kann, es richtig zu implementieren. Sie fragen sich vielleicht, warum wir zunächst das Problem der Infektionsverfolgung lösen, anstatt zu überwachen, wie das Programm versucht, etwas über das Netzwerk zu senden, indem Sie einfach Daten scannen, die uns vertraulich erscheinen. Dies scheint ziemlich einfach zu sein, da wir dann nicht alles, was das Programm tut, dynamisch überwachen müssen.

Das Problem ist, dass dies nur auf heuristischer Ebene funktioniert. Wenn ein Angreifer weiß, dass Sie genau das tun, kann er Sie leicht knacken. Wenn Sie nur dort sitzen und versuchen, Sozialversicherungsnummern zu ermitteln, kann ein Angreifer einfach die Base 64-Codierung verwenden oder eine andere dumme Sache wie die Komprimierung ausführen. Das Umgehen dieses Filtertyps ist recht trivial, daher reicht dies in der Praxis nicht aus, um die Sicherheit zu gewährleisten.
Kommen wir nun zu Ihrer Frage zurück, wie wir die Flüsse verfolgen können, die durch Zweigzweige fließen. Dies führt uns zu einem Thema namens Implizite Flüsse oder Implizite Flüsse. Ein impliziter Stream tritt normalerweise auf, wenn Sie einen infizierten Wert haben, der sich auf die Zuweisung einer anderen Variablen auswirkt, auch wenn diese implizite Stream-Variable keine Variablen direkt zuweist. Ich werde ein konkretes Beispiel geben.
Angenommen, Sie haben eine if-Anweisung, die sich Ihre IMEI ansieht und sagt: "Wenn sie größer als 42 ist, werde ich x = 0 zuweisen, andernfalls werde ich x = 1 zuweisen."
Interessanterweise betrachten wir zuerst vertrauliche IMEI-Daten und vergleichen sie mit einer bestimmten Zahl. Wenn wir dann x zuweisen, weisen wir nichts zu, was direkt aus diesen vertraulichen Daten erhalten würde.

Dies ist ein Beispiel für einen der impliziten Threads. Der Wert von x hängt wirklich vom obigen Vergleich ab, aber der Gegner kann, wenn er klug ist, seinen Code so erstellen, dass keine direkte Verbindung darin verfolgt werden kann.
Bitte beachten Sie, dass Sie auch hier, anstatt nur x = 0, x = 1 zuzuweisen, einfach den Befehl zum Senden von etwas über das Netzwerk eingeben können, dh Sie können über das Netzwerk sagen, dass x = 0 oder x = 1, oder so ähnlich. Dies ist ein Beispiel für einen dieser impliziten Threads, die ein System wie TaintDroid nicht steuern kann. Dies wird also als impliziter Stream bezeichnet, im Gegensatz zu einem expliziten Stream, beispielsweise einem Zuweisungsoperator. Entwickler sind sich dieses Problems bewusst.
Wenn ich es richtig verstanden habe, haben sie mich gefragt, was passieren würde, wenn wir eine Art Maschinenfunktion haben, die etwas Ähnliches wie im obigen Beispiel tut, und daher muss das TaintDroid-System dies nicht wissen, da TaintDroid nicht in der Lage ist, in diesen Maschinencode zu schauen und Dinge zu sehen diese Art. Übrigens behaupten die Entwickler, dass sie dies mit maschinenorientierten Methoden steuern werden, die von der virtuellen Maschine selbst bestimmt werden, und sie werden die Art und Weise berücksichtigen, wie diese Methode implementiert wird. Zum Beispiel nehmen wir diese beiden Zahlen und geben dann ihren Durchschnittswert zurück. In diesem Fall vertraut das TaintDroid-System der Maschinenfunktion, daher müssen wir herausfinden, wie die entsprechende Richtlinie für Taint-Infektionen aussehen sollte.
Sie haben jedoch Recht, dass die von den Autoren von TaintDroid erfundenen manuellen Richtlinien diesen impliziten Stream möglicherweise nicht abfangen, wenn so etwas im Maschinencode versteckt war und aus irgendeinem Grund keiner offenen Revision unterzogen wurde. In der Tat kann dies dazu führen, dass die Informationen irgendwie auslaufen. Darüber hinaus kann es sogar einen direkten Stream geben, den die Autoren von TaintDroid nicht bemerkt haben, und wir haben möglicherweise ein noch direkteres Leck.
Student: Das heißt, in der Praxis scheint es sehr gefährlich zu sein, oder? Weil Sie buchstäblich alle infizierten Werte löschen können, indem Sie einfach die letzten 3 Zeilen betrachten.
Professor: Wir hatten mehrere Klassen, die untersuchten, wie implizite Flüsse solche Dinge tun. Es gibt verschiedene Möglichkeiten, dies zu beheben. Eine Möglichkeit, dies zu verhindern, besteht darin, dem PC ein Taint-Tag zuzuweisen, das ihn im Wesentlichen mit dem Branch-Test infiziert. Die Idee ist, dass wir aus menschlicher Sicht diesen Code betrachten und sagen können, dass dieser implizite Strom hier existiert, denn um hierher zu gelangen, mussten wir uns mit vertraulichen Daten befassen.
Was bedeutet das auf Implementierungsebene? Dies bedeutet, dass der PC über etwas verfügen muss, das mit vertraulichen Daten infiziert ist, um hierher zu gelangen. Das heißt, wir können sagen, dass wir diese Daten erhalten haben, weil der PC hier installiert wurde - x = 0 - oder hier - x = 1.
Im Allgemeinen kann man sich vorstellen, dass das System einige Analysen durchführt und herausfindet, dass der PC mit impliziten Datenströmen an dieser Stelle nicht infiziert ist. Dann nimmt es die Infektion von IMEI auf und an diesem Punkt, an dem x = 0 ist, ist der PC bereits infiziert. Am Ende passiert, wenn x eine Variable ist, die anfänglich ohne Makel angezeigt wird, dann sagen wir: "OK, an diesem Punkt x = 0 erhalten wir die Infektion vom PC, der oben tatsächlich infiziert wurde, in IMEI." Hier gibt es einige Feinheiten, aber im Allgemeinen können Sie nachverfolgen, wie der PC installiert ist, und dann versuchen, die Infektion auf die Zielbetreiber zu übertragen.
Das ist klar? Wenn Sie mehr wissen möchten, können wir über dieses Thema sprechen, da ich viel über diese Art von Forschung geforscht habe. Das soeben beschriebene System ist jedoch möglicherweise wieder zu konservativ. Stellen Sie sich vor, anstelle von x = 1 haben wir hier wie oben auch x = 0. In diesem Fall ist es nicht sinnvoll, x mit etwas zu infizieren, das mit IMEI zusammenhängt, daher können keine Informationen aus diesen Zweigen austreten.
Wenn Sie jedoch ein computergestütztes PC-Infektionsschema verwenden, können Sie überschätzen, wie viele x-Variablen beschädigt wurden. Es gibt einige Feinheiten, die Sie tun können, um einige dieser Probleme zu umgehen, aber es wird ein bisschen schwierig.
Student: Wenn Sie die if-Anweisung beenden, verlassen Sie auch Branch und entfernen sich von Infektionen?
Professor: In der Regel, ja, sobald der Satz von Variablen endet, wird der PC von Infektionen befreit. Eine Infektion wird nur innerhalb dieser Zweige von x bis x festgestellt. Der Grund ist, dass wenn Sie hier runter gehen, Sie es tun, egal was die IMEI war.

Wir haben darüber gesprochen, wie nützlich, wenn auch sehr teuer, die Verfolgung von Infektionen auf diesem sehr niedrigen Niveau ist, da Sie damit wirklich sehen können, wie lange Ihre Daten leben. Vor einigen Vorträgen haben wir darüber gesprochen, dass Schlüsseldaten häufig viel länger im Speicher bleiben, als Sie denken.
Sie können sich vorstellen, dass das Verfolgen von x86- oder ARM-Infektionen zwar recht teuer ist, Sie dies jedoch zur Überwachung Ihres Systems verwenden können. Sie können beispielsweise einen geheimen Schlüssel infizieren, den ein Benutzer eingegeben hat, und sehen, wo und wie er sich im gesamten System bewegt. Dies ist eine Offline-Analyse, die keine Auswirkungen auf Benutzer hat. Daher ist es normal, dass sie langsam sein kann. Eine solche Analyse hilft beispielsweise herauszufinden, dass diese Daten in den Tastaturpuffer fallen, dies an einen externen Server, dies an einem anderen Ort. Selbst wenn es sich um einen langsamen Prozess handelt, kann er dennoch sehr nützlich sein.
Wie gesagt, eine nützliche Funktion von TaintDroid ist, dass es das „Universum“ von Infektionsquellen und Absorbern infizierter Informationen begrenzt. Aber als Entwickler möchten Sie wahrscheinlich eine genauere Kontrolle über die Infektionsmarkierungen haben, mit denen Ihr Programm interagiert. Daher möchten Sie als Programmierer Folgendes tun.
Sie deklarieren also ein Int dieser Art, nennen es X und binden dann ein Label daran. Die Bedeutung dieses Etiketts ist, dass Alice die Eigentümerin der Informationen ist, die Bob anzeigen darf, oder dass diese Informationen von Bob zum Anzeigen markiert sind. TaintDroid erlaubt Ihnen dies nicht, da es im Wesentlichen dieses Universum von Beschriftungen steuert. Als Programmierer möchten Sie dies jedoch möglicherweise tun.
Angenommen, Ihr Programm verfügt über Eingangs- und Ausgangskanäle, die auch beschriftet sind. Dies sind die Bezeichnungen, die Sie als Programmierer ausgewählt haben, im Gegensatz zum System selbst, um zu sagen, dass solche Dinge im Voraus festgelegt sind. Angenommen, Sie legen für Eingangskanäle Lesewerte fest, die die Kanalbezeichnung erhalten.

Dies ist der Funktionsweise von TaintDroid sehr ähnlich. Wenn die GPS-Sensorwerte gelesen werden, werden sie mit dem Taint-Tag des GPS-Kanals markiert. Jetzt wählen Sie als Programmierer diese Beschriftungen selbst aus. In diesem Fall sollte die Beschriftung des Ausgangskanals mit dem von uns aufgezeichneten Beschriftungswert übereinstimmen.

Andere Richtlinien können hier eingeführt werden, aber die Hauptidee ist, dass es Programmmanager gibt, die den Entwickler die Wahl der Art der Beschriftungen und ihrer Semantik überlassen. Dies erfordert viel Arbeit vom Programmierer, was zur Folge hat, dass eine statische Prüfung durchgeführt werden kann. Mit statisch meine ich eine Überprüfung, die zur Kompilierungszeit durchgeführt wird und viele Arten von Informationsflussfehlern "abfangen" kann.
Wenn Sie also alle Netzwerkkanäle und Bildschirmkanäle sorgfältig mit Beschriftungen mit den entsprechenden Berechtigungen kennzeichnen und dann Ihre Daten, die als Beispiel angegeben sind, sorgfältig auf der Tafel platzieren, kann der Compiler Ihnen während der Kompilierung sagen: „Hey, wenn Sie dieses Programm ausführen, Dann kann es zu einem Informationsleck kommen, da ein Teil der Daten über einen nicht vertrauenswürdigen Kanal geleitet wird. “
Auf hoher Ebene kann eine statische Überprüfung viele dieser Fehler auffangen, da solche int {Alice Bob} x -Kommentare ein bisschen wie Typen sind. So wie Compiler typbezogene Fehler in einer Typensprache abfangen können, können sie auch mit Code in der oben genannten Sprache funktionieren. Wenn Sie dieses Programm ausführen, kann dies ein Problem sein. Daher müssen Sie die Funktionsweise von Beschriftungen korrigieren, möglicherweise etwas deklassieren und so weiter.
Abhängig von der Sprache können diese Bezeichnungen daher Personen, E / A-Ports und dergleichen zugeordnet werden. TaintDroid bietet Ihnen die Möglichkeit, sich mit den Funktionsprinzipien von Informationsflüssen und Informationslecks vertraut zu machen. Es gibt jedoch komplexere Systeme mit einer ausgeprägteren Semantik für die Verwaltung dieser Prozesse.

Beachten Sie, dass es bei statischen Überprüfungen vorzuziehen ist, möglichst viele Fehler und Irrtümer mithilfe statistischer Überprüfungen und nicht mithilfe dynamischer Überprüfungen zu erfassen. Dafür gibt es einen sehr heiklen Grund. Angenommen, wir verschieben alle statischen Überprüfungen für die Dauer eines Programms, was wir definitiv tun können.
Das Problem ist, dass der Fehler oder Erfolg dieser Überprüfungen ein impliziter Kanal ist. Auf diese Weise kann ein Angreifer dem Programm einige Informationen zur Verfügung stellen und dann prüfen, ob das Programm dadurch abgestürzt ist. Wenn ein Fehler auftritt, kann der Hacker sagen: "Ja, wir haben eine dynamische Überprüfung des Informationsflusses durchgeführt, daher gibt es hier ein Geheimnis bezüglich der Werte, die den Berechnungsprozess beeinflussen." Daher sollten Sie versuchen, diese Überprüfungen so statisch wie möglich zu gestalten.
Wenn Sie weitere Informationen zu diesen Dingen wünschen, sollten Sie sich Jif ansehen. Dies ist ein sehr leistungsfähiges System, das Etikettenberechnungsmethoden erstellt hat. Sie können damit beginnen und sich weiter in diese Richtung bewegen. Mein Kollege, Professor Zeldovich, hat auf diesem Gebiet viel Gutes getan, sodass Sie mit ihm über dieses Thema sprechen können.
Interessanterweise ist TaintDroid in seiner Fähigkeit, Tags anzuzeigen und zu beschreiben, sehr eingeschränkt. Es gibt Systeme, mit denen Sie leistungsfähigere Aufgaben ausführen können.
Abschließend möchte ich darüber sprechen, was wir tun können, wenn wir den Informationsfluss mit herkömmlichen Programmen oder mit in C oder C ++ geschriebenen Programmen verfolgen möchten, die all diese Dinge bei der Codeausführung nicht unterstützen. Es gibt ein sehr vernünftiges TightLip-System, und einige der Autoren desselben Artikels überlegen, wie Informationslecks in einem System verfolgt werden können, in dem wir nichts an der Anwendung selbst ändern möchten.
Die Grundidee ist, dass hier das Konzept von Doppelgängerprozessen oder "Prozessgegenstücken" verwendet wird. TightLip verwendet standardmäßig einen Prozessdoppel. Als erstes scannt sie regelmäßig das Dateisystem des Benutzers nach vertraulichen Dateitypen. Es kann sich um E-Mail-Dateien, Textdokumente usw. handeln. Für jede dieser Dateien erstellt das System die "bereinigte" Version. Das heißt, in der E-Mail-Nachrichtendatei werden die Informationen "bis" oder "von" durch eine Zeichenfolge gleicher Länge ersetzt, die Dummy-Daten enthält, z. B. Leerzeichen. Dies wird als Hintergrundprozess ausgeführt.
Das zweite, was TightLip beim Starten eines Prozesses tut, ist festzustellen, ob der Prozess versucht, auf eine vertrauliche Datei zuzugreifen. Wenn ein solcher Zugriff stattfindet, erstellt TightLip ein Doppel dieses Prozesses. Dieser Look-Alike sieht genauso aus wie der ursprüngliche Prozess, bei dem versucht wird, vertrauliche Daten zu beeinflussen. Der grundlegende Unterschied besteht jedoch darin, dass der Look-Alike, ich werde ihn als DG bezeichnen, die gelöschten Daten liest.

Stellen Sie sich vor, Sie versuchen gerade, auf Ihre E-Mail-Datei zuzugreifen. Das System erzeugt diesen neuen Prozess, Doppelgänger, genau wie das Original, aber jetzt liest es die bereinigten Daten anstelle von wirklich sensiblen Daten. Im Wesentlichen führt TightLip beide Prozesse parallel aus und überwacht sie, um zu sehen, was sie tun. , , , . , , - , , – , , , -, .

, , TightLip , . , . , , , , . , TaintDroid, , : «, , , , - ».
, , , - . TaintDroid, , - , . — , — . , , , , , .
: , - Word, , - .
: , . , . . Word. - , - , . .
: , , ? - .
: , . , , , - , . , . «» , , , .
, , , , , , , .

– , TightLip TCB, , -, . , . . , , . TightLip.
, . taint .
: , ? , ?
: ! - DG , , . , , , -, , .
, .
.
Vielen Dank für Ihren Aufenthalt bei uns. Gefällt dir unser Artikel? Möchten Sie weitere interessante Materialien sehen? Unterstützen Sie uns, indem Sie eine Bestellung
aufgeben oder Ihren Freunden empfehlen, einen
Rabatt von 30% für Habr-Benutzer auf ein einzigartiges Analogon von Einstiegsservern, das wir für Sie erfunden haben: Die ganze Wahrheit über VPS (KVM) E5-2650 v4 (6 Kerne) 10 GB DDR4 240 GB SSD 1 Gbit / s von $ 20 oder wie teilt man den Server? (Optionen sind mit RAID1 und RAID10, bis zu 24 Kernen und bis zu 40 GB DDR4 verfügbar).
VPS (KVM) E5-2650 v4 (6 Cores) 10GB DDR4 240GB SSD 1Gbps ,
.
Dell R730xd 2 mal günstiger? Nur wir haben
2 x Intel Dodeca-Core Xeon E5-2650v4 128 GB DDR4 6 x 480 GB SSD 1 Gbit / s 100 TV von 249 US-Dollar in den Niederlanden und den USA! Lesen Sie mehr über
den Aufbau eines Infrastrukturgebäudes. Klasse mit Dell R730xd E5-2650 v4 Servern für 9.000 Euro für einen Cent?