8.1.4. Viren, Würmer und andere Sabotage-Software

Bisher standen hauptsächlich diejenigen Gefahren im Mittelpunkt der Betrachtung, die einem System von außen, d.h. speziell vom Netz her drohen (Manipulation der übertragenen Informationen, Einbrüche, ...). Im letzten Teil des Abschnitts 8.1. wollen wir uns überblicksartig damit auseinandersetzen, welchen Bedrohungen die Systeme von innen, also durch die auf ihnen ablaufenden Programme ausgesetzt sind.

Dieser Bereich der Computer-Sicherheit betrifft im wesentlichen alle Rechner, allerdings kommen in der Regel durch die Vernetzung einige neue Aspekte hinzu. So stehen z.B. mit E-Mail, News, FTP und WWW viele neue Kanäle zur Verteilung von Software zur Verfügung, weshalb Programme wesentlicher leichter und schneller auf neue Maschinen gelangen können. Außerdem gestattet das Netz prinzipiell eine unmittelbare Beeinflussung fremder Systeme. Bei isoliert betriebenen Computern ist das nicht der Fall.

Grundsätzlich stellen alle auf einem Computer ausgeführten Programme eine potentielle Gefahrenquelle dar, da sie absichtlich oder unabsichtlich illegale Effekte bzw. Schäden hervorrufen können. Beispiele dafür sind das fehlerhafte Verändern des Inhalts einer Datei, das Löschen von Files ohne Einverständnis des Eigentümers oder die Erlangung illegitimer Privilegien und damit des Zugriffs auf Ressourcen, zu deren Nutzung man nicht autorisiert ist.

Oft resultieren unzulässige Wirkungen aus Fehlern (Bugs) in der Software, d.h., sie waren vom Programmierer so nicht beabsichtigt. Es gibt aber auch eine Menge von Applikationen, die speziell mit dem Ziel entwickelt wurden, unterschiedlichste Schäden anzurichten. Derartige Programme bezeichnet man als Sabotage-Software bzw. im Englischen als malicious software, wobei deren konkrete Ausprägung jeweils sehr verschieden sein kann.

In der Literatur werden die betreffenden Programme meist danach klassifiziert, welchen Schaden sie anrichten, unter welchen Bedingungen sie dies tun und auf welchem Wege sie sich verbreiten. Die verwendete Terminologie ist allerdings nicht immer ganz einheitlich. Man sollte die Unterteilung auch nicht zu ernst nehmen, da es Erscheinungen geben kann, die sich nicht genau einer Gruppe zuordnen lassen.

Die folgende Liste enthält häufig anzutreffende Begriffe und erläutert kurz deren Bedeutung:

Auf Grund der z.T. übertriebenen Ängste vor Viren und ähnlichen Gebilden sei an dieser Stelle noch einmal ganz deutlich darauf hingewiesen, daß Programme generell nur während ihrer Ausführung die ihnen evtl. innewohnenden schädlichen Potenzen entfalten können. Solange also die schädlichen Code-Teile nicht als Anweisungen interpretiert, sondern nur als normale Daten behandelt werden, stellen sie in der Regel eine völlig harmlose Bytefolge dar. Es ist dann z.B. absolut ungefährlich, sie auf einen anderen Datenträger zu kopieren, per E-Mail zu verschicken oder mit einem Editor zu betrachten, der in der Lage ist, mit beliebigen Binärdateien sicher umzugehen.

Natürlich kann E-Mail auch gefährlich sein, nämlich dann, wenn der Mail-Agent die Abarbeitung von schädlichem Code veranlaßt, der als Bestandteil der Mail mitgesendet wurde. Ein Beispiel dafür wäre das Starten eines als MIME-Attachment angehängten Sabotage-Programms. Das reine Abspeichern des Mail-Inhalts in eine Datei bzw. einen Folder ist dagegen normalerweise völlig unbedenklich.

