Zusätzliche Sicherheitskonzepte im Linux-Kernel
Sicherheitsanker
von Florian Seitner
Erschienen im Linux-Magazin
2005/03
Projekte wie Pax oder Exec-Shield verankern tief im Kern eines Linux-Systems zusätzliche Sicherheitsmechanismen, die deutlich über die herkömmliche Zugriffskontrolle hinausgehen. Sie vermindern die Gefahr durch Exploits, Race Conditions und Ressourcen-Verschwendung.
Trotz aller Vorsicht beim Programmieren ist auch Linux-Software immer wieder durch Buffer Overflows, Race Conditions und andere Sicherheitslücken bedroht. Sobald ein Fehler bekannt ist, können ihn die Entwickler korrigieren und Anwender können ihre installierte Software aktualisieren. Die große Gefahr sind unbekannte Fehler. Oft gibt es schwarze Schafe, die Sicherheitslücken zwar finden, aber nicht melden, sondern lieber selbst ausnutzen.
Die Gefährdung durch bislang unbekannte Bugs verringern - dieser Aufgabe haben sich mehrere Projekte verschrieben. Die gängigen, im Kernel ansetzenden Schutzmethoden implementieren zusätzliche Access-Control-Funktionen. Beispiele dafür sind LIDS[4], SE Linux[5], GR Security[6] oder RSBAC[7]. Sie begrenzen vor allem die Rechte von Benutzern und Prozessen auf das nötige Minimum, um die Folgen eines erfolgreichen Angriffs zu begrenzen.
Tiefer ansetzende Schutzkonzepte betreffen den Speicher der Prozesse. Zu finden sind diese Mechanismen in bekannten Patches wie Pax[1], Exec-Shield[2] und Openwall[3]. Diese Projekte haben den Exploits den Kampf angesagt. Ihr Ziel: Auch wenn eine Lücke im System steckt, soll kein Angreifer durch sie hindurchschlüpfen und das System knacken. Die Abwehrmaßnahmen dieser Projekte funktionieren zwar ähnlich, sind jedoch teilweise sehr unterschiedlich implementiert. Sie nutzen verschiedene (oft Hardware-spezifische) Merkmale, um zusätzliche und striktere Kontrollen zu ermöglichen.
Ausfuhrverbot
Viele Exploit versuchen eine auf dem Stack liegende Rücksprungadresse zu überschreiben. Nach einem Return-Aufruf soll das attackierte Programm den Code des Angreifers ausführen. Dieser Code liegt ebenfalls auf dem Stack - dort hat ihn der Saboteur per Buffer Overflow eingeschleust[8]. Als Gegenwehr verbieten es einige Patches, Code innerhalb des Stack auszuführen. Konsequent weitergedacht bedeutet dies, einzelne Speicherbereiche explizit als entweder beschreibbar oder ausführbar zu markieren. Dann ist es weder möglich, ausführbaren Code zu verändern noch Code in Datenbereichen auszuführen.
Bit-Schererei
Diese gute Idee ist in der Praxis nicht so leicht umzusetzen. Eines der Probleme ist das Flag »PROT_READ_OR_EXEC« der x86-Hardware-Architektur. Es verwendet für die Einträge in der Page Table leider nur ein gemeinsames Bit, um zu markieren, ob ein Bereich lesbar (»PROT_READ«) oder ausführbar ist (»PROT_EXEC«). Dadurch sind alle Daten in einem lesbaren Bereich automatisch auch ausführbar, das ist aber oft nicht erwünscht. Ein Speicherbereich der beschreibbar ist, muss meist auch lesbar sein, was ihm automatisch das Ausführungsrecht verschafft.
Das unter Linux übliche Binärformat ELF[9] markiert aus Kompatibilitätsgründen den Stack eines Prozesses automatisch als ausführbar, und zwar selbst dann, wenn die Prozessorarchitektur über ein eigenes No-Execute-Bit verfügt. ELF verzichtet immer darauf, zwischen einem lesbaren und einem ausführbaren Stack zu unterscheiden.
Die Sicherheitspatches verwenden je nach Hardware unterschiedliche Ansätze, um die Noexec-Eigenschaft (NX) zu implementieren. Am einfachsten gelingt das, wenn die Hardware-Architektur bereits über passende Paging-Eigenschaften verfügt. Auf vielen Non-x86-Architekturen ist das der Fall. Deren MMU (Memory Management Unit) unterscheidet zwischen nur lesbaren und ausführbaren Speicherbereichen. Die Page Table kennzeichnet dann nicht ausführbare Bereiche mit einem eigenen Bit.
|
Zurzeit sind unter Linux zwei Methoden im Einsatz, um ein dem Prozessor fehlendes No-Execution-Flag zu emulieren: die Pageexec- und die Segmexec-Methode.
Pageexec: Diese Methode nutzt die Aufteilung des TLB (Translation Lookaside Buffer) bei Prozessoren ab der Pentium-Serie (Intel) und dem K5 (AMD). Diese verwalten Code und Daten im TLB nicht mehr gemeinsam, sondern getrennt im Instruction-TLB für Code und im Data-TLB für Daten. Die TLBs wirken als sehr schnelle Caches für die Abbildung von virtuellen auf physikalische Adressen.
Will der Prozessor auf eine virtuelle Speicheradresse zugreifen, sucht er den Eintrag zuerst im TLB. Wird er dort nicht fündig, lädt er die Adresse aus der Page Table und speichert sie im TLB für spätere Zugriffe. Um das Cacheing der Einträge im TLB kümmern sich die x86-Prozessoren normalerweise automatisch. Sie erlauben es aber auch der Software, den kompletten TLB zu leeren oder einzelne Einträge für virtuelle Adressen zu löschen. Dies nutzt die Pageexec-Technik, um Non-Executable-Pages zu implementieren.
Pageexec entfernt Speicherseiten, die nicht ausführbar sein sollen, aus dem TLB oder gewährt den Zugriff nur im Supervisor-Level. Bei jedem TLB-Zugriff, der auf die geschützten Bereiche zielt, generiert der Prozessor einen Page Fault. Der Kernel erhält dann die Kontrolle und darf entscheiden, ob es sich um einen legalen Datenzugriff handelt oder um das verbotene Laden von Instruktionen. Allerdings senken die gezielt verursachten Page Faults die Performance und die Effektivität des TLB.
Segmexec: Die zweite No-Execute-Emulation basiert auf so genannten Segmentation based non-executable pages (Segmexec). Wie in Abbildung 1 zu sehen ist, unterteilt sie den Speicher in unterschiedliche Segmente. Auf x86-Prozessoren läuft Linux im Protected Mode und verwendet Paging. Das Paging übersetzt bei jedem Datenzugriff die aus Segment und Offset bestehende logische Adresse in eine virtuelle (lineare) Adresse. Diese Technik bildet den virtuellen auf den physikalischen Speicher ab.
Im Normalfall umfasst der virtuelle Userspace eines Prozesses 3 GByte Speicher. Segmexec unterteilt diesen Bereich in zwei Hälften. Die erste enthält alle Mappings für Lese- und Schreibzugriffe, die zweite Hälfte ist für ausführbaren Code zuständig. Unterhalb der 1,5-GByte-Grenze liegen also die Daten, darüber der Code. Die ausführbare Hälfte darf auch Mappings auf Daten nutzen, umgekehrt ist das nicht gestattet.
Dank des Tricks mit der Speicherhalbierung sind Code- und Datenbereich unterscheidbar. Das Laden von Instruktionen aus dem ausschließlich für nicht ausführbare Daten bestimmten Bereich führt zu einem Page Fault, der Kernel kann diesen Zugriff somit kontrolliert unterbinden.
Kombination: Da sie architekturspezifische Eigenschaft verwenden, sind beide Ansätze allerdings an die x86-Architektur gebunden. Openwall[3] und andere Projekte implementieren auf eine der beiden Arten einen nicht ausführbaren Stack.
Das Exec-Shield-Patch[2] (und somit Pax[1]) geht noch einen Schritt weiter und wendet das Konzept zusätzlich auf den Heap an. Es schützt damit auch jene Datenbereiche, die ein Prozess mittels »mmap()« in den Speicher abbildet, sowie den Heap-Speicher, den es per »malloc()« anfordert. Pax verwendet sogar - je nach eingesetzter Hardware - Pageexec oder Segmexec und bedient damit beinahe jede Hardware-Architektur.

