Fachinterview Safety&Security

Verlässlichkeit auf Systemdesign-Basis

28. Juni 2019, 10:37 Uhr | Dr. Constantin Tomaras
Diesen Artikel anhören

Fortsetzung des Artikels von Teil 2

Angriffskategorien

D&E: Gemessen an den Einträgen in Exploit-Datenbanken sind Security-Angriffe enorm vielfältig. Sind sie dennoch kategorisierbar?

DZ: Eine ad-hoc Kategorisierung bieten bereits die Security-Attribute (Verfügbarkeit, Integrität und Vertraulichkeit). Eine zusätzliche Metrik stellen dann die Angriffsmethoden, die jeweils in invasiv und nicht-invasiv, sowie logisch und physikalisch aufspalten (Bild 2).

Eine breite Klasse von Angriffen stellen Code-Injection-Angriffe dar, deren Ziel ganz unterschiedlich ausfallen kann: die Beeinträchtigung von Codeintegrität oder Daten, eine wesentliche Verlangsamung des Systems oder Zugang zu sensiblen Daten. Hier muss der Schadcode ins System gebracht und der Kontrollfluss derart verändert werden, dass er auch ausgeführt wird. Eine gängige Methode überschreibt unter Kenntnis der Speicherarchitektur mit einem Pufferüberlauf die Return-Adresse oder Frame-Pointer-Adresse auf den Stack. Dann führt der Weg aus einer Subroutine nicht mehr zurück in die aufgerufene Funktion sondern in das Schadprogramm. Analog können die Header-Informationen bei dynamischem Speicher mit einem Pufferüberlauf verändert werden.

Bild 2: Kategorisierung von Angriffen nach Zielen oder Mitteln.
Bild 2: Kategorisierung von Angriffen nach Zielen oder Mitteln.
© Daniel Ziener

Bei hinreichender Kenntnis des Speicherlayouts von Systembibliotheken, können auch diese zum Angriff verwendet werden, indem Abzweige in den Kontrollfluss eingebracht werden (»return-into-libc«-Angriffe). Es gibt sogar die Möglichkeit aus den Bausteinen einer im Speicher vorhandenen Bibliothek schadhaften Code zusammen zu bauen.

Nach Shacham kann dieses Verfahren für einen Angriff verwendet werden, ohne das Schadsoftware ins System gebracht werden muss. Hierbei muss ein entsprechender Stack präpariert werden, bei dem jedes Segment auf ein Codesnippet (meist nur 2-3 Instruktionen) in dem Bibliothekscode zeigt. Durch einen Speicherüberlauf lässt sich, z.B. durch Überschreiben des Stackzeigers, dieser präparierte Stack aktivieren.

Invasive Angriffe verwenden Spezialequipment: dabei werden kritische Daten, Chiplayouts oder komplette Implementierungen ausgeforscht. Dies kann nur mit teuren Geräten unter Laborbedingungen geschehen.

Nicht-invasive logische Angriffe versuchen kritische Informationen durch Täuschung der Personen oder Maschinen zu erlangen oder Schwachstellen in kryptographische Methoden oder den Protokollen auszunutzen. Des Weiteren zählt auch das Kopieren sensibler Daten oder Copyright-Verletzungen zu den nicht-invasiven logischen Angriffen.

Zu den nicht-invasiven physikalischen Attacken zählen Lauschangriffe und Seitenkanalangriffe. Dabei werden sensible Daten in der Kommunikation ausgehorcht. Bei einen Seitenkanalangriff werden physikalische Parameter des Chips gemessen und sensitive Daten durch Korrelation extrahiert.

Beispiele sind Zeit- und Leistungsumsatz-Analyse, elektromagnetische Feldanalyse, Fehler- und Glitch-Analyse. Die Zeitanalyse misst Variationen in der Ausführungszeit bei kryptographischen Verfahren. Die Leistungsumsatz-Analyse betrachtet Variationen im Leistungsumsatz, ebenso können elektromagnetische Feldemissionen geprüft werden. In der Fehleranalyse wird das System rauen Umgebungsbedingungen ausgesetzt, die Fehler bewirken. Anhand der berechneten fehlerhaften Ergebnisse kann durch diese Analyse auf die Kryptographie und den Schlüssel geschlossen werden. Die Glitch-Attacken gehören streng genommen auch zur Fehleranalyse: hier werden zusätzliche Glitches in das Clock-Signal eingebracht, um die korrekte Datenverarbeitung auf dem kritischen Pfad zu stören.

D&E: Welche Gegenmaßnahmen können Embedded-Entwickler im Bereich der Schadcode-Injektion ergreifen?

