Back to the author's homepage

Das Linux Intrusion Detection System (LIDS)

Root guckt in die Röhre

David Spreen

Wenn ein Angreifer unter Linux Root-Rechte erlangt, ist er mit Bordmittelnnicht mehr aufzuhalten. LIDS bietet Methoden, die dem Eindringling den Blick und den Zugriff auf wichtige Teile des Systems verwehren.

Auf Linux-Systemen sind für viele Aktionen Root-Rechte nötig. Leider gibt es für Root keine weiteren Einschränkungen, er darf einfach alles lesen, alles schreiben, alles löschen. Wenn statt des Systemadministrators ein Eindringling Root-Rechte erlangt, kann er ebenfalls alles: private E-Mails lesen, Programme austauschen, Hintertüren installieren, seine Spuren verwischen und beliebige Informationen aus dem System schaffen.

Mit LIDS lassen sich Dateien und Verzeichnisse auch vor Root schützen, seine Allmacht wird also aufgehoben. Sie können die Zugriffsrechte auf Dateien genauer festlegen (ACLs, Access Control Lists). Zusätzlich können Sie über Capabilities einzelnen Programmen Dinge erlauben, die eigentlich Root-Rechte benötigen. Beispielsweise benötigt ein Prozess für das Öffnen eines Ports unterhalb 1024 eigentlich Root-Rechte. Mit der passenden Capability geht's auch ohne Root.

Zugriffsrechte mit ACLs vergeben

Dateien vor Root schützen zu können ist sicherlich eine nützliche Sache. Damit Ihr Linux aber trotzdem noch so funktioniert wie es sein soll, können Sie einzelnen Programmen wieder Schreib- und Leserechte geben. LIDS versteckt beispielsweise die Datei /etc/shadow vor allen Benutzern, erlaubt es aber /bin/login explizit, diese Datei zu lesen.

Der erste Schritt ist sinnvoll, da mit Hilfe der Shadowdatei Passwörter gecrackt werden könnten. Ohne jeglichen Zugriff auf diese Datei kann sich aber auch kein Benutzer mehr einloggen, da /bin/login das eingegebene Passwort nicht überprüfen kann.

Eigentlich müssten Sie noch eine Ausnahme machen: Ohne Schreibzugriff auf /etc/shadow kann kein Benutzer sein Passwort ändern.

Auf den ersten Blick sieht das ganz einfach aus, Sie könnten ja dem Programm /usr/bin/passwd Schreibzugriff auf die Shadowdatei geben. In diesem Fall könnte allerdings Root wieder alle Passwörter ändern. Da wir bei LIDS aber von einem Angreifer ausgehen, sollten wir diese Möglichkeit ausschließen.

LIDS heißt nur so

Vielleicht fragen Sie sich, warum das Ganze Intrusion Detection heißt. Es hat ja auch über diesen Namen lange Diskussionen gegeben, schließlich ist es nicht das primäre Ziel von LIDS, Einbrüche zu bemerken, sondern nach einem Einbruch das System zu schützen. Immerhin gibt es aber einige Mechanismen, die auf Erkennung ausgerichtet sind. Wenn eine LIDS-Regel verletzt wird, schließt LIDS nicht nur die Shell, von der aus die Regel verletzt wurde. LIDS kann auch den Administrator benachrichtigen, etwa per E-Mail. Außerdem bietet LIDS einen Portscan Detector im Kernel, der allerdings bei weitem nicht so ausgereift ist wie Port Sentry [4].

LIDS hat auch dafür eine Lösung, die LIDS free Session (LFS). Eine LFS gilt für das aktuelle Terminal und alle aus ihm gestarteten Programme. In einer LFS gelten die LIDS-Einschränkungen nicht. Da LFS nur nach Eingabe des lidsadm-Passworts startet, könnte nur der Sysadmin Passwörter ändern. Wenn es außer dem Admin keine User auf dem System gibt, ist das ein gangbarer Weg.

Wenn jedoch mehrere Personen Zugriff haben, müssen Sie sich zwischen dem Komfort für die User und verstärkter Sicherheit entscheiden.

Auf welchen Systemen macht LIDS überhaupt Sinn?

LIDS ist dafür ausgelegt, das Überschreiben von wichtigen Systemteilen zu verhindern. Es macht daher wenig Sinn, LIDS auf einem System zu benutzen, das täglich verändert wird. Anders bei Produktionssystemen mit einzelnen Services, die einmal eingerichtet werden um dann stabil zu laufen. Ab und zu mal ein Bugfix oder ein Update einspielen ist kein Problem, aber automatische Upgrades wie das Apt-get von Debian lassen sich mit LIDS kaum vereinbaren.

