Login
Newsletter
Werbung

Mo, 28. Mai 2007, 00:00

Systeme mit Systrace härten

Systrace ermöglicht die Überwachung und Steuerung von Systemaufrufen. Dazu benutzt es Richtlinien, die für jedes verwendete Programm definiert werden. Anhand dieser Richtlinie werden Systemaufrufe erlaubt oder verboten. Ebenso kann man einzelne Systemaufrufe unter anderen Benutzerrechten ausführen. Somit ist es möglich, SETUID-Programme als unprivilegierter Benutzer auszuführen und nur bestimmte Systemaufrufe mit Root-Rechten auszuführen. Systrace erlaubt daher die Implementierung einer feingranulierten Sicherheitsrichtlinie, die sogar Argumente von Systemaufrufen überprüfen kann. Dieser Artikel beschreibt die Funktionsweise von Systrace, Aufbau und Erzeugung einer Richtlinie sowie den praktischen Einsatz anhand von zwei Beispielen auf NetBSD.

Systemaufrufe mit Systrace steuern

Wie inzwischen allgemein anerkannt ist, setzt eine erfolgreiche Verteidigung eines Rechner-Systems mehrere Verteidigungslinien voraus. Diese Linien müssen sich überlappen, ohne jedoch voneinander abzuhängen. Dies können beispielsweise Paketfilter, Application-Level-Gateways oder biometrische Zugangskontrollen sein. Allerdings bietet jede Verteidigungslinie wiederum neue Angriffspunkte, so könnte beispielsweise ein Einbruchserkennungssystem mittels Speicherüberlauf übernommen und mit Root-Rechten missbraucht werden. Daher ist es notwendig, die Schadmöglichkeiten von Programmen einzugrenzen.

Nahezu jedes heute eingesetzte Programm ist zu komplex und umfangreich, um sorgfältig auf Fehlerquellen und Sicherheitslücken überprüft zu werden. Selbst wenn es als quelloffenes Programm vorliegt, überprüft in der Regel niemand den Quellcode auf absichtliche oder fahrlässige Sicherheitsprobleme. Quelloffenheit ist zwar ein sehr gutes Kriterium für sicherheitsrelevante Programme, schützt aber definitiv nicht vor Lücken oder Hintertüren, wie [Thompson 1984] beweist. Teilweise ist man aber auch auf den Einsatz geschlossener Software angewiesen und hat dann keinerlei Möglichkeit mehr, diese zu prüfen, und muss ihr zwangsläufig trauen.

Angriffe gegen Systeme konzentrieren sich in der Regel auf Systemaufrufe (auch System Calls oder Syscalls genannt), die unter anderem auch dazu verwendet werden können, um im Kernel privilegierte Operationen durchzuführen. Um derartigen Vorgehensweisen zu begegnen, wird die Angriffsfläche reduziert. Dazu wird ein Programm eingeführt, das die Ausführung von Systemaufrufen begrenzt und die Zugriffsrechte darauf feiner als bisher granuliert. Hierzu benötigt man eine Richtlinie, die die Zugriffe reglementiert. Die Richtlinie muss alle möglichen Fälle abdecken und auch Kenntnisse von allen möglicherweise auftretenden Pfaden haben, was dank symbolischer Links nicht besonders einfach ist. Die Richtlinie beschreibt das Normalverhalten eines Prozesses und dient so als Vergleich zum laufenden System. Weicht ein Prozess von der beschriebenen Richtlinie ab, wird dies als Einbruchsversuch erkannt und verhindert. Außerdem soll das überwachende Programm auch Überwachungsprotokolle der überwachten Programme erzeugen, um so Anomalien erkennen und analysieren zu können.

Ein derartiges System lässt sich auf verschiedene Arten implementieren. Einerseits kann es komplett im Kernel arbeiten, andererseits auch komplett im User-Space. Im Kernel ist die Ausführung recht schnell, aber das System selbst ist äußerst komplex und nur sehr schwer auf andere Betriebssysteme zu portieren. Im User-Space hingegen ist das Programm portabel, aber sehr langsam und unsicher, da es zu Race-Conditions zwischen dem Zeitpunkt der Analyse und der Ausführung eines Systemaufrufs kommen kann.