In einigen Fällen besteht auch die Möglichkeit, daß scheinbar normaler Text (beispielsweise der Inhalt einer harmlos wirkenden E-Mail) ein Problem darstellt, weil er spezielle Byte-Sequenzen enthält, die von einigen Terminals bzw. Terminal-Emulatoren als Steuerzeichen betrachtet werden und unterschiedliche schädliche Wirkungen haben können (u.a. das Schreiben in Dateien oder das Ausführen beliebigen Codes). Die Steuerzeichen werden allerdings nur dann wirksam, wenn sie das zum Betrachten oder Editieren des Textes verwendete Werkzeug unverändert an das Terminal weiterreicht, was in der Regel allerdings nicht geschehen sollte.

Derartige Attacken, bei denen der Angreifer durch speziell konstruierte Daten möglicherweise gefährliche Fehlfunktionen in einem an sich harmlosen und normal funktionierenden Programm hervorruft, werden als data-driven attacks bezeichnet. Mitunter wird dieses Prinzip auch genutzt, um ein Fehlverhalten des Nutzers oder der Hardware herbeizuführen. So könnte man z.B. versuchen, das Paßwort eines Anwenders in Erfahrung zu bringen, indem man ihn durch einen geeigneten Dialog bzw. eine Aufforderung per Mail dazu verleitet, sein Paßwort in ein von einem Angreifer bereitgestelltes WWW-Formular einzutragen oder per Mail an einen vermeintlichen Administrator zu schicken, bei dem es sich allerdings in Wirklichkeit um den Angreifer handelt.

