MIT-Kurs "Computer Systems Security". Vorlesung 4: „Privilegien teilen“, Teil 2

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 3
Vorlesung 2: „Kontrolle von Hackerangriffen“ Teil 1 / Teil 2 / Teil 3
Vorlesung 3: „Pufferüberläufe: Exploits und Schutz“ Teil 1 / Teil 2 / Teil 3
Vorlesung 4: „Trennung von Privilegien“ Teil 1 / Teil 2 / Teil 3

Was hatten wir sonst noch auf dieser Liste? Prozesse. Gedächtnis geschieht gleichzeitig mit dem Prozess. Wenn Sie sich also nicht in diesem Prozess befinden, können Sie nicht auf den Speicher zugreifen. Der virtuelle Speicher verbessert diese Isolation für uns perfekt. Darüber hinaus können Sie mit dem Debugging-Mechanismus in den Speicher eines anderen Prozesses "springen", wenn Sie dieselbe Benutzer-ID haben

Als nächstes haben wir das Netzwerk. Netzwerke in Unix entsprechen nicht ganz dem oben beschriebenen Modell, was teilweise darauf zurückzuführen ist, dass das Unix- Betriebssystem zuerst entwickelt wurde und dann ein Netzwerk erschien, das bald populär wurde. Es gibt ein etwas anderes Regelwerk. Daher müssen wir wirklich jemanden mit dem Netzwerk verbinden, wenn Sie das Netzwerk verwalten, oder einen Port abhören, wenn Sie als Server fungieren. Möglicherweise müssen Sie Daten über diese Verbindung lesen oder schreiben oder Rohpakete senden und empfangen.



Daher sind Netzwerke unter Unix meist nicht mit der Benutzer-ID verbunden . Die Regeln lauten, dass jeder jederzeit eine Verbindung zu einem Computer oder einer IP-Adresse herstellen oder eine Verbindung herstellen kann. Wenn Sie einen Port abhören möchten, gibt es in diesem Fall einen Unterschied: Den meisten Benutzern ist es verboten, Ports mit einer Zahl unter dem „magischen Wert“ von 1024 abzuhören. Grundsätzlich können Sie solche Ports abhören, in diesem Fall sollten Sie dies jedoch tun Sei ein spezieller Benutzer namens "Super User" mit uid = 0 .

Im Allgemeinen gibt es unter Unix das Konzept des Administrators oder Superusers, der durch die Kennung uid = 0 dargestellt wird und fast alle diese Überprüfungen umgehen kann. Wenn Sie also mit Root-Rechten arbeiten, können Sie Dateien lesen und schreiben und die Zugriffsrechte darauf ändern. Das Betriebssystem ermöglicht Ihnen dies, da es der Meinung ist, dass Sie alle Berechtigungen haben sollten. Und Sie brauchen wirklich solche Privilegien, um Ports mit der Nummer <1024 abzuhören. Was halten Sie von einer so seltsamen Einschränkung?

Zielgruppe: Es identifiziert bestimmte Portnummern für bestimmte Verbindungen, z. B. für http an Port 80.

Professor: Ja, standardmäßig verwendet das HTTP-Protokoll Port 80. Andererseits können andere Dienste Ports mit einer Nummer über 1024 verwenden. Warum ist diese Einschränkung erforderlich? Was nützt das hier?

Zielgruppe: Sie möchten nicht, dass jemand versehentlich auf Ihr HTTP hört.

Professor: Ja. Ich denke, der Grund dafür ist, dass Sie früher viele Benutzer auf demselben Computer hatten. Sie haben sich mit ihren Anmeldungen angemeldet und ihre Anwendungen gestartet. Sie wollten also sicherstellen, dass ein zufälliger Benutzer, der sich am Computer angemeldet hat, nicht auf den darauf laufenden Webserver zugreifen kann. Da Benutzer, die von außen eine Verbindung herstellen, nicht wissen, wer an diesem Port arbeitet, und nur eine Verbindung zu Port 80 herstellen. Wenn ich diesen Computer betreten und meinen eigenen Webserver starten möchte, übertrage ich einfach den gesamten Webserververkehr an dieses Auto. Dies ist wahrscheinlich kein sehr guter Plan, aber auf diese Weise verhindert das Unix-Netzwerksubsystem, dass zufällige Benutzer bekannte Dienste steuern, die auf diesen niedrigen Portnummern ausgeführt werden. Das ist der Grund für eine solche Einschränkung.