Zu empfehlen ist ein Linux mit einem 2.2.x-Kernel. Es gibt LIDS zwar auch für den Linux-Kernel 2.4, man kann aber in der Regel vom Einsatz eines Kernels unter x.x.10 nur abraten. Außerdem ist LIDS noch in der Entwicklung, Sie sollten also regelmäßig nach Updates Ausschau halten.

Installation von LIDS

Ein Kernel-Patch und die Administrationsprogramme sind als .tar.gz-Archive auf http://www.lids.org erhältlich. Nachdem das Paket für die entsprechende Kernel-Version heruntergeladen und entpackt ist, wechseln Sie in das Verzeichnis /usr/src/linux. Von hier aus wird das Patch mit

patch -p1 < .../lids-version.patch

angewendet, anschließend der Kernel konfiguriert. Näheres dazu erfahren Sie in der deutschen Kernel-HOWTO [1] des Dlhp.

Um die LIDS-Optionen überhaupt als Auswahl zu erhalten, müssen folgende Punkte ausgewählt sein:

[*] Prompt for development and/or
   incomplete code/drivers
[*] Sysctl Support

Nun können Sie Ihren LIDS-Kernel konfigurieren und kompilieren.

Als Nächstes sollte das lidsadm-Tool übersetzt werden. Sie finden das Unterverzeichnis lidsadm-version im LIDS-Paket. Bevor Sie dort make tippen, ist jedoch in der Version 0.9.12 eine kleine Änderung am Makefile vorzunehmen: Ergänzen Sie die Zeile CFLAGS=... noch um den Eintrag -DLIDS_CONFIG. Nun rufen Sie make && make install auf, um das Programm zu übersetzen und zu installieren.

Vor dem ersten Booten mit dem neuen Kernel müssen Sie unbedingt noch ein LIDS-Passwort setzen und die Konfiguration auf Ihren Computer abstimmen. Das LIDS-Passwort wird mit lidsadm -P gesetzt. Es wird später zum Deaktivieren von LIDS oder zum Wechseln in eine LFS benötigt. Sollten Sie mit dem LIDS-Kernel starten, ohne vorher ein Passwort gesetzt zu haben, endet der Versuch mit einer Kernel Panic.

Neue LIDS-Versionen

Während der Arbeit an diesem Artikel sind neuere Versionen von LIDS entstanden. Deren Syntax ist allerdings inkompatibel zu den alten und auch noch nicht hinlänglich dokumentiert, dafür aber in sich konsistenter.

Der Artikel befasst sich vor allem mit den alten Versionen: 0.9.13 für Kernel 2.2.18 und 1.0.5 für Kernel 2.4.1. Doch konnte ich durch Lesen des Quellcodes und mit Hilfe der LIDS-Mailingliste noch rechtzeitig Anpassungen im Text vornehmen.

Wir hatten schon die ACLs angesprochen. Diese werden in der Datei /etc/ lids/lids.conf gespeichert; zusätzlich zu den Datei- und Verzeichnisnamen sind dort aber auch Inode-Nummern eingetragen. Die Inode-Nummern sind neben den Dateinamen mit einer Adresse der Dateien vergleichbar.

Da Dateisystemzugriffe nicht nur über die Dateinamen, sondern auch über Inode-Nummer erfolgen können, muss LIDS diese Nummern der zu schützenden Dateien natürlich kennen. Damit die ACLs, die mit dem LIDS-Paket vorinstalliert wurden, auch zu Ihrem System passen, aktualisieren Sie die Inode-Nummern mit lidsadm -U.

Die ACLs, die sich auf Dateien und Verzeichnisse beziehen, sind aktiv, sobald der Kernel das LIDS-System lädt. Dagegen werden die ACLs, die Capabilities behandeln, erst aktiv, wenn das erste Mal lidsadm -I ausgeführt wird. Sie müssen also noch dafür sorgen, dass dies bereits beim Booten geschieht.

LIDS und VFS

LIDS setzt an der VFS-Schicht an. Linux ist dafür ausgelegt, mit vielen unterschiedlichen Dateisystemen arbeiten zu können. Die VFS-Schicht ist ein allgemeines Interface für alle im Kernel unterstützten Dateisysteme. Wenn nun ein Zugriff auf das Dateisystem erfolgt, greift das System-Call-Interface nicht direkt auf das einzelne Filesystem zu, sondern richtet diese Anfrage - vereinfacht gesagt - an das VFS. In der Realität spielt dabei auch noch das Device-Driver-Subsystem eine Rolle. Abbildung 1 zeigt das Prinzip; Details hierzu finden Sie in [2].

Abb.1
Abbildung 1: Das System-Call-Interface (die Dateisystem-Schnittstelle, die Userprozessen zur Verfügung steht) greift nicht auf das einzelne Dateisystem zu, sondern auf ihr gemeinsames Interface, das VFS.