Als Beispiel für eine gegen die Hardware gerichtete Attacke sei die Ausnutzung des im November 1997 offengelegten F00F-Bugs (s. http://support.intel.com/support/processors/pentium/ppiie/index.htm) im Pentium-Prozessor genannt. Dieser Bug führt ohne spezielle Gegenmaßnahmen (workarounds) des Betriebssystems dazu, daß der Prozessor durch normale Nutzer-Applikationen vollständig blockiert werden kann (so daß ein Reset nötig ist), wenn diese den gezielt konstruierten, aus den vier Hexadezimal-Bytes F0 0F C7 C8 bestehenden ungültigen Maschinenbefehl zur Ausführung bringen. Es ist davon auszugehen, daß neuere Betriebssystem-Versionen die negative Wirkung dieses Befehls zuverlässig verhindern.

Man sollte grundsätzlich sehr genau darauf achten, ob durch eine bestimmte Aktion evtl. unbekannte und möglicherweise gefährliche Programme gestartet werden. Nicht immer ist das sofort klar. Hier einige typische Beispiele:

Gefahren drohen allerdings nicht nur von mit schlechten Absichten geschriebenen Programmen. Nicht selten nutzen Angreifer gewisse Schwachstellen bzw. Fehler im Betriebssystem oder in mit hohen Privilegien ablaufenden Programmen aus. Mitunter verkehrt sich hierbei die Wirkung mancher der für Administratoren entwickelten Sicherheits-Werkzeuge, die die Systeme nach verschiedensten Lücken absuchen, ins Gegenteil, indem sie dem potentiellen Eindringling wertvolle Informationen für sein illegales Vorhaben liefern können.

Das folgende Beispiel diskutiert einen für viele C-Programme typischen klassischen Bug, der auf unterschiedlichen UNIX-Systemen sehr oft ausgenutzt wurde, um widerrechtlich die Privilegien des Superusers (meist Nutzer root) zu erlangen. Selbst in modernen Systemen werden in gewissen Abständen immer wieder derartige Fehler entdeckt und in CERT Advisories oder sonstigen Security Alerts beschrieben.

Die Angriffe richten sich überwiegend gegen die mit Root-Rechten laufenden Netzwerk-Server oder die dem Superuser gehörenden sog. SUID-Applikationen. SUID steht für set UID und bedeutet, daß das Programm bei der Ausführung über die Rechte seines Eigentümers verfügt, in unserem Falle also die Rechte von root. Im Gegensatz dazu läuft eine "normale" Applikation mit den Rechten desjenigen Nutzers, der sie startet.

Die Attacken machen sich den Fakt zunutze, daß es bei der Programmiersprache C, in der die allermeisten UNIX-Programme implementiert wurden, ohne weiteres möglich ist, die Grenzen von Feldern zu überschreiten, ohne daß dies durch das Laufzeitsystem bemerkt oder gar unterbunden würde. Da C für die Systemprogrammierung entworfen wurde und sich daher durch eine besondere Maschinennähe auszeichnet (ich bezeichne C deshalb manchmal etwas scherzhaft als portable Assemblersprache), ist dies als gewolltes Feature und nicht als Bug zu betrachten.

Daraus ergibt sich die Konsequenz, daß allein der Programmierer dafür verantwortlich ist, ein ungewolltes Überschreiben von nicht mehr zum Feld gehörenden Teilen des Speichers zu verhindern. Wird dies nicht oder nicht in ausreichendem Maße getan, besteht unter Umständen die Möglichkeit, im Rahmen einer data-driven attack durch speziell aufgebaute, sehr lange Daten, die z.B. bei SUID-Programmen als Kommandozeilenargumente oder bei Netzwerk-Servern über TCP-Verbindungen übergeben werden, Teile des Laufzeitstacks gezielt zu überschreiben und so unterschiedlichste Effekte zu erzielen, u.a. die Ausführung beliebiger Programme.

Diese Möglichkeit wurde auch durch den bereits erwähnten Internet-Worm von 1988 ausgenutzt. Eine seiner drei Methoden, in eine fremde Maschine einzudringen, bestand darin, dem Finger-Dämon (fingerd) der entfernten Maschine eine speziell konstruierte, 536 Byte lange Zeichenkette zu senden, die dessen 512 Byte großen Eingabe-Puffer zum Überlaufen brachte. Auf diese Weise konnte der Wurm auf dem Laufzeitstack von VAX-Computern eine spezielle Folge von Maschinenbefehlen hinterlegen, die nach Beendigung der Funktion main (und damit des gesamten C-Programms) für den Start einer Shell sorgte. Durch entsprechende Anpassungen der gesendeten Zeichenkette wäre diese Technik auch auf andere Prozessor-Architekturen und Betriebssysteme übertragbar.

Der illegal gestartete Kommando-Interpreter hatte Root-Rechte, da der Finger-Dämon wie so oft mit den Rechten des Superusers lief, was der Voreinstellung entsprach, aber für die Funktionsweise keineswegs erforderlich war. Deshalb startet man fingerd heute (wenn überhaupt) mit den Rechten eines normalen, mit wenigen Privilegien ausgestatteten Nutzers (z.B. nobody). In diesem Zusammenhang sei nochmals an die allgemeine Forderung erinnert, Servern nur genau die Privilegien einzuräumen, die sie für ihren Dienst wirklich benötigen.

Da es keine Methode gibt, die mit absoluter Sicherheit feststellt, welche Seiteneffekte und Gefahren von einem bestimmten Programm ausgehen, verbleibt immer ein gewisses Risiko. Viele Probleme betreffen vor allem diejenigen Systeme, die wie z.B. MSDOS, Windows 3.x und Windows 95 keine Unterscheidung verschiedener Identitäten vornehmen, so daß jedes Programm de facto vollen Zugriff auf alle Ressourcen des Systems (Speicher, Dateisystem, Netzwerk-Interfaces, ...) hat.

Dennoch kann man sich durch die Beachtung einiger Verhaltensregeln in der Praxis recht gut vor Schäden schützen:

Abschließend noch einige Bemerkungen zur Zuverlässigkeit bzw. Sicherheit von UNIX-Werkzeugen und -Diensten. Das Paper ftp://ftp.cert.dfn.de/pub/docs/misc/fuzz-revisited-A4.ps.gz beschreibt die Ergebnisse eines praktischen Tests verschiedener UNIX-Systeme mittels eines Programms namens Fuzz. Hier einige interessante Aussagen:

Es sei noch erwähnt, daß GNU mit Sicherheit zu einem nicht geringen Anteil von den strengen Kodierungsvorschriften der Free Software Foundation (FSF) profitiert, die z.B. die Verwendung von Puffern fester Länge verbieten. Der Abschnitt Writing Robust Programs beginnt so:
Avoid arbitrary limits on the length or number of any data structure, including file names, lines, files, and symbols, by allocating all data structures dynamically. In most Unix utilities, "long lines are silently truncated". This is not acceptable in a GNU utility.
Die gesamten GNU Coding Standards finden Sie unter http://www.fsf.org/prep/standards_toc.html.


© Holger Trapp, 28.10.1998