|
|
|
Nachdem wir den angenommenen Bedrohungsrahmen definiert haben, beschreiben wir folgend unseren Lösungsansatz. Wie angesprochen, beginnen wir mit einer Aufzählung der erforderlichen Voraussetzungen, die das Betriebssystem erfüllen muss.
In unserem Lösungsansatz muss das verwendete Betriebssystem gewisse Kriterien erfüllen. Folgend listen und erläutern wir zwingend notwendige Punkte, die für eine korrekte Umsetzung erforderlich sind.
Eine triviale aber notwendige Annahme lautet: das Betriebssystem unterscheidet zwischen privilegiertem und normalen Zugriffsrecht. Normale Benutzer haben nur eingeschränkten Zugriff auf das System. Einzig die Systemverwalter haben Zugang zu Superuser-Privilegien. Das ist unter Unix-Systemen Standard.
Dem Betriebssystem muss ein normaler Benutzer mit dem Login ainst bekannt sein. Es besteht theoretisch die freie Wahl eines Namens. Das Abweichen der Vorgabe erzwingt jedoch eine Anpassung unserer Skript-Datei. Üblicherweise sollte der erstellte Benutzer einer gleichlautenden Benutzergruppe ainst angehören. Weiter Gruppenzugehörigkeiten sind auszuschließen, da sie nicht notwendig sind. Die Authentifizierung zum erstellten Konto sollte durch ein Passwort geschützt sein. Die Komplexität ist möglichst stark zu wählen. Es sollte für andere Benutzer nicht erratbar sein, denn unter Umständen hat dieser Benutzer Zugriff auf schädliche Daten. Da die Eingabe des Passwortes nie erforderlich sein wird, kann dies ohne Komfortverlust geschehen. Ferner muss für diesen Benutzer kein Heimatverzeichnis angelegt sein. Ein wichtiger Punkt ist das eingetragene Login-Kommando für ainst. Es steht in der Datei /etc/passwd und muss die Shell /bin/bash beinhalten.
Aus technischer Sicht besteht kein Zwang dazu sich auf die Verwendung von apt-get und dpkg zu beschränken. Eine Erweiterung um andere Paketmanager ist mit entsprechenden Anpassungen prinzipiell möglich. Unser Lösungsansatz orientiert sich jedoch an diesen Werkzeugen und daher sehen wir die Verwendung dieser Paketverwalter als erforderlich an.
Der Kernel des Betriebssystems muss das Dateisystem aufs2 beinhalten. Zum Zeitpunkt des Schreibens enthält keine größere Distribution aufs2 im Standard. Notwendigerweise sollte daher der eigene Kernel um aufs2 erweitert, kompiliert und installiert werden. Ungeachtet der Umsetzung, die vollständige Gewährleistung der Funktionalität des aufs2 Dateisystems ist zwingend erforderlich.
Durch das Verfahren zum Kompilieren eines eigenen Kernels, wird das Betriebssystem üblicherweise um das Paket fakeroot erweitert. Diese Tatsache unterscheidet sich aber innerhalb der Distributionen. Auch gibt es zu jeder Distribution diverse Anleitungen zum Erstellen eines eigenen Kernels. Entsprechend variieren die dazu verwendeten Pakte. Zur Klarstellung erwähnten wir an dieser Stelle den Bedarf dieses Pakets explizit.
Zu Beginn der Erläuterungen zum Verfahren, präsentieren wir einen Überblick des Ablaufs einer kontrollierten Software-Installation. Er ist in drei Phasen eingeteilt. In der Initialisierungs-Phase erstellt das Betriebssystem eine virtuelle Umgebung und bezieht die Softwarepakete. Die darauf folgende Schleifen-Phase installiert das Paket virtuell (virtuell bedeutet hierbei ohne das echte Betriebssystem zu modifizieren). Für diesen Vorgang können mehrere Anläufe nötig sein. Die Abschluss-Phase generiert eine Zusammenfassung der durchgeführten Änderungen in Form eines Berichts. Unter den geltenden Bedingungen des vorher gehenden Abschnitts, zeigen wir nun den Verlauf einer kontrollierten Software-Installation auf einem Linux-System. Dabei erörtern wir die angesprochenen Phasen möglichst präzise und ergänzen an geeigneter Stelle.
Der Benutzer ist mit Superuser-Privilegien authentifiziert und ruft das Shell-Skript cinstall.sh zur Durchführung einer kontrollierten Software-Installation von paket auf (paket als Platzhalter für den eigentlichen Paketnamen). Dieser Aufruf erfolgt über die Konsole per Parameterübergabe. Es wird ein neuer Prozess der Shell gestartet, der damit beginnt das Skript zu interpretieren und auszuführen. Die darin enthaltenen Anweisungen werden unter root-Privilegien ausgeführt.
Zunächst prüft cinstall, ob paket nicht bereits virtuell Installiert ist. Es verweigert mehrere Installationen des gleichen Paketes. Eine weitere Installation macht keinen Sinn: es entstünde der selbe Bericht. Die Datei .pakets enthält Einträge der aktuell bestehenden virtuellen Installationen und wird zur Verwaltung genutzt. Veranlasst die Überprüfung keinen Abbruch, wird im Verzeichnis von cinstall ein Ordner mit dem Namen paket/ angelegt. Zwei weitere Ordner paket/rw/ und paket/aufs/ werden dem hinzugefügt. Anschließend listet das Skript alle Namen der unter dem Wurzelverzeichnis “/“ angelegten Ordner. Es legt sowohl unter paket/rw/als auch paket/aufs/ leere Verzeichnisse mit den gefilterten, gelisteten Namen an.
Zwei Ursachen veranlassen die Filterung einiger Ordner. Eine davon hängt mit der virtuelle Umgebung zusammen, die cinstall anschließend mit Hilfe von aufs2 erzeugt. Diese virtuelle Umgebung definieren wir wie folgt: es soll die vollständige Dateistruktur des echten Betriebssystems vorhanden sein, welche als rr-branch einzubinden ist. Damit Änderungen daran möglich sind, benötigt man einen rw-branch. Aber aufs2 gestattet es nicht, dass ein branch Vorfahre oder Nachfahre eines anderen branch ist. Dies führt zu Überlappung und ist verboten [Oka10]. Daher kann das Wurzelverzeichnis nicht einfach als rr-branch eingebunden werden, denn das nötige rw-branch wäre zwangsläufig ein Nachfahre. Wir lösen dieses Problem, indem wir die einzelnen Ordner unterhalb von “/“ als rr-branch heranziehen. Für jedes Verzeichnis benötigen wir ein rw-branchund einen virtuellen Ordner, der die virtuelle Ansicht ermöglicht. Die zuvor erstellten Verzeichnisse paket/rw/ und paket/aufs/ dienen diesem Zweck. Wir halten fest, dass wir die Ordner innerhalb der Verzeichnisstruktur von cinstall anlegen. Da aber auch das Basisverzeichnis von cinstall sich unter “/“ befindet, muss dieses notwendigerweise herausgefiltert werden. Der weitere Grund zur nötigen Filterung hängt mit manchen Dateisystemen zusammen. Die beschriebene Inkompatibilität von aufs2 führt zur zwangsläufigen Filterung der Ordner /proc und /sys (für Unbuntu Derivate ist /sys typisch, gehört aber nicht zum Standard[Fis10]).
Ferner müssen wir noch den Ordner _sanity/ betrachten, der Bestandteil der kontrollierten Software-Installation ist und sich im Basisordner befindet. Tatsächlich prüft cinstall für jeden ungefilterten Ordnernamen _sanity/ auf Existenz eines gleichlautenden Verzeichnis. Falls vorhanden, fügt das Skript dieses als zweiten rr-branch zum Zusammenschluss hinzu. Eine nähere Erläuterung zu _sanity/ findet im nächsten Abschnitt statt. Folgende Abbildung 4.1 verdeutlicht den logischen Zusammenhang der angesprochenen Ordner.
Abbildung 4.1: Die aufs2 Zusammenschlüsse bestehen aus paket/rw/*, optional_sanity/* und den Ordnern des Betriebssystems "/" unter den Ansichten inpaket/aufs/*
Für die unterhalb von paket/ angelegten Ordner trägt cinstall den Benutzer ainst als Besitzer ein. Die Benutzergruppe und Andere erhalten keine Berechtigungen. Wir stellen damit sicher, dass aus dem Kreis der normalen Benutzer kein Zugriff erfolgen kann. Mit abschließenden mount ist die Erstellung der virtuellen Umgebung erfolgreich abgeschlossen. Im nächsten Schritt wenden wir die Konfigurationsdateien für paket an.
Diese zwei paketspezifischen Dateien sind zur Zeit der Initialisierung noch nicht erstellt. Sie enthalten zum einen allow Einträge und zum anderen deny Einträge. Bei den Einträgen handelt es sich um absolute Pfadangaben zu Ordnern oder Dateien des echten Betriebssystems. Unter der Vorlagedatei konfig.default.all generiert das Skript eigene Konfigurationsdateien zu jedem Paket. Nun kann die Umsetzung der Standard-Einträge erfolgen. Das Skript ändert für jeden allow Eintrag den Besitzer und Besitzergruppe zu ainst. Weiter gewährt es dem Besitzer rwx-Zugriff. Diese Modifikationen führt es in der virtuellen Ansicht durch. Somit legt letzten Endes aufs2 für jeden allow Eintrag eine Kopie im jeweiligen rw-branch an. Mit diesem Verfahren ermöglichen wir ainst volle Zugriffsrechte innerhalb der virtuellen Umgebung. Das echte Betriebssystem bleibt davon unberührt. Die deny Einträge haben an dieser Stelle keinen Einfluss auf den Ablauf. Die Anwendung der Konfigurationsdateien führt das Skript im weiteren Verlauf erneut durch. Zunächst bereitet es den Eintritt in die virtuelle Umgebung vor, um die Paketdaten aus dem Repositorie zu beziehen.
Zur Vorbereitung kopiert cinstall ein weiteres Shell-Skript rinstall.sh in den Ordnerpaket/aufs/. Dort legt es auch paket/aufs/pvars.cinstall an; die Bezeichnungen der zu installierenden Pakete sind darin enthalten. Es können durchaus mehrere Pakete in einem Aufruf kontrolliert installiert werden. Zuletzt erstellt es paket/aufs/FIRSTRUN, um rinstall zu steuern. Die virtuelle Umgebung ist somit bereit für ihren Einsatz.
Bevor wir diese Umgebung betreten, erläutern wir verwendete Linux-Befehle. Mit dem Diagnosetool strace ist es möglich die Systemaufrufe und Signale eines anzugebenden Prozesses abzufangen. Durch die Option “-“ untersucht man auch dessen Kindprozesse. Mit einer weiteren Option “-o“ leitet man die Ausgabe von strace in eine Datei um. Für chroot kann ein Ordner angegeben werden, der zum Wurzelverzeichnis für einen anzugebenden Prozess wird. Dieser mit chroot aufgerufene Prozess kann nicht mehr auf Daten außerhalb des angegebenen Verzeichnisses zugreifen. Durch su ist es möglich die Benutzerkennung zu wechseln. Mit der Option “-c“ kann man einen Befehl angeben, den die Shell unmittelbar unter der neuen Benutzerkennung ausführt. Die kombinierte Verwendung dieser Systemprogramme und das zuvor präparierte virtuelle System ermöglichen es eine kontrollierte Umgebung für Installationen zu schaffen. Folgende Abbildung 4.2 verdeutlicht die Aufrufreihenfolge.
Abbildung 4.2: Aufrufreihenfolge beim Betreten der virtuellen Umgebung unterder Kennung ainst.
Wir setzen mit chroot für su paket/aufs/ als neues Wurzelverzeichnis. Die Summe der dort enthaltenen virtuellen Ordner bildet die virtuelle Systemumgebung. In dieser findet ein Benutzerwechsel zu ainst statt. Die Option “-c ./rinstall.sh“ startet rinstall unmittelbar danach. Ein vorgestelltes strace überwacht die Systemaufrufe und schreibt diese in paket/aufs/ACCLOG. Die Flusskontrolle ist nun bei rinstall und wird mit den Privilegien von ainst ausgeführt.
Es liest die zu installierenden Pakete ein. Die Existenz von FIRSTRUN bewirkt, dass es apt-get mit der Option “-d“ startet. Benötigte Pakete werden dadurch lediglich heruntergeladen, ohne Installationsaufruf. Mit der Option “-y“ beantwortet apt-get alle Rückfragen automatisch mit ja. Somit ist ein mögliches Eingreifen durch den Benutzer nicht länger erforderlich. Vor dem Paketmanager steht ein notwendiges fakeroot (Zwar nicht zum Beziehen der Paketdaten. Aber spätestens beim Aufruf zur Installation meldet dpkg: „Angeforderte Operation benötigt Superuser-Rechte“). Dieses täuscht nachgestellten Prozessen root-Privilegien vor. Nach einem Aufruf von fakeroot wird UID und GID mit dem Wert 0 zurückgegeben. Nachdem die Pakete bezogen sind, terminiert apt-get und rinstall. Die chroot-Umgebung wird verlassen und die durch strace angefertigte Logdatei abgeschlossen. Die Flusskontrolle kehrt zurück zu cinstall. Dieses löscht zunächst FIRSTRUN. Es folgt der letzte Schritt der Initialisierungs-Phase: die Untersuchung der bezogenen Paketdateien.
Wir fokussieren nun die im rw-branch unter paket/rw/var/cache/apt/archives/ erstellten Paketdateien. Mit dpkg-deb generiert cinstall eine Liste der gepackten Dateien mit absoluter Pfadangabe. Dies geschieht ohne die entsprechenden Pakete auspacken zu müssen. Die Listen aller Paketarchive führt es zusammen und verarbeitet sie weiter. Ziel der Weiterverarbeitung ist es relevante Verzeichnisse des Betriebssystems zu erkennen, die durch das Entpacken der neuen Programmpakete betroffen sind. Beispielsweise wäre bei einem Eintrag /etc/paket/NeueDatei das Verzeichnis /etc relevant. Denn in diesem wird ein neuer Ordner paket angelegt. Die Konfigurationsdatei mit den allow Einträgen erweitert cinstall um diese relevanten Verzeichnisse. Aber nur unter Abgleich mit der deny Konfiguration, wenn es keinen Eintrag gibt, der das Hinzufügen verbietet. Stellt es Versuche deny Einträge hinzuzufügen fest, protokolliert cinstall diesen Vorfall. Zusätzlich überprüft es die zu entpackenden Archivpakete dahingehend, ob bereits bestehende Dateien überschrieben werden. Durch die schließlich angepasste Konfigurationsdatei kann man im Anschluss ein fehlerfreies Entpacken durchführen. Die Analyse der Paketdateien endet mit der Anzeige der Anzahl von neuen Ordnern und Dateien, die entpackt werden.
Zu Beginn der Schleife wendet cinstall die aktualisierte Konfigurationsdatei an. Somit werden die zum Entpacken der Paketdateien benötigen Berechtigungen gesetzt. Durch den bekannten Aufruf betritt es erneut die virtuelle Umgebung als ainst. Darin kann rinstall FIRSTRUN nicht mehr finden. Deswegen ruft es apt-get in der Schleife stets ohne die Option “-d“ auf. Die Paketdaten befinden sich bereits im lokalen Repositorie. Mit der Feststellung, dass kein weiterer Datenbezug nötig ist, endet apt-get und ruft dpkg zur Fortführung auf. Dieses prüft die Paketdaten auf mögliche „preinst“-Skripte. Falls vorhanden, werden diese zunächst ausgeführt. Danach entpackt es die Daten aus dem Paket. Optionale „postinst“-Skripte werden anschließend verarbeitet [DSKR08]. Es ist allgemein nicht bekannt, welche Modifikationen durch ein Installations-Skript getätigt werden. Daher muss man in Kauf nehmen, dass dessen Ausführung fehlschlagen kann und dpkg die Installation abbricht. Grund hierfür wären nicht ausreichende Berechtigungen in der Konfigurationsdatei. Die Installation durch dpkg kann aber auch erfolgreich terminieren. Unter welchen Umständen auch immer, die Flusskontrolle kehrt zu cinstall zurück. Die durch strace erstellte Diagnosedatei wird nun Untersucht, um fehlende Berechtigungenaufzudecken.
Misslingt ein Dateizugriff auf Grund von fehlenden Zugriffsrechten, ist der Rückgabewert für den Systemaufruf „EACCES“. Daher sucht cinstall die Diagnosedatei nach solchen Einträgen ab. Unter Berücksichtigung der deny Konfiguration fügt es die gefundenen Einträge zur allow Konfiguration hinzu. Dabei unterscheidet es auch, ob ein Eintrag bereits auf der allow Liste vorhanden war oder neu ist. Die Unterscheidung ist wichtig, um die Terminierung der Schleife zu bestimmen. Denn manchmal gibt es Einträge, die trotz gewährten Rechten, immer wieder ein EACCES auslösen. Nur wenn neue Einträge zur allow Konfiguration hinzugefügt wurden erfolgt ein weiterer Aufruf der Schleife.
Ist eine Installation in der virtuellen Umgebung erfolgreich durchgeführt, bricht die Schleife ab. Denn beim erneuter Wiederholung der Schleife, meldet apt-get „paket ist bereits auf dem neuesten Stand“ und terminiert. Dabei entstehen keine neuen EACCES und somit ist die Schleifenbedingung nicht länger erfüllt.
Kann eine Paketinstallation nicht vollständig in der virtuellen Umgebung durchgeführt werden, bricht die Schleife ebenfalls ab. Sollte trotz zusätzlich gewährter Rechte dpkg an derselben Stelle abbrechen, so „steckt die Installation fest“. Es entstehen jedoch keine neuen EACCES und somit terminiert auch in diesem Fall die Schleife.
Mit Beendigung der Schleife, beginnt die letzte Phase.
Anfangs analysiert cinstall die vollzogenen Modifikationen. Sämtliche Änderungen befinden sich unter dem Verzeichnis paket/rw/. Es erstellt eine Liste der Dateien unterhalb dieses Ordners. Dateien die aufs2 zur Anpassung anlegt, untersucht es auf mögliche Löschversuche. Anschließend entfernt es die aufs2 Einträge. Sie haben keine Relevanz bei der Untersuchung von installationsbedingten Daten. Durch report.filter gesteuert, löscht cinstall weitere, unwichtige Einträge aus der Liste. Dazu zählen Paketverwalter Dateien, die bei jeder Installation modifiziertwerden. Sollte die Installation ein Python-Skript ausgeführt haben, entstand eine Vielzahl an *.pyc Dateien. Wegen mangelnder Relevanz filtert es diese ebenfalls.
Die in der Liste verbliebenen Dateieinträge stuft cinstall schließlich ein. Es unterteilt zunächst in die Kategorien „sehr kritisch“, „kritisch“ und „kaum kritisch“. Wir betrachten den Pfad einer Datei zur Einordnung in die Kategorien. Aus der Standard-Tripwire-Konfiguration [Tri10] arbeiteten wir uns eine Bewertungsgrundlage heraus. Daneben unterscheidet cinstall, ob eine Datei neu erstellt oder modifiziert wurde. Dem Benutzer zeigt es auf der Konsole einen Überblick aus dem erzeugten Bericht. Damit endet das Skript. Ein erster Eindruck der Bedrohung ist anhand der Anzahl „sehr kritischer“ Einträge möglich. Folgende Abbildung 4.3 zeigt beispielhaft die Konsolenausgabe bei Installation des Paketes xchat. Anmerkung: die Liste der verwendeten Filter geht über den Bildrand hinaus und wurde aus stilistischen Gründen abgeschnitten.
Abbildung 4.3: Die Ausgabe des Kurzberichtes auf der Konsole, erstellt bei derkontrollierten Software-Installation des Paketes xchat.
Bei Bedarf kann der Benutzer den kompletten Bericht einsehen. Dieser enthält alle relevanten Dateien, die wie ausgeführt eingestuft wurden. Das Wissen um die Auswirkungen einer Software-Installation ist letzten Endes somit gewonnen.