|
Abbildung 1: Speicherverwaltung ohne und mit Segmexec. Durch die Teilung des virtuellen Speichers in Code- und Datenbereich ist auch auf der x86-Architektur ein NX-Flag möglich.
|
|

|
Abbildung 2: Alle Speichermappings landen hier außerhalb des geschützten Ascii-Armor-Bereichs. Das Exec-Limit liegt sogar bei 0xbfffffff (3 GByte), es umfasst also den gesamten Userspace.
|
Dank Hardware-Unterstützung arbeitet diese Lösung ohne Geschwindigkeitsverlust. Der Kernel muss nur beim Laden des Binary trotz ELF-Format die richtigen Flags setzen. Unter Pax setzt das Tool »chpax« diese Flags im ELF-Header einer Datei. Sie sind Teil des Dateiobjekts und damit unabhängig vom Dateisystem. Sie bleiben auch beim Komprimieren, Kopieren, Verschlüsseln oder Verschieben erhalten.
Auf Architekturen ohne NX-Unterstützung in der Hardware muss der Kernel das fehlende Flag emulieren. Dabei kommen zwei Techniken zum Einsatz, der Kasten "Emulation des NX-Flag" beschreibt beide. Die 64-Bit-Prozessoren von Intel und AMD besitzen ein No-Execution-Flag und auch VIA wird es in kommenden Prozessoren einsetzen. Die Prozessoren von Transmeta können dank des Software-Kerns per Update ein NX-Flag erhalten.
|
Ähnliche Artikel
|
|
Kern-Technik
|
Kernel- und Treiberprogrammierung mit dem Kernel 2.6 -
Folge 28
|
|
Voll im Blick
|
Die Greenbone Vulnerability Assessment und Management Appliance im Test
|
|
Mit Schutzmantel
|
Gekapselt und überschaubar: Minix 3 strebt nach
Sicherheit
|
|
Kampf um die Ressourcen
|
Futexe und andere Formen der Prozesssynchronisation
|
|
Die Flaggschiffe
|
Seltenes Ereignis: RHEL und SLES stehen vor Neuauflagen
|
|
Kern-Technik
|
Kernel- und Treiberprogrammierung mit dem Kernel 2.6 -
|
| Whitepaper |
|
Open Source Datenintegration in der Praxis: Fallstudien und Anwendungsbeispiele
Über die letzten Jahre hinweg haben sich Open Source Lösungen als fester Bestandteil des gesamten Datenintegrationsmarktes etabliert. Viele Unternehmen haben bereits das Open Source Modell für Ihre Datenintegrationsprojekte aufgegriffen. Das vorliegende White Paper illustriert anhand ausgewählter Fallstudien und Anwendungsbeispiele die Implementierung von Open Source Datenintegration in der Praxis und benennt die daraus resultierenden Vorteile.
Download PDF (Registrierung erforderlich)
|
|
The Role of Open Source in Data Integration
Obwohl in den letzten Jahren viele technische Fortschritte erzielt werden konnten, verfügen die meisten Datenintegrationsprozesse nach wie vor nur über eine sehr begrenzte Automatisierung. Das vorliegende White Paper von dem Industry Analyst Mark Madson wird zunächst ein grundlegendes Verständnis von Daten Integration vermitteln, die Vorzüge von Open Source Lösungen für Daten Integration erläutern und Ihnen professionelle Empfehlungen geben, damit Sie Ihre Integrationsjobs noch einfacher und produktiver gestalten können.
Download PDF (Registrierung erforderlich)
|
Dieser Online-Artikel kann Links enthalten, die auf nicht mehr vorhandene Seiten verweisen. Wir ändern solche "broken links"
nur in wenigen Ausnahmefällen. Der Online-Artikel soll möglichst unverändert der gedrucken Fassung entsprechen.
|