Überlegen Sie sich genau, wann Sie die Capability-Regeln aktiv werden lassen wollen: Es macht zum Beispiel Sinn, diese erst nach dem Aktivieren der Firewall greifen zu lassen, wenn die Firewall Capabilities benutzt, die Sie sperren möchten.

Stellen Sie unbedingt die Konfiguration erst fertig, bevor Sie das System mit dem neuen Kernel booten, damit die Maschine beim nächsten Start auch wirklich noch benutzbar ist. Sollte Ihr Computer durch LIDS-Regeln einmal unbenutzbar werden, übergeben Sie Lilo beim Booten den Parameter security=0.

Konfiguration

Neue Regeln werden mit lidsadm hinzugefügt. Für eine Dateiregel sieht der lidsadm-Befehl folgendermaßen aus:

lidsadm -A -s /pfad/programm -o /pfad/Datei,Verzeichnis -j REGEL 

Die Syntax erinnert ein wenig an Ipchains. Die Option -s übergibt das Regelsubjekt, die Option -o das Objekt. Wenn das Subjekt (hier ein Programm) auf das Objekt (Datei, Verzeichnis oder Capability) zugreifen möchte, wird durch die ACL (genauer: durch die Regel, die mit -j übergeben wird) geregelt, ob und wie das Subjekt zugreifen darf.

Folgender Aufruf erlaubt /bin/login den Lesezugriff auf /etc/shadow:

/sbin/lidsadm -A -s /bin/login -o /etc/shadow -j READ 

Um /etc/shadow für alle unlesbar zu machen, wäre der folgende Aufruf nötig:

/sbin/lidsadm -A -o /etc/shadow -j DENY 

Weitere Regeln kann man der Lidsadm-Manpage entnehmen. Warum LIDS für beliebige Dateisysteme funktioniert, nicht nur für Ext2, ist im Kasten "LIDS und VFS" erklärt.

Capabilities

Seit Kernel 2.2.x hat der Linux-Kernel eine Art eigener Zugriffskontrolle - die Capabilities. Für bestimmte Aktionen benötigen Prozesse mehr Privilegien, als ein normaler Benutzer hat. An die Stelle der Alles-oder-nichts-Aufteilung zwischen Root und normalem User treten feiner unterteilte Berechtigungen. Beispielsweise setzt das Laden und Entfernen von Modulen die Capability CAP_SYS_ MODULES voraus, insmod benötigt also genau diese Capability (siehe Abbildung 2).

Im Linux-Standardkernel kann man einer Programmdatei keine Capabilities zuweisen, es fehlt der Support im Dateisystem. Erst einem laufenden Prozess lassen sich Capabilities geben oder nehmen. Der Kernel überprüft aber die Capabilities; dies wird gelöst, indem Root-Prozesse automatisch alle Capabilities erhalten. Um einem Root-Programm eine Capability zu nehmen, muss man sie global aus dem System entfernen.

Abb.2
Abbildung 2: In Schritt 1 will Insmod auf den Module_loader zugreifen. Zunächst überprüft der Kernel in Schritt 2, ob Insmod die Capability CAP_SYS_MODULES hat, und erlaubt erst dann in Schritt 3 das Laden des sb-Moduls.

LIDS dagegen bietet die Möglichkeit, jedem Programm individuell Capabilities zu geben und zu nehmen, egal ob es Root-Rechte hat oder nicht. In /etc/lids/lids.cap wird festgelegt, welche Capabilities per Default verfügbar sind und welche nur durch Sonderregelungen in den ACLs vergeben werden. So kann man beispielsweise dem Apache-Webserver die Capability CAP_NET_BIND_ SERVICE zuteilen, damit er einen Port kleiner 1024 belegen darf, obwohl diese Capability global deaktiviert war. Dieses Beispiel erfordert folgendes Kommando:

/sbin/lidsadm -A -s /usr/sbin/httpd -t -o CAP_NET_BIND_SERVICE -j INHERIT 

Die Option -t besagt, dass das Objekt dieser Regel eine Capability ist. Die Regel INHERIT bestimmt, dass die Capability auch an Kindprozesse von /usr/sbin/httpd vererbt wird. Das Gegenteil wäre NO_INHERIT. Eine Übersicht über die für LIDS relevanten Capabilities finden Sie in der Lidsadm-Manpage.

Ab Version 0.9.14-2.2.18 beziehungsweise 1.0.6-2.4.2 hat sich die Syntax von lidsadm etwas verändert. Hier sähe der Aufruf so aus:

/sbin/lidsadm -A -s /usr/sbin/httpd -i -1 -o CAP_NET_BIND_SERVICE -j GRANT  