Systrace, von seinem Entwickler Niels Provos in [Provos 2006] und [Eriksen und Provos 2003] beschrieben, verwendet einen hybriden Ansatz. Es wird ein kleiner Teil im Kernel implementiert und der größte Teil im User-Space. Der Kernel-Teil ermöglicht die sehr schnelle Behandlung von kontextinsensitiven Systemaufrufen, die bspw. stets abgelehnt oder erlaubt werden. Weiterhin ermöglicht dies, auszuführende Programme in einem Sandkasten zu kapseln und geforkte Prozesse mit der vererbten Richtlinie weiter zu kontrollieren. Der Teil im User-Space überwacht die Systemaufrufe auf kontextsensitive Entscheidungen und trifft sie anhand der definierten Richtlinie. Während der Entscheidungsfindung blockiert der Kernel den fraglichen Prozess. Weiterhin kann der User-Space-Daemon über eine Schnittstelle Informationen wie Zustandsübergänge, PID-Änderungen oder Forks vom Kernel-Teil anfordern.

Um Funktionen des Kernels zu nutzen, können Anwenderprogramme Systemaufrufe verwenden. Mit diesen kann sich ein Programm bspw. an einen Port binden oder eine Logdatei öffnen, da solche Operationen System-Rechte erfordern. Damit ein Programm auf derartige Systemaufrufe zugreifen darf, muss es mit Root-Rechten gestartet werden - und eröffnet damit eine riesige Sicherheitslücke. Systrace von Niels Provos umgeht dieses Problem, indem die Rechtezuteilung nicht mehr auf Programmebene vorgenommen wird, sondern auf Ebene der Systemaufrufe heruntergebrochen wird. Ein Programm kann also von einem normalen Benutzer gestartet werden und bekommt gemäß einer vorher erstellten Richtlinie von Systrace entsprechende Zugriffsrechte auf Systemaufrufe zugeteilt.

Die Grammatik der Richtlinie

Die Richtlinie für ein zu überwachendes Programm wird in einer recht einfachen Grammatik definiert, in der Ausdrücke aneinandergereiht werden. Ein Ausdruck besteht dabei aus einem booleschen Ausdruck und der auszuführenden Aktion. Die Aktion kann aus folgenden Aktionen bestehen: ask (frage), deny (verbiete) oder permit (erlaube) in Verbindung mit optionalen Argumenten. Ergibt der boolesche Ausdruck wahr, wird die definierte Aktion ausgeführt. Ist als Aktion ask definiert, wird der Benutzer befragt, um die Aktion zu erlauben oder zu verbieten.

Der boolesche Ausdruck setzt sich aus verschiedenen Variablen und den Logik-Operatoren and (logisches Und), or (logisches Oder) und not (logisches Nicht) zusammen. Die Variablen bestehen aus den normalisierten Systemaufruf-Namen, den dem Systemaufruf übergebenen Argumenten und einem Logik-Operator, der beide Argumenteverknüpft.

Die Filterausdrücke auf Argumente verwenden verschiedene Operatoren:

  • match Wahr, wenn der Dateiname gemäß den Regeln in fnmatch(3) getroffen wird.
  • eq Wahr, wenn das Argument des Systemaufrufs genau der Vorgabe entspricht.
  • neq Die logische Negation des eq-Operators.
  • sub Wahr, wenn die angegebene Teilzeichenkette im Argument des Systemaufrufs vorkommt.
  • nsub Die logische Negation des sub-Operators.
  • inpath Wahr, wenn das Argument des Systemaufrufs im Pfad der Vorgabe vorkommt.
  • re Wahr, wenn das Argument des Systemaufrufs dem angegebenen Regulären Ausdruck entspricht.

Ein paar Ausdrücke zur Veranschaulichung der Möglichkeiten:

Kommentare (Insgesamt: 0 )
Pro-Linux
Pro-Linux @Facebook
Neue Nachrichten
Werbung