DZ: Da nahezu alle diese Angriffe dem Stack im Speicher gelten, kann ein zusätzlicher hardware-basierter Stack Abhilfe schaffen. Diese Stacks werden üblicherweise zur Überprüfung von Rücksprungadressen eingesetzt. Wenn die Speicher-Adressen von denen im Hardware-Stack abweichen, wird ein Ausnahme ausgelöst. Das Betriebssystem entscheidet dann ob Schadcode vorliegt bzw. wie darauf reagiert wird.

Weiterhin könnte der Stack in Control- und Daten-Stack getrennt werden. Das geht die Ursache »Manipulation durch Pufferüberlauf« direkt an, zieht aber eine Modifikation des Übersetzers, oder der Hardware des Prozessors nach sich.

Die Methode von Bhatkar und Xu setzt an der Speicherarchitektur an: um Pufferüberläufe instrumentalisieren zu können, muss ein Angreifer das Speicherlayout verstehen. Das wird erschwert, in dem der Code mit jeder Ausführung die virtuellen Adressen nach einem Zufallsschema neu vergibt. Dies betrifft sowohl die Basisadressen des statischen und dynamischen Speichers, die Stack-Adressen dynamisch verknüpfter Bibliotheken und den Ort von statischen Daten.

Sind Objekte nicht umsortierbar, so werden zufällige Lücken eingefügt. Wenn der Code verschlüsselt im Speicher hinterlegt wird, ist das Einspielen von Schadsoftware praktisch unmöglich, da der Angreifer seine Malware dann ebenfalls verschlüsselt einführen muss. Wird unverschlüsselter Code injiziert, so bewirkt das einen Prozessabsturz.

Angriffe welche die Schwachstellen der C/C++-Sprache ausnutzen, können mit alternativen Sprachen vermindert werden. Beispielsweise analysiert der Cyclone C-Dialekt ein Programm statisch zur Übersetzung und setzt dynamische Bereichsüberprüfungen an sämtlichen Stellen ein, die durch einen Angriff ausgenutzt werden könnten. Damit können Pufferüberläufe, Format-String-Attacken und Speichermanagement-Fehler vermindert werden.

Statische oder dynamische Codeanalysatoren können Metriken für die Sicherheit angeben. Oft fußt diese Metrik aber auf heuristischen Erkennungsraten. Die statische Analyse ist nicht geeignet um Pufferüberläufe zu erkennen.

Es gibt auch lexikalische Tools, die den Code mit unsicherem Code aus einer Bibliothek abgleichen.

Weitere Methoden gleichen das Anwendungsverhalten mit einem vorgegebenen Profil ab. Das kann vom Nutzer gesetzt werden oder sogar maschinelles Lernen einbeziehen. Der Nachteil ist die hohe Rate an Falschmeldungen. Auf Hofmeyer und Forrest geht eine Methode zurück, welche die Systemaufrufe bei UNIX-Prozessen betrachtet. Wenn das Aufrufmuster wesentlich von den vorherigen abweicht, können beispielsweise Prozessabbrüche eingeleitet werden.

Verbesserung der Informationssicherheit können auch Erweiterungen von Compilern, Bibliotheken oder Betriebssysteme schaffen. Im Compiler ist das natürlich bequem, da die Programmiersprache nicht verändert wird. Hier werden vor allem Methoden vorgeschlagen welche die Return-Adresse oder Stack-Zeiger schützen. Hierbei können sogenannte Canary-Wörter vor der Return-Adresse eingefügt werden. Das ist eine Variable mit zufälligem  Wert. Wird durch einen Pufferüberlauf versucht die Return-Adresse zu überschreiben, wird zuerst das Canary-Wort überschrieben. Damit kann vor der Ausführung des Rücksprungs überprüft werden, ob dieses noch intakt ist. Diese Erweiterung hat es mittlerweile auch in den GCC-Compiler geschafft. Des Weiteren können Zeiger vor allem durch Verschlüsselung geschützt werden.

Eine weitere Methode von Jones und Kelly identifiziert unzulässige Zeiger, die auf nicht initialisierten Speicher zeigen. Das kann zur Laufzeit mit zusätzlichen Befehlen erfolgen. Auf Bibliothekenebene können zusätzlich kritische Funktionen durch sichere Implementierungen ausgetauscht werden.


  1. Verlässlichkeit auf Systemdesign-Basis
  2. Anforderung an alle Systemebenen
  3. Angriffskategorien
  4. Kontrollflussmethoden
  5. IP-Schutz

Lesen Sie mehr zum Thema


Das könnte Sie auch interessieren

Jetzt kostenfreie Newsletter bestellen!

Weitere Artikel zu RWTH Aachen International Academy

Weitere Artikel zu Funktionale Sicherheit/Safety

Weitere Artikel zu Cyber-Security