Die Optionen -s und -o übergeben weiterhin Subjekt und Objekt der ACL. Die Option -t entfällt und die Regeln INHERIT und NO_INHERIT gibt es ebenfalls nicht mehr. Stattdessen übergibt man bei Capabilities die Regel GRANT, um sie dem Subjekt zuzuordnen. Die Option -i -1 bedeutet, dass die Kindprozesse des Httpd die Capability ebenfalls erhalten.

Neu ist die Möglichkeit, die Tiefe der Vererbung zu bestimmen. Während -i -1 unendlich tiefe Vererbung bedeutet, würde bei -i 1 die Capability zwar an die Kindprozesse des Httpd vererbt werden, aber nicht mehr an deren Kinder (also die Enkel). Um die Vererbung ganz zu verhindern, geben Sie -i 0 an oder lassen die Option -i komplett aus.

Versteckte Prozesse

Mit den bisher vorgestellten Mitteln können Sie einem Eindringling das Leben zwar ganz schön schwer machen. In der realen Welt würde man ihn aber so weit wie möglich im Dunkeln tappen lassen. Eine Firewall kann das sehr gut nach außen bewerkstelligen, sie verbirgt beispielsweise die innere Netzstruktur.

Innerhalb eines Computers erreicht LIDS ähnliche Wirkungen: Prozesse werden versteckt, wenn man dem Programm die Capability CAP_HIDDEN gibt:

/sbin/lidsadm -A -s /usr/sbin/popper -t -o CAP_HIDDEN -j INHERIT 

Das Beispiel bewirkt, wie Sie sicherlich schon entdeckt haben, dass /usr /sbin/popper in Prozesslisten wie ps und top nicht mehr zu sehen ist.

Auch hier sieht der Aufruf in den neueren Versionen von lidsadm etwas anders aus:

/sbin/lidsadm -A -s /usr/sbin/popper -i -1 -o CAP_HIDDEN -j GRANT 

Switching LIDS

Prozesse verstecken, Capabilities vergeben oder verweigern, Dateizugriffe auch für Root einschränken - alles mit dem Ziel, einem Eindringling seine Arbeit zu erschweren. Leider erschwert man sich damit aber auch selbst die Arbeit: Manchmal muss man selbst als legitimer Admin einfach und schnell etwas ändern, eine Route oder ein Gateway, oder es sind Änderungen an der Firewall vorzunehmen. Für diese Fälle gibt es die LFS (LIDS Free Session), in der Sie wieder wie gewohnt arbeiten können. Mit Hilfe des LIDS-Passworts kann ein Terminal von der LIDS-Kontrolle befreit werden. Das Kommando dafür lautet:

/sbin/lidsadm -S -- -LIDS

Wenn aber ein Service neu gestartet werden soll oder sogar ein Neustart ansteht, dann reicht auch die LFS nicht mehr aus. Hier stehen die Aktionen nicht mehr unter dem Einfluss der einen freigegebenen Shell, also müssen wir LIDS erst komplett deaktivieren. Das folgende Kommando sorgt dafür:

/sbin/lidsadm -S -- -LIDS_GLOBAL

Um eine veränderte LIDS-Konfiguration neu zu laden während LIDS aktiv ist, rufen Sie Folgendes auf:

/sbin/lidsadm -S -- -RELOAD_CONF

Den größten Teil seiner Dienstzeit sollte LIDS aber ohne viel Umschalten absolvieren.

Dieser Artikel hat Ihnen hoffentlich einen grundlegenden Einblick in die Funktionsweise und die Bedienung von LIDS gegeben. Trotzdem sollten Sie es nicht versäumen, neben der Lidsadm-Manpage auch die LIDS-FAQ [3] bei der Konfiguration zu Rate zu ziehen, nicht dass Ihr Linux Sie plötzlich als Feind sieht und den Zutritt verweigert. (fjl)

Infos

[1] Brian Ward & Peter Sütterlin: Deutsches Linux Kernel HOWTO: http://www.tu-harburg.de/dlhp/HOWTO/DE-Kernel-HOWTO.html

[2] Ivan Bowman, Saheem Siddiqi & Meyer C. Tanuan: Concrete Architecture of the Linux Kernel: http://plg.uwaterloo.ca/~itbowman/CS746G/a2

[3] Steve Bremer: LIDS FAQ: http://www.clublinux.org/lids/

[4] Port Sentry: http://www.psionic.com/abacus/portsentry/

Der Autor

David Spreen ist der Debian-Maintainer der LIDS-Pakete. Neben der Schule arbeitet er für die NetUSE AG, einen ISP in Kiel. Auch den Rest seiner Zeit verbringt er häufig mit seiner Linuxbox oder mit dem Programmieren. Er dankt unter anderem Benjamin Traube (nerror) und Eugene A. Brin (blackbro).

Copyright © 2001 Linux New Media AG


Back to the author's homepage