Wenn Sie unter dem Gesichtspunkt des Lesens und Schreibens von Verbindungsdaten eine Deskriptordatei für einen bestimmten Socket haben, können Sie mit Unix alle Daten in dieser TCP- oder uTP-Verbindung lesen und schreiben. Beim Senden von Rohpaketen verhält sich Unix wie ein Paranoiker, sodass Sie keine beliebigen Pakete über das Netzwerk senden können. Dies sollte im Kontext der speziellen Verbindung erfolgen, es sei denn, Sie haben root - das Recht und können tun, was Sie wollen.

Eine interessante Frage, die Sie sich stellen könnten, ist, woher all diese Benutzer-IDs stammen.

Wir sprechen über Prozesse mit Benutzer- oder Gruppen- ID . Wenn Sie PS auf Ihrem Computer starten, werden Sie definitiv eine Reihe von Prozessen mit unterschiedlichen UID- Werten sehen. Woher kamen sie?

Wir benötigen einen Mechanismus, um alle diese Benutzer-ID- Werte zu laden. Unix verfügt über mehrere Systemaufrufe, die dafür ausgelegt sind. Um diese Bezeichnerwerte zu booten , gibt es daher eine Funktion namens setuid (uid) , sodass Sie diesem Wert die UID- Nummer eines aktuellen Prozesses zuweisen können. Dies ist tatsächlich eine gefährliche Operation, wie alles andere in der Unix- Tradition, da Sie dies nur tun können, wenn Ihre UID = 0 ist . In jedem Fall sollte es so sein.

Wenn Sie also ein Benutzer mit Root-Rechten sind und uid = 0 haben , können Sie setuid (uid) aufrufen und den Benutzer zu einem beliebigen Prozess wechseln. Es gibt einige ähnliche Systemaufrufe zum Initialisieren prozessbezogener GIDs : Setgid und Setgroups . Daher können Sie mit diesen Systemaufrufen Prozessberechtigungen konfigurieren.



Die Tatsache, dass Ihre Prozesse die richtigen Zugriffsrechte erhalten, wenn Sie sich am Unix- Computer anmelden, tritt nicht auf, weil Sie dieselbe ID wie die Prozesse haben, weil das System noch nicht weiß, wer Sie sind. Stattdessen gibt es unter Unix eine Art Anmeldeverfahren, wenn das SSH Secure Shell- Protokoll den Prozess für jeden startet, der eine Verbindung zum Computer herstellt und versucht, den Benutzer zu authentifizieren.

Daher beginnt dieser Anmeldevorgang zunächst mit uid = 0 wie für einen Benutzer mit Root-Rechten. Wenn er einen bestimmten Benutzernamen und ein bestimmtes Kennwort erhält, überprüft er diese in seiner eigenen Kontodatenbank. Unter Unix werden diese Daten in der Regel in zwei Dateien gespeichert: / etc / password (aus historischen Gründen werden Kennwörter nicht mehr in dieser Datei gespeichert) und in der Datei / etc / shadow , in der Kennwörter gespeichert sind. In der Datei / etc / password befindet sich jedoch eine Tabelle, in der jeder Benutzername im System als ganzzahliger Wert angezeigt wird.

Daher wird Ihr Benutzername einer bestimmten Ganzzahl in dieser / etc / password- Datei zugeordnet, und der Anmeldevorgang prüft, ob Ihr Passwort gemäß dieser Datei korrekt ist. Wenn es Ihre ganzzahlige UID findet , setzt es die Setuid- Funktionen auf diesen UID- Wert und startet die Shell mit dem Befehl exec (/ bin / sh) . Jetzt können Sie mit der Shell interagieren, diese funktioniert jedoch unter Ihrer UID , sodass Sie diese Maschine nicht versehentlich beschädigen können.



