Dieser Artikel ist verfübar in: English Castellano Deutsch Francais Nederlands Russian |
von Über den Autor: Christophe Blaess ist ein unabhängiger Raumfahrtingenieur. Er ist ein Linuxfan und arbeitet die meiste Zeit mit diesem System. Er koordiniert die Übersetzung der Man-pages die vom Linux Dokumentationsprojekt veröffentlicht werden. Christophe Grenier ist Student im fünften Semester an der ESIEA, wo er auch als Systemadministrator arbeitet. Er hat eine Leidenschaft für Computersicherheit. Frédéric Raynal benutzt Linux, weil er mit Software, die keine Patente enthält, arbeiten möchte. Er geht gerne ins Kino. Dancer in the Dark ist ein guter Film. Inhalt: |
Zusammenfassung:
Dies ist der erste Artikel in einer Serie von Artikeln über Sicherheitslöcher, die beim Entwickeln von Software entstehen können. Diese Artikel werden zeigen, wie man Sicherheitsprobleme vermeiden kann, indem man seine Programmiergewohnheiten ein wenig ändert.
Im allgemeinen dauert es nicht länger als zwei Wochen, bis wieder ein Sicherheitsloch in einer größeren Anwendung auftaucht. Ein Sicherheitsloch, das es z.B dem auf dem Rechner eingeloggten Benutzern erlaubt, root zu werden. Trotz der hervorragenden Qualität der meisten dieser Applikationen scheint es immer sehr schwierig zu sein, sichere Programme zu schreiben. Ein sicheres Programm gibt einem Benutzer mit bösen oder kriminellen Absichten keine Möglichkeit, sich zu Systemteilen Zugang zu verschaffen, zu denen er keinen Zugang haben soll. Die Verfügbarkeit von Quellcode ist eine gute Sache und wird von vielen Programmierern sehr geschätzt, aber der kleinste Fehler in einem Programm wird damit sichtbar für jedermann. Diese Fehler werden oft zufällig gefunden und Leute, die nach solchen Fehlern suchen, haben nicht immer gute Absichten.
Für einen Systemadministrator besteht die tägliche Arbeit darin, Newsgruppen und Webseiten, auf denen Sicherheitslöcher veröffentlicht werden, zu studieren und für die entsprechenden Pakete einen Update einzuspielen. Der Programmierer kann durch die Studie dieser Informationen viel lernen, speziell wenn er selbst versucht, an seinem Rechner solche Sicherheitslöcher auszuprobieren. Egal wie schnell ein Sicherheitsproblem gefunden wird, ist es immer besser, Sicherheitsprobleme von vornherein zu vermeiden. Wir werden hier einige klassische Fehler besprechen, und zeigen Lösungen für diese Probleme. Wir werden keine Sicherheitsprobleme besprechen, die speziell in Netzwerken auftreten, da diese meist Konfigurationsfehler sind. Systemfehler, die DOS (Denial Of Service) Angriffe zulassen. Diese Probleme betreffen den Systemadministrator oder den Kernelentwickler, aber manchmal auch Applikationsprogrammierer. Speziell dann, wenn diese Programme auf Daten zugreifen, die nicht unbedingt vertrauenswürdig sind. Typische Programme in dieser Klasse sind pine
, acroread
, netscape
, access
,... Einige von diesen Programmen erlaubten es, Informationen auszuspionieren oder direkten Zugriff auf das System zu erhalten. Es ist eine Tatsache, daß sicheres Programmieren einfach jeden betrifft.
Diese Artikelserie zeigt Methoden, die benutzt werden können, um ein Unixsystem zu beschädigen. Wir hätten diese Probleme einfach auflisten können, aber wir bevorzugen offene und klare Erklärungen, damit alle die Mechanismen verstehen. Nach dieser Serie solltest du in der Lage sein, Sicherheitsfehler zu beheben und zu vermeiden. Für jedes Sicherheitsloch werden wir denselben Ansatz wählen. Wir erklären, wie sie funktionieren und dann zeigen wir, wie man sie vermeidet.
Dieser erste Artikel erklärt grundlegende Sicherheitsmechanismen. Wir zeigen, wie man Privilegien durch den Mißbrauch von Set-UID und Set-GID erhalten kann. Als nächstes analysieren wir die bekannte C Funktion system()
und zeigen die Sicherheitslöcher, die es in dieser Funktion gibt.
Wir werden häufig die Problematik anhand kleiner C Programme aufzeigen, aber diese Problematiken lassen sich auf andere Sprachen übertragen: perl, java, shell scripts... Einige Probleme sind spezifisch für eine Sprache, aber das ist nicht immer so, wie wir anhand der Funktion system()
sehen werden.
Auf einem Unixsytem sind die Benutzer nicht alle gleich. Sie haben nicht die gleichen Rechte und das gilt auch für Applikationen. Der Zugriff auf das Dateisystem und die Peripherie einer Maschine unterliegt einer strikten Identitätskontrolle. Einige Benutzer dürfen empfindliche Operationen ausführen, um das System in gutem Zustand zu halten, andere haben diese Rechte nicht. Eine Nummer, die als UID (User Identifier) bezeichnet wird, wird für diese Identitätskontrolle benutzt. Um die Sache einfacher zu machen, gibt es einen Namen, der dieser Nummer entspricht und die Assoziation zwischen Namen und Nummer erfolgt über die Datei /etc/passwd
.
Der Benutzer root, mit der UID 0, kann auf alles im System zugreifen. Er kann nicht nur auf alle Dateien zugreifen, er kann auch die physikalische Konfiguration einer Maschine ändern. Er kann Partitionen mounten, Netzwerk Interfaces aktivieren, IP Adressen ändern oder Systemaufrufe wie mmlock()
benutzen, um auf den physikalischen Speicher zuzugreifen. In zukünftigen Artikeln werden wir die Möglichkeiten studieren, die Posix.1e bietet, um die Privilegien von Programmen, die mit root Rechten laufen, zu limitieren. Für den Augenblick nehmen wir jedoch an, daß der Benutzer root alles kann.
Die Attacken, die wir besprechen, sind interne Attacken. Ein eingeloggter und authentifizierter Benutzer versucht, Privilegien zu erlangen, die er eigentlich nicht hat. Weiterhin gibt es Netzwerkangriffe, externe Angriffe, bei denen Leute versuchen, Verbindungen aufzubauen, die sie eigentlich nicht aufbauen dürfen. Wenn man die Privilegien eines anderen Benutzers erhalten hat, bedeutet das, daß alles unter seinem Namen, seiner UID, gemacht wird und nicht unter der ursprünglichen UID. Natürlich wird ein Angreifer versuchen, die ID von root zu erhalten, aber auch andere Benutzer sind von Interesse, weil man damit auf Informationen zugreifen kann, (news, mail, lp...) und man damit geschützte Daten (Briefe, persönliche Dateien, etc) erhalten kann. Außerdem werden sie benutzt, um illegale Aktivitäten gegenüber anderen zu verstecken.
Um die Privilegien, die für einen anderen Benutzer reserviert sind, zu nutzen, ohne als dieser Benutzer eingeloggt zu sein, muß man zumindest die Möglichkeit haben, mit einer Applikation zu kommunizieren, die unter der UID des Opfers läuft. Wenn eine Applikation --ein Prozeß-- unter Linux läuft, dann hat diese eine klar definierte Identität. Zunächst hat ein Programm ein Attribut namens RUID (Real UID), die der UID (Benutzer Identität) des Benutzers entspricht, der das Programm gestartet hat. Diese Daten werden vom Kernel verwaltet und können sich normalerweise nicht ändern. Es gibt noch ein weiteres Attribut, die EUID (Effective UID). Die EUID wird herangezogen, wenn der Kernel Zugriffsrechte regelt (beim Öffnen von Dateien, Benutzung spezieller Systemaufrufe ...).
Um eine Applikation mit einer Effective UID (bestimmte Privilegien), die anders als die Real UID (Benutzer, der das Programm startete) laufen zu lassen ist, muß ein spezielles Zugriffsrechte-Bit namens Set-UID (wird mit chmod gesetzt) gesetzt sein. Dieses Bit befindet sich in dem Datei Permission Attribut. Es hat den oktalen Wert 4000. Das Set-UID Bit wird als ein s
dargestellt, wenn man sich die Zugriffsrechte mit dem Befehl ls
anzeigen läßt:
Der Befehl ">> ls -l /bin/su -rwsr-xr-x 1 root root 14124 Aug 18 1999 /bin/su >>
find / -type f -perm +4000
" zeigt alle Applikationen im Dateisystem, die das Set-UID Bit gesetzt haben. Wenn der Kernel ein Programm, das dieses Set-UID Bit gesetzt hat, startet, dann benutzt er als EUID die UID des Benutzers, dem die Datei gehört. Die RUID ändert sich nicht und entspricht weiterhin dem Benutzer, der das Programm startete. Der Befehl /bin/su
benutzt z.B diese Eigenschaft. Jeder Benutzer kann den Befehl /bin/su
starten, aber er läuft mit der UID des Eigentümers (root). Es braucht wohl nicht weiter betont zu werden, daß solch ein Programm sorgfältig programmiert werden muß.
Jeder Prozeß hat auch eine effektive Group ID, EGID, und eine real group ID , RGID. Das Set-GID (oktal 2000 ) regelt die Gruppenzugriffsrechte, wenn ein Programm gestartet wird. Eine merkwürdige Kombination entsteht, wenn das Set-GID Bit gesetzt ist, ohne daß die Datei ein execute Bit gesetzt hat. Dies ist eine Konvention, die nichts mit den Privilegien einer Applikation zu tun hat, sondern eine Datei, die mit der Funktion fcntl(fd, F_SETLK, lock)
geblockt werden kann. Normalerweise benutzen Applikationen diese Set-GID bit nicht. Einige Spiele benutzen es z.B um Highscores systemweit zu speichern.
Es gibt verschiedene Typen von Angriffen gegen ein System. Heute werden wir die Mechanismen studieren, mit dem ein Angreifer einen beliebigen Befehl aus einer Applikation heraus starten kann. Dieser Befehl ist normalerweise die Shell, die dann unter der UID der Applikation läuft. Eine zweite Art von Angriff ist ein buffer overflow. Dieser gibt dem Angreifer die Möglichkeit, beliebigen Maschinencode auszuführen. Ein dritter Typ eines Angriffs basiert auf race conditions. Es wird die Zeit genutzt, die zwischen dem Ausführen verschiedener Codestücke vergeht. In dieser Zeit wird irgendein Teil des Systems verändert (normalerweise eine Datei), während die Applikation denkt, es sei gleichgeblieben.
Die zwei ersten Arten von Angriffen versuchen, die Shell mit den Privilegien des Eigentümers eines Programmes auszuführen. Der dritte Type hingegen versucht, Zugriff auf geschützte Systemdateien zu erhalten. Auch der Lesezugriff auf bestimmte Dateien wie z.B /etc/shadow
ist ein Sicherheitsrisiko.
Die Ziele eines Angriffs auf die Systemsicherheit sind meist Programme, die das Set-UID (oder Set-GID) Bit gesetzt haben. Das betrifft auch andere Applikationen, die nicht unter der UID ihrer Benutzer laufen. Die System daemons (Server Prozesse) repräsentieren einen großen Teil dieser Art von Programmen. Ein daemon wird im allgemeinen beim Booten gestartet und läuft im Hintergrund. lpd
, z.B erlaubt es jedem Benutzer Dokumente an den Drucker zu schicken. sendmail
empfängt und verschickt E-Mail, oder apmd
, der das Bios nach dem Status der Batterie befragt (läuft meist auf Laptops). Einige daemons kommunizieren auch mit externen Benutzern über das Netzwerk (Ftp, Http, Telnet... ). Ein Prozeß namens inetd
verwaltet Netzwerkverbindungen.
Zusammenfassend können wir feststellen, daß ein Programm angegriffen werden kann, sobald es mit einem Benutzer ungleich dem Benutzer der es gestartet hat, kommunizieren kann. Wenn es in der Natur des Designs eine Applikation liegt, so etwas zu tun, dann muß man sehr sorgfältig programmieren.
Eine Applikation läuft normalerweise mit einer EUID ungleich der RUID, um dem Benutzer gezielten Zugriff auf Privilegien zu geben, die er normalerweise nicht hat (Dateizugriff, reservierte Systemaufrufe). Im allgemeinen wird das jedoch nur punktuell benötigt, zum Beispiel beim Öffnen einer Datei, ansonsten ist die Applikation in der Lage, mit den Rechten des Benutzers, der sie gestartet hat, auszukommen. Man kann die EUID temporär mit dem Befehl seteuid ändern:
int seteuid (uid_t uid);Eine Applikation kann immer den Wert der EUID so ändern, daß er der RUID entspricht. In diesem Fall wird die alte UID gespeichert in einem Feld namens SUID (Saved UID). Es ist möglich, die SUID zurückzuerhalten und als EUID zu benutzen. Natürlich kann ein Programm mit der EUID Null (root) sowohl die EUID als auch die RUID beliebig ändern (Das Programm
/bin/su
funktioniert so).
Um das Risiko eines Angriffs zu reduzieren wird vorgeschlagen, die EUID zu ändern und die RUID zu benutzen, wenn gerade keine speziellen Privilegien gebraucht werden. Wenn Privilegien gebraucht werden, schreibt man die Saved UID wieder in die EUID. Hier ist ein Beispiel:
uid_t e_uid_initial; uid_t r_uid; int main (int argc, char * argv []) { /* Saves the different UIDs */ e_uid_initial = geteuid (); r_uid = getuid (); /* limits access rights to the ones of the * user launching the program */ seteuid (r_uid); ... privileged_function (); ... } void privileged_function (void) { /* Gets initial privileges back */ seteuid (e_uid_initial); ... /* Portion needing privileges */ ... /* Back to the rights of the runner */ seteuid (r_uid); }
Diese Strategie ist besser als die oft gesehene andersherum arbeitende Strategie, bei der die EUID temporär zur RUID gesetzt wird, bevor man "riskante" Programmstücke ausführt. Diese Reduzierung der Privilegien ist jedoch nutzlos gegen einen Buffer overflow Angriff. Das werden wir im nächsten Artikel sehen. Bei einem Buffer overflow wird beliebiger Code ausgeführt und dieser kann die Anweisungen enthalten, um die EUID zu verändern. Trotzdem hilft dieses nur punktuelle Setzen der Privilegien gegen das beliebige Ausführen einiger Befehle und gegen die meisten Race Conditions gut.
Eine Applikation muß oft einen externen Befehl aufrufen. Ein bekanntes Beispiel ist der Befehl mail
, um ein Mail zu verschicken ( einen Alarm zu melden oder einfach Statistiken zu schicken). Die einfachste Lösung, um das zu machen, ist die Library Funktion system() zu benutzen:
int system (const char * command)
Diese Funktion ist sehr gefährlich: Sie ruft die Shell auf, um einen Befehl, das in der Variable "command" spezifiziert wurde, auszuführen. Das Verhalten der Shell hängt dabei von den Vorlieben des Benutzers ab. Ein typisches Beispiel ist die PATH
Umgebungsvariable. Laß uns annehmen, daß eine Applikation mail
aufruft. Dieses Programm schickt z.B den Quellcode dem Benutzer, der es aufruft:
Nehmen wir weiterhin an, daß das Programm mit Set-UID root arbeitet:/* system1.c */ #include <stdio.h> #include <stdlib.h> int main (void) { if (system ("mail $USER < system1.c") != 0) perror ("system"); return (0); }
Beim Ausführen dieses Programmes wird die Shell (>> cc system1.c -o system1 >> su Password: [root] chown root.root system1 [root] chmod +s system1 [root] exit >> ls -l system1 -rwsrwsr-x 1 root root 11831 Oct 16 17:25 system1 >>
/bin/sh
) mit der Option -c
aufgerufen und übergibt den String der als Befehl ausgeführt werden soll. Die Shell sucht dann die Verzeichnisse aus der Umgebungsvariable PATH
ab, um eine ausführbare Datei names mail
zu finden. Der Benutzer braucht bloß die Variable PATH
zu ändern und der Befehl, den er ausführen möchte in mail
umbenennen und schon kann er irgendetwas ausführen:
Damit wird z.B versucht,>> export PATH=. >> ./system1
mail
im augenblicklichen Verzeichnis zu finden. Jetzt schreiben wir einfach ein kleines Shell Script und nennen es mail. Das Skript wird dann mit der EUID des Dateieigentümers der Applikation ausgeführt. Hier ist ein Skript, das /bin/sh
ausführt. Da stdin umgeleitet ist, müßen wir uns die Eingabe zurück vom Terminal holen. Unser Skript sieht damit so aus:
Hier ist das Ergebnis:#! /bin/sh # "mail" script running a shell # getting its standard input back. /bin/sh < /dev/tty
>> export PATH="." >> ./system1 bash# /usr/bin/whoami root bash#
Der erste Lösungsansatz besteht natürlich darin, immer einen vollen Pfadnamen zu benutzen, z.B /bin/mail
. Damit gibt es ein neues Problem. Die Applikation vertraut darauf, daß mail
an einer bestimmten Stelle im System zu finden ist. Während /bin/mail
im allgemeinen in jedem System zu finden ist, gibt es andere Programme wie z.B GhostScript, die in verschiedenen Distributionen unterschiedlich installiert sind. Desweiteren gibt es noch einen anderen Typ von Angriff bei einigen alten Shells, der auf er Umgebungsvariable IFS
beruht. Die Shell benutzt sie, um die Trennzeichen zwischen Befehl und Argument zu finden. Im allgemeinen sind das Leerzeichen Tab und Return. Wenn der Benutzer /
hinzugügt, dann wird der Befehl "/bin/mail
" als "bin mail
" interpretiert. Eine ausfürbare Datei namens bin
kann jetzt im augenblicklichen Verzeichnis ausgeführt werden, wenn PATH
entsprechend gesetzt ist.
Unter Linux ist die IFS
Umgebungsvariable kein Problem mehr, da die bash sie mit Leerzeichen, Tab und Return beim Start vervollständigt. Das gleiche gilt für pdksh. Dennoch sollte man sich nicht darauf verlassen, denn Applikation werden oft auf andere Systeme portiert und diese Systeme können sich hier anders verhalten.
Einige andere Umgebungvariablen können unerwartete Probleme machen. Das Programm mail
erlaubt es z.B dem Benutze,r ein anderes Programm auszuführen, während er eine Nachricht schreibt. Das geht mit der Escapesequenz "~!
". Schreibt der Benutzer den String "~!command
" am Anfang einer Zeile, dann wir dieser ausgeführt. Das Program /usr/bin/suidperl
zum Schreiben von Set-UID perl Scripten rief /bin/mail
auf, wenn es irgendein Problem hatte, um root eine Nachricht zu schicken. Da suidperl ein Set-UID root Programm ist, wird alles mit root Rechten ausgeführt. In der Nachricht an root steht der Name der fehlerhaften Datei. Jemand kann eine Datei erzeugen mit einem Dateinamen, der carriage return gefolgt von ~!command
enthält. Wenn ein suidperl
Programm über ein Problem stolpert, das mit dieser Datei zusammenhängt, dann wird /bin/mail
aufgerufen und mit der Escapesequenz aus dem Dateinamen gefüttert.
Eigentlich sollte das kein Problem machen, da mail
keine Escapesequenzen akzeptiert, wenn es nicht innerhalb eines Terminalfensters aufgerufen wird. Leider gibt es ein nicht dokumentiertes Feature (vermutlich vom Debuggen übrig geblieben), das es erlaubt, Escapesequenzen zu benutzen, sobald die Umgebungsvariable interactive
gesetzt ist. Das Ergebnis? Ein leicht ausbeutbares Sicherheitsloch innerhalb einer Applikation, die eigentlich die Sicherheit eines Systems verbessern sollte. Der erste Fehler ist ein zwischen zwei Programmen geteilter Fehler. /bin/mail
enthält ein nicht dokumentiertes Feature, das das Ausführen von beliebigem Code erlaubt. Das zweite Problem ist, selbst wenn die Entwickler des /usr/bin/suidperl
dieses Feature nicht kannten, sollten sie nicht einfach alle Umgebungsvariablen übernehmen.
Linux ignoriert normalerwiese die Set-UID und Set-GID bits bei Skripten. Siehe /usr/src/linux/fs/binfmt_script.c
und /usr/src/linux/fs/exec.c
. Einige Tricks erlauben es, diesen Mechanismus zu umgehen. /usr/bin/suidperl
benutzt solche Tricks.
Es ist nicht immer einfach einen Ersatz für die Funktion system()
zu finden. Die erste Variante ist, Systemaufrufe wie execl()
oder execle()
zu benutzen. Das Verhalten ist dann jedoch völlig anders, da das externe Programm nicht mehr als Subroutine (Unterprogramm) aufgerufen wird. Das externe Programm ersetzt den augenblicklichen Prozess. Man muß den Prozess dublizieren und die Kommandozeilenargumente durchsuchen wie in dem folgenden Programm.
wird :if (system ("/bin/lpr -Plisting stats.txt") != 0) { perror ("Printing"); return (-1); }
Offensichtlich viel mehr Code. Unter einigen Umständen wird es sehr komplex. Zum Beispiel, falls man die Standardeingabe (stdin) umleiten möchte. Wie zum Beispiel hier:pid_t pid; int status; if ((pid = fork()) < 0) { perror("fork"); return (-1); } if (pid == 0) { /* child process */ execl ("/bin/lpr", "lpr", "-Plisting", "stats.txt", NULL); perror ("execl"); exit (-1); } /* father process */ waitpid (pid, & status, 0); if ((! WIFEXITED (status)) || (WEXITSTATUS (status) != 0)) { perror ("Printing"); return (-1); }
Die Umleitung (system ("mail root < stat.txt");
<
) wird von der Shell erledigt. Man kann das gleiche durch eine komplexe Verknüpfung von fork()
, open()
, dup2()
, execl()
, etc. erreichen. In diesem Fall ist es eine akzeptable Lösung, die system()
Funktion zu benutzen, aber man muß vorher die gesamte Umgebung konfigurieren.
Umgebungsvariablen werden unter Linux in Form eines Zeigers auf ein Array abgespeichert: char ** environ
. Dieses Array endet mit NULL. Die Strings haben die Form "NAME=value
".
Wir fangen damit an, die gesamte Umgebung zu löschen. Wir benutzen die Gnu Erweiterung clearenv:
oder wir setzen den Pointerint clearenv (void);
einfach zu NULL. Als nächstes werden die Umgebungsvariablen, die wir brauchen, initialisiert:extern char ** environ;
Vor einemint setenv (const char * name, const char * value, int remove) int putenv(const char *string)
system()
aufruf z.B so:
Falls nötig, kann man sich den Inhalt einiger nützlicher Umgebungsvariablen merken, bevor man die gesamte Umgebung löscht. Z.B.clearenv (); setenv ("PATH", "/bin:/usr/bin:/usr/local/bin", 1); setenv ("IFS", " \t\n", 1); system ("mail root < /tmp/msg.txt");
LANG
, TERM
, TZ
, HOME
. Der Inhalt, die Form und die Größe dieser Variablen muß genauestens geprüft werden. Es ist wichtig, daß man die gesamte Umgebung löscht, bevor man einige benötigte Variablen definiert. Das suidperl
Sicherheitsproblem wäre nicht aufgetatucht, wenn die Umgebung korrekt gelöscht worden wäre.
Entsprechend geht man bei einer Netzwerkkonfiguration vor. Zunächst verwährt man jeder Maschiene die Verbindung. Als nächstes werden die benötigten Services aktiviert. Genauso geht man bei der Entwicklung einer Set-UID Applikation vor. Erst die gesamte Umgebung löschen und dann einzlne Umgebungsvariablen setzen.
Das Verifizieren der Parameter wird gemacht, indem man die erwarteten Werte mit den erlaubten Formaten vergleicht. Macht man es anders und überprüft nur auf mögliche Fehler in den Parametern, so könnte es sein, daß man einen Fall vergessen hat.
Was bei system()
gefährlich ist, gilt natürlich auch für verwandte Funktionen wie popen()
, oder Aufrufe wie execlp()
und execvp()
, die die PATH
Variable berücksichtigen.
Um die Ergonomie eines Programmes zu verbessern, ist es eine einfache Möglichkeit, ein Program konfigurierbar zu machen. Z.B. mit Hilfe von Makros. Um Variablen oder generische Muster handzuhaben, gibt es eine Funktion names wordexp()
. Man muß mit ihr sehr vorsichtig sein, da sie einen String wie $(commande)
als externen Befehl ausführt. Es ist genug, den String "$(/bin/sh)
" einzugeben, um eine Set-UID Shell zu erhalten. Um so etwas zu vermeiden, hat wordexp()
ein Attribut namens WRDE_NOCMD
, das die Sequenz $( )
deaktiviert.
Beim Aufruf von externen Kommandos muß man vorsichtig sein, damit man kein Kommando erwischt, das eine Escapesequenz zum Öffnen einer Shell zuläßt. Wie z.B vi :!command
. Es ist schwierig, alle aufzuführen. Einige Applikationen sind offensichtlich (Texteditoren, Dateimanger...) andere sind schwieriger zu entdecken, wie wir es bei /bin/mail
gesehen haben.
Dieser Artikel hat folgende Aspekte erläutert :
Im nächsten Artikel werden wir über Speicher sprechen. Wie er organisiert ist, Funktionsaufrufe .... und dann werden wir zu buffer overflows kommen und zeigen, wie man dieses Sicherheitsloch mit shellcode ausnutzen kann.
|
Dem LinuxFocus-Team schreiben © Frédéric Raynal, Christophe Blaess, Christophe Grenier, FDL LinuxFocus.org Click here to report a fault or send a comment to Linuxfocus |
Autoren und Übersetzer:
|
2001-01-10, generated by lfparser version 2.7