Zielgruppe: Ist es möglich, einen neuen Prozess mit uid = 0 zu starten, wenn Ihre uid nicht wirklich 0 ist?

Professor: Wenn Sie Root-Rechte haben, können Sie sich auf eine andere UID beschränken , Ihre Autorität verringern , aber in jedem Fall können Sie einen Prozess mit nur derselben UID wie Ihrer erstellen. Es kommt jedoch vor, dass Sie aus verschiedenen Gründen Ihre Berechtigungen erhöhen möchten. Angenommen, Sie müssen ein Paket installieren, für das Sie Root- Rechte benötigen.

Es gibt zwei Möglichkeiten, Berechtigungen für Unix festzulegen . Eine, die wir bereits erwähnt haben, ist ein Dateideskriptor. Wenn Sie also Ihre Berechtigungen wirklich erhöhen möchten, können Sie mit jemandem sprechen, der unter Root-Rechten arbeitet, und ihn bitten, diese Datei für Sie zu öffnen. Oder Sie müssen eine neue Schnittstelle installieren, dann öffnet dieser Assistent eine Datei für Sie und gibt Ihnen mithilfe der fd- Übertragung einen Dateideskriptor zurück. Dies ist eine Möglichkeit, Ihre Berechtigungen zu erhöhen, ist jedoch unpraktisch, da in einigen Fällen Prozesse mit einer großen Anzahl von Berechtigungen ausgeführt werden. Dafür verfügt Unix über einen intelligenten, aber gleichzeitig problematischen Mechanismus namens "setuid binaries" . Dieser Mechanismus ist eine reguläre ausführbare Datei in einem Unix- Dateisystem, es sei denn, Sie führen exec auf der setuid- Binärdatei aus, z. B. / bin / su auf den meisten Computern oder sudo beim Start.

Ein typisches Unix- System verfügt über eine Reihe von Setuid- Binärdateien. Der Unterschied besteht darin, dass beim Ausführen einer dieser Binärdateien die Benutzer-ID des Prozesses tatsächlich auf den Eigentümer dieser Binärdatei umgeschaltet wird. Dieser Mechanismus scheint seltsam, wenn Sie ihn zum ersten Mal sehen. In der Regel besteht die Möglichkeit darin, dass diese "Binärdatei" höchstwahrscheinlich eine Eigentümer- UID von 0 hat, da Sie wirklich viele Berechtigungen wiederherstellen möchten.



Sie möchten die Superuser-Rechte wiederherstellen, damit Sie diesen Befehl su ausführen können, und der Kernel schaltet beim Ausführen dieser Binärdatei die Prozess- UID auf 0, sodass dieses Programm nun einige privilegierte Aktionen ausführt.

Zielgruppe: Wenn Sie uid = 0 haben und die uid all dieser setuid- Binärdateien auf etwas anderes als 0 ändern, können Sie Ihre Berechtigungen wiederherstellen?

Professor: Nein, viele Prozesse können beim Verringern der Zugriffsebene keine Berechtigungen wiederherstellen, sodass Sie möglicherweise an dieser Stelle stecken bleiben. Dieser Mechanismus ist nicht an uid = 0 gebunden. Wie jeder Benutzer eines Unix- Systems können Sie eine beliebige Binärdatei erstellen, ein Programm erstellen, kompilieren und dieses Setuid- Bit auf das Programm selbst setzen. Es gehört Ihnen, dem Benutzer, Ihrer Benutzer-ID. Und das bedeutet, dass jeder, der Ihr Programm ausführt, diesen Code mit Ihrer Benutzer-ID ausführt. Gibt es ein Problem damit? Was muss getan werden?

Zielgruppe: Wenn also ein Fehler in Ihrer Bewerbung aufgetreten ist, kann jemand etwas damit anfangen und mit Ihren Privilegien handeln?

Professor: Richtig, es passiert, wenn meine Anwendung "fehlerhaft" ist oder wenn Sie damit alles ausführen können, was Sie wollen. Angenommen, ich könnte die System-Shell kopieren und für mich setuid machen, aber dann kann jeder diese Shell unter meinem Konto ausführen. Dies ist wahrscheinlich nicht der beste Aktionsplan. Ein solcher Mechanismus verursacht jedoch kein Problem, da die einzige Person, die das setuid- Bit für eine Binärdatei setzen kann, der Eigentümer dieser Datei ist. Sie als Eigentümer der Datei haben das UID- Privileg, sodass Sie Ihr Konto auf eine andere Person übertragen können. Diese andere Person kann die setuid- Binärdatei jedoch nicht mit Ihrer Benutzer-ID erstellen.

Dieses Setuid-Bit wird neben diesen Berechtigungsbits gespeichert, dh in jedem Inode befindet sich auch ein Setuid- Bit, das angibt , ob diese ausführbare Datei während der Ausführung auf die Eigentümer- UID umgeschaltet werden soll oder nicht.



Es stellt sich heraus, dass dies bei korrekter Verwendung ein sehr kniffliger Mechanismus ist, und dank dessen implementiert der Kernel das Programm korrekt. Dies ist eigentlich recht einfach, da nur eine Prüfung durchgeführt wird: Wenn dieses Setuid- Bit vorhanden ist, wechselt der Prozess zu UID . Es ist ziemlich einfach.

Die sichere Verwendung ist jedoch recht schwierig, da Sie, wie bereits erwähnt, unter uid = 0 oder unter einer anderen uid beliebige Aktionen ausführen können , wenn dieses Programm Fehler enthält oder unerwartete Aktionen ausführt . Unter Unix erben Sie beim Ausführen eines Programms viele Dinge von Ihrem übergeordneten Prozess.

Beispielsweise können Sie Umgebungsvariablen an setuid- Binärdateien übergeben. Tatsache ist, dass Sie unter Unix angeben können, welche gemeinsam genutzte Bibliothek für den Prozess verwendet werden soll, indem Sie die Umgebungsvariable festlegen. Setuid- Binärdateien kümmern sich nicht um das Filtern dieser Umgebungsvariablen.

Sie können beispielsweise bin / su ausführen, aber gemeinsam genutzte Bibliotheken für die Funktion printf verwenden, sodass Ihre printf startet, wenn bin / su etwas druckt, und Sie können die Shell anstelle von printf ausführen.

Es gibt viele Feinheiten, die Sie in Bezug auf das Misstrauen des Programms gegenüber den vom Benutzer eingegebenen Daten richtig verstehen müssen. Da Sie normalerweise Benutzereingaben vertrauen, war setuid nie der sicherste Teil eines gesamten Unix- Systems. Haben Sie Fragen dazu?

Zielgruppe: Gilt setuid auch für Gruppen oder nur für den Benutzer?

Professor: Es gibt ein Setgid- Bit, das symmetrisch zum Setuid- Bit ist und das Sie auch setzen können. Wenn die Datei eine bestimmte GID hat und dieses Setgid- Bit beim Starten des Programms gesetzt ist, erhalten Sie es.

Setgid wird nicht besonders verwendet, kann jedoch in Fällen nützlich sein, in denen Sie ganz bestimmte Berechtigungen bereitstellen möchten. Zum Beispiel benötigt bin / su wahrscheinlich viele Berechtigungen, aber vielleicht gibt es ein Programm, das einige zusätzliche Berechtigungen benötigt, um beispielsweise etwas in eine spezielle Protokolldatei zu schreiben. Daher möchten Sie ihr wahrscheinlich eine bestimmte Gruppe zur Verfügung stellen und eine Protokolldatei für sie erstellen, die von dieser Gruppe geschrieben werden kann. Selbst wenn das Programm "fehlerhaft" ist, verlieren Sie nichts anderes als diese Gruppe. Dies ist nützlich als Mechanismus, der aus irgendeinem Grund nicht zu oft verwendet wird, da die Benutzer schließlich mehr Root-Rechte verwenden sollten.

Zielgruppe: Gibt es Einschränkungen, wer den Zugriff ändern kann?

Professor: Ja. Unterschiedliche Unix- Implementierungen haben hierfür unterschiedliche Prüfungen. Die allgemeine Regel lautet, dass nur root den Eigentümer der Datei ändern kann, da Sie keine Dateien erstellen möchten, die jemand anderem gehören, und natürlich nicht die Dateien anderer Personen verwenden möchten. Wenn Ihre UID also nicht 0 ist, stecken Sie fest. Sie können den Besitz einer Datei nicht ändern. Wenn Ihre UID = 0 ist , haben Sie Root-Rechte und können den Eigentümer in einen beliebigen ändern. Es gibt einige Komplikationen, wenn Sie eine binäre Setuid haben und von einer UID zu einer anderen wechseln. Dies ist ziemlich schwierig, aber im Grunde können Sie den Dateibesitzer nicht grundsätzlich ändern, wenn Sie keine Root-Rechte haben.

In jedem Fall ist dies ein leicht veraltetes System. Sie können sich wahrscheinlich viele Möglichkeiten vorstellen, die oben beschriebenen Prozesse zu vereinfachen, aber tatsächlich sehen die meisten fortschrittlichen Systeme so aus, weil sie sich im Laufe der Zeit weiterentwickeln. Sie können diese Mechanismen jedoch perfekt als "Sandbox" verwenden.

Dies sind nur einige grundlegende Unix- Prinzipien, die in fast jedem Unix-ähnlichen Betriebssystem vorkommen: Mac OS X , Linux , FreeBSD , Solaris , wenn jemand anderes sie verwendet, und so weiter. Jedes dieser Systeme verfügt jedoch über ausgefeiltere Mechanismen, die Sie verwenden können. Unter Linux gibt es beispielsweise ein "Sandbox" -Set COMP , Mac OS X verwendet den "Sandbox" -Sicherheitsgurt . Nächste Woche werde ich Ihnen Beispiele für Sandboxen geben, die auf jedem Unix- basierten System verfügbar sind.

Einer der letzten Mechanismen, die wir vor dem Eintauchen in OKWS berücksichtigen werden , erklärt, wie Sie mit Setuid- Binärdateien umgehen müssen, und zeigt, wie Sie sich vor vorhandenen Sicherheitslücken schützen können. Das Problem ist, dass Sie zwangsläufig einige Setuid- Binärdateien auf Ihrem System haben, wie z. B. / bin / su oder sudo oder etwas anderes, und es ist wahrscheinlich, dass Ihre Programme Fehler aufweisen. Aus diesem Grund kann jemand die setuid- Binärdatei ausführen und der Prozess kann Root- Zugriff erhalten, den Sie nicht zulassen möchten.



Der Unix- Mechanismus, der häufig verwendet wird, um die Ausführung eines potenziell böswilligen Prozesses mithilfe von Setuid- Binärdateien zu verhindern, besteht darin, ihn mithilfe des Dateisystem-Namespace mithilfe des Chroot- Systemaufrufs zu ändern. Dabei wird das Stammverzeichnis geändert. OKWS als Webserver, der sich auf die Erstellung schneller und sicherer Webdienste spezialisiert hat, nutzt dies in großem Umfang .



Unter Unix können Sie chroot also in einem bestimmten Verzeichnis ausführen. Vielleicht können Sie auch chroot ("/ foo") ausführen.

Es gibt 2 Erklärungen dafür, was Chroot macht. Das erste ist nur intuitiv, dh nach dem Ausführen von chroot entspricht das Stammverzeichnis oder das Verzeichnis hinter dem Schrägstrich im Wesentlichen dem, was / foo verwendet hat, bevor Sie chroot aufgerufen haben. Es sieht so aus, als würde der Namespace unter Ihrem / foo eingeschränkt . Wenn Sie also eine Datei haben, die früher / foo / x genannt wurde , können Sie diese Datei nach dem Aufruf von chroot einfach durch Öffnen von / x abrufen . Beschränken Sie Ihren Namespace also einfach auf ein Unterverzeichnis. Hier ist die intuitive Version.



Aus Sicherheitsgründen ist natürlich nicht die intuitive Version von Bedeutung, aber was genau macht der Kernel mit diesem Systemaufruf? Und es macht im Grunde zwei Dinge. Erstens ändert sich der Wert dieses Schrägstrichs. Wenn Sie also auf den Verzeichnisnamen zugreifen oder ihn mit einem Schrägstrich beginnen, enthält der Kernel alle Dateien, die Sie mit Chroot- Operationen bereitgestellt haben. In unserem Beispiel ist dies die Datei / foo, bevor Sie chroot aufgerufen haben, dh wir erhalten diese / = / foo .



Das nächste, was der Kernel versuchen wird, ist, Sie davor zu schützen, aus Ihrem / "entkommen" zu können, wenn Sie dies tun /../ . Denn unter Unix könnte ich Sie bitten, mir zum Beispiel /../etc/password zu geben . Wenn ich diese Zeile also wie folgt ergänzen würde: /foo/../etc/password , wäre das nicht gut, da ich einfach / foo beenden und / etc / password abrufen könnte.

Das zweite, was der Kernel mit einem Unix- Systemaufruf macht, ist, dass wenn Sie chroot für diesen bestimmten Prozess aufrufen, sich die Art und Weise ändert, wie /../ in diesem Verzeichnis ausgewertet wird. Daher ändert es /../ so, dass / foo auf sich selbst zeigt. Auf diese Weise können Sie nicht „entkommen“, und diese Änderung gilt nur für diesen Prozess und wirkt sich nicht auf den Rest aus. Welche Ideen haben Sie, wie Sie mit ihrer Implementierung aus der Chroot- Umgebung „entkommen“ können?

Interessanterweise überwacht der Kernel nur ein Chroot- Verzeichnis, sodass Sie wahrscheinlich die Operation chroot = (/ foo) ausführen könnten, aber Sie würden an dieser Stelle hängen bleiben. Sie möchten / etc / password erhalten , aber wie geht das? Sie können das Stammverzeichnis jetzt öffnen, indem Sie open (* / *) eingeben. Dadurch erhalten Sie einen Dateideskriptor, der beschreibt, was / foo ist . Dann können Sie chroot erneut aufrufen und chroot (`/ bar) ausführen.



, : root /foo , /foo/bar /../ /foo / bar/..



, /foo . fchdir (fd) (*/*) , chdir (..) .





/foo , /../ . /foo , root , .

, , . . Unix root- chroot , chroot . , Unix uid = 0 , chroot . . , , chroot , userid . , Unix , , root , .

, , , . chroot — . .

: , inod , ?

: ! , , , : « inode 23», - hroot . , Unix inode inode , , , root-.

, , , OKWS . , OKWS .

, -, , - , . , , httpd , , Apache .

userid www /etc/password . , , SSL , PHP , . , , , MySQL , . MySQL . MySQL , , , .



, , , MySQL , , .

, , , , . , , , Apache oder in SSL oder vielleicht im Anwendungscode oder im PHP- Interpreter . Und da es Fehler gibt, können Sie sie verwenden, um den gesamten Inhalt der Anwendung abzurufen.

52:30 min

Fortsetzung:

MIT-Kurs "Computer Systems Security". Vorlesung 4: „Privilegien teilen“, Teil 2


Die Vollversion des Kurses finden Sie hier .

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 sie Ihren Freunden empfehlen. Habr-Benutzer erhalten 30% Rabatt 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 $ 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).

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?

Source: https://habr.com/ru/post/de418197/


All Articles