Nur weil sich ein Programm besonders paranoid verhält, ist es noch lange nicht sicher: Das recht bekannte Perl-Programm Ridentd verschleiert zwar aufwändig die Identität eines Users, leidet aber an Sicherheitslücken. Welche das sind und was Programmierer dagegen unternehmen, zeigt dieser Artikel.
Sichere Programme entwickeln ist eine viel zu selten ausgeübte Kunst. Selbst wer sich Mühe gibt, greift häufig daneben: Wie leicht das passiert, belegen die “InSecurity News” in jedem Linux-Magazin und Sicherheits-Webseiten wie der Security Tracker. Auch Ridentd [1] hat dort seine Spuren hinterlassen [3] – ein Anlass, das Programm genauer zu analysieren. Dabei treten einige verbreitete Fehler zutage. Die im Folgenden erarbeiteten Korrekturen funktionieren ähnlich auch bei anderer Software.
Wie im Namen anklingt, geben der klassische Ident-Daemon »identd« und seine zahlreichen Ableger an Port 113 den Namen des Benutzers heraus, dem eine Netzwerkverbindung gehört [2]. Typischerweise fragt ein Server den Ident-Daemon des Clients nach dem Besitzer einer Verbindung, über die der Server eine Anfrage empfangen hat (Abbildung 1).

Abbildung 1: Annika startet über eine Applikation auf Tomate eine Anfrage an den Applikationsserver (1). Dieser fragt den Ident-Daemon von Tomate, wem die Verbindung mit dem lokalen Port 789 und dem entfernten Port 456 gehört (2). Normalerweise antwortet Identd wahrheitsgemäß mit »annika« (3).
Diese Maßnahme scheint auf den ersten Blick die Authentizität des Benutzers sicherzustellen. In der Praxis klappt das nicht: Ein Angreifer lässt seinen eigenen Ident-Daemon mit beliebigem Quatsch antworten. Ehrliche Anwender gefährdet der Dienst sogar, weil er ohne Not lokale Benutzernamen preisgibt. Sinnvoll ist das bestenfalls bei gut administrierten Mehrbenutzermaschinen, von denen aus ein User fremde Rechner angreift. Das Opfer erfährt vom Ident-Daemon den Account der Quellmaschine und informiert dessen Admin.
Trotz aller Bedenken erlaubt es manche Software, dass sich Benutzer einzig über das Ident-Protokoll ausweisen. Zum Beispiel PostgreSQL bei entsprechender Konfiguration. Auf die Frage nach den Gründen für eine solche Konfiguration erhielt der Autor erschreckende Antworten wie: Das ist ja nur intern, wir haben eine Firewall.
Gesunde Paranoia
Der Random Ident Daemon (Ridentd) tritt mit dem Anspruch an, keinerlei Informationen über das System herauszugeben. Statt mit einem Benutzernamen antwortet er mit einem zufälligen Eintrag aus einem Ispell-Wörterbuch. Die Informationen über die abgefragte Verbindung liest er aus dem Proc-Dateisystem und ordnet ihr für ihre gesamte Lebensdauer ein gleich bleibendes Wort zu. Dabei setzt Ridentd eine Standardinstallation von Ispell mit den Daten in »/usr/lib/ispell« voraus.
Bisher behandelte die Reihe “Sicheres Programmieren” ([4] bis [8]) die Sprachen C, C++ und Shellskripte. Mit anderen Programmiersprachen sind Entwickler offensichtlich auch nicht besser bedient: Der Ridentd-Autor hatte sich für Perl entschieden. Im Folgenden arbeitet dieser Artikel Schwächen der Versionen 0.9.1b und 0.9.2b heraus. In Kooperation mit dem Ridentd-Autor Rob Meijer entstand im Januar 2006 die Version 0.9.3b, die einige kritische Probleme beseitigt.
Im Fokus
Anfang 2004 berichtete ein Benutzer auf der Sicherheitsseite Security Tracker von einer Symlink-Schwäche mit der temporären Datei »/tmp/rident.pid« in der Ridentd-Version 0.9.1b [3]. Das Listing 1 zeigt die interessantesten Ausschnitte aus dem Perl-Skript.
|
Listing 1: Ridentd |
|---|
001 #!/usr/bin/perl
[...]
136 if (open(PID,"/tmp/rident.pid"))
137 {
[...]
139 $opid=<PID>;
140 chomp($opid);
141 close(PID);
142 unless ($opid =~ /^d+$/)
143 {
[...]
145 exit;
146 }
[...]
148 open(PS,"/bin/ps -p $opid|");
149 $killit=0;
150 while (<PS>)
151 {
152 if (/ridentd.pl/)
153 {
154 $killit=1;
155 }
156 }
157 if ($killit)
158 {
[...]
160 kill(9,$opid);
161 sleep(1);
162 }
[...]
167 }
[...]
176 $pid=fork();
[...]
181 if ($pid)
182 {
183 open(PID,">/tmp/rident.pid");
184 print PID "$pidn";
[...]
187 }
|
Der Block von Zeile 136 bis 167 öffnet, sofern vorhanden, die PID-Datei (Zeile 136), liest daraus die Prozess-ID eines noch laufenden oder abgestürzten Ridentd (139 bis 141) und stellt sicher, dass er eine Zahl gelesen hat (regulärer Ausdruck »^d+ in Zeile 142). Anschließend sucht Ridentd in der Ausgabe von »/bin/ps -p nach der Zeichenkette »ridentd.pl« (148 bis 156). Falls ein gleichnamiger Prozess mit der gegebenen PID existiert, killt ihn das Skript per Signal 9 (SIGKILL, 157 bis 162).
Dieser kurze Auszug hat bereits mindestens drei unangenehme Macken – dazu später mehr. Nachdem der Ridentd einen zweiten Prozess abgespaltet hat (Zeile 176), erzeugt oder überschreibt der Mutterprozess die Datei »/tmp/rident.pid«, indem er vor den Dateinamen das Zeichen »>« hängt. Damit gibt es wenigstens drei Erfolg versprechende Angriffspfade auf das System:
- Der Angreifer erzeugt einen Symlink auf eine Datei, deren erste
Zeile lediglich aus einer ganzen Zahl besteht. - Er legt einen Symlink an, der auf keine bestehende Datei zeigt,
beispielsweise »/etc/rc2.d/S55foobar«. - Er versucht einen Symlink auf eine beliebige Datei zu
erstellen, nachdem das Skript Zeile 136 passiert hat (Abbildung
2).

Abbildung 2: Der Angreifer startet ein Shellskript, das abwechselnd den Symlink »/tmp/ridentd.pid« erzeugt und löscht. Mit etwas Glück existiert der Link nicht, wenn Ridentd 0.9.1b die Datei in Zeile 136 öffnen will, zeigt aber auf »/etc/passwd«, wenn das Skript in Zeile 183 vorbeikommt.
Im Erfolgsfall mäht das »open()«-Kommando in Zeile 183 mit der anschließenden Schreiboperation eine bestehende Datei nieder (dritter Punkt) oder erzeugt sie neu (Variante zwei). Methode drei ist am schwierigsten auszuführen, erlaubt es dem Angreifer aber, beliebige Dateien zu zerstören. Das schafft ein kleines Shellskript mit guter Erfolgschance: Es legt pausenlos den Symlink an und löscht ihn sofort wieder (Abbildung 2, rechts oben). Mehr zu Symlink-Attacken steht in Folge 2 dieser Serie [5].
Bald nach der Sicherheitsmeldung hat Rob Meijer die Version 0.9.2b veröffentlicht, um die Symlink-Schwäche zu beseitigen. Hinzugekommen sind zwei Sicherheitsabfragen (Listing 2). Zeile 136 prüft per »(-l “/tmp/rident.pid”)« vor dem Öffnen der Datei, ob »/tmp/ridentd.pid« ein symbolischer Link ist. Das deutet auf einen Angriff hin und das Skript beendet sich mit einer Fehlermeldung. Weiter unten löscht eine neuer Codeblock (Zeilen 187 bis 192) eine noch bestehende PID-Datei. Die Bedingung »(-e “/tmp/rident.pid”)« testet, ob die Datei existiert.
|
Listing 2: Ridentd |
|---|
[...]
136 if (-l "/tmp/rident.pid") {
137 print "PANIC: It apears someone has tempored with the pid file /tmp/rident.pidn";
138 exit;
139 }
140 if (open(PID,"/tmp/rident.pid"))
141 {
[...]
146 unless ($opid =~ /^d+$/)
147 {
[...]
149 exit;
150 }
[...]
185 if ($pid)
186 {
187 if (-e "/tmp/rident.pid") {
188 unlink("/tmp/rident.pid");
[...]
192 }
193 open(PID,">/tmp/rident.pid");
194 print PID "$pidn";
[...]
197 }
|
Untauglicher Fix
Auf den ersten und zweiten Blick eine sichere und saubere Lösung. Folglich findet sich in zahlreichen Projekten ähnlicher Code. Das Konzept ist immer gleich: Der Entwickler prüft – wenn überhaupt -, ob eine Datei eine gewünschte Eigenschaft besitzt, und öffnet sie anschließend. Die einschlägigen Tests in Perl, Shell, C oder C++ drängen ihm dieses Vorgehen geradezu auf.
Betriebssysteme wie Unix, die mehrere Prozesse parallel konkurrierend ausführen, garantieren aber nicht, dass das Dateisystem zwischen der Abfrage und dem nächsten Kommando gleich bleibt. Konkret heißt das, auch wenn kein Symlink existierte, als Ridentd in Zeile 136 arbeitete, hat irgendjemand ihn vielleicht noch vor dem »open()« in Zeile 140 angelegt. Dasselbe gilt in den Zeilen 187 und 188. Selbst nach dem Löschen kann es dem Angreifer gelingen, vor Zeile 193 einen Symlink anzulegen.
Je näher Test und »open()« liegen, desto schwieriger wird es für den Angreifer. Ganz unterbinden lässt sich die Lücke so aber nicht. Weil sich Angreifer und Opfer dabei ein Wettrennen liefern, heißt dieser Fehlertypus auch Race Condition.
Fehlerfrei
Wie der Programmierer solche Schwächen beim Öffnen von Dateien vermeidet, hat Folge 5 [8] für C-Programme erläutert. Genau wie die C-Funktion »fopen()« ist die Perl-Funktion »open()« nicht ausreichend ausdrucksstark, um Symlink-Angriffe zu verhindern. Stattdessen kommt »sysopen()« zum Einsatz, das genau wie »open()« in C funktioniert. Der Auszug aus Ridentd 0.9.3b zeigt, wie es richtig geht (Listing 3), und behebt gleich noch einige weitere Schwachpunkte.
|
Listing 3: Ridentd |
|---|
001 #!/usr/bin/perl
002 #It's already too late to do that check here, but at least try to print a
003 #warning
004 if ($> != $<)
005 {
006 print "Must not run with Set-UID bit setn";
007 exit;
008 }
[...]
033 #We need to be root at startup so we can bind to the ident port.
034 if ($< != 0)
035 {
036 print "Need to be root to bind to the ident portn";
037 exit;
038 }
039 chdir("/") or die "Can not change working directory";
[...]
057 if ($file =~ /^[^-'][^']*.hash$/)
058 {
059 $usefile=$file;
060 }
[...]
066 open(STR1,"/usr/bin/strings /usr/lib/ispell/'$usefile'|")||die "Can't start strings";
[...]
152 ($pnam,$dummy,$myuid,$mygid)=getpwnam("nobody");
[...]
158 #Just in case O_NOFOLLOW is not supported we double check.
159 if (-l "/tmp/rident.pid") {
[...]
161 exit;
162 } elsif (sysopen(PID,"/tmp/rident.pid",O_RDONLY | O_NOFOLLOW)) {
163 $oldpid = 0;
164 ($pfuid,$pfgid) = (stat(PID))[4,5] or die "PANIC: Can not stat open pidfile";
165 unless ($pfuid == $myuid || $pfgid == $mygid)
166 {
[...]
168 exit;
169 } else {
170 #See if the file was already written.
171 seek(PID,0,SEEK_END);
172 $size=tell(PID);
173 seek(PID,0,SEEK_SET);
[...]
175 if ($size > 0 && $size < 100) {
[...]
177 sysread(PID,$oldpid,$size,0);
178 chomp $oldpid;
179 unless ($oldpid =~ /^d+$/)
180 {
[...]
182 exit;
183 }
184 $oldpid +=0;
185 } else {
186 &dprint("* PID file is corruptn");
187 exit;
188 }
189 }
190 close(PID);
191 #Now let's test if the found pid is really our old instance.
192 $killit=0;
193 if ($oldpid)
194 {
[...]
196 open(PS,"/bin/ps -p '$oldpid'|");
197 $killit=0;
198 while (<PS>)
199 {
200 if (/bridentd.plb/)
201 {
202 $killit=$oldpid;
203 }
204 }
205 unless ($killit)
206 {
207 &dprint("* pid file apears to be oldn");
208 } else {
209 #We need to kill the old process, but we are root and thus to powerfull.
210 $tpid=fork();
211 unless (defined($tpid)) {
212 print "ERR: Forking errorn";
213 exit;
214 }
215 if ($tpid) {
216 #The parent remains root and must wait for the child process.
217 &dprint("* Started background process to kill old instance safelyn");
218 waitpid($tpid,0);
219 &dprint("* Background process finished.n");
220 sleep(1);
221 } else {
222 unless ($)=$mygid) {print "Cleanup Unable to set group ID to $mygidn";exit;}
223 unless ($>=$myuid) {print "Cleanup Unable to set user ID to $myuidn";exit;}
224 kill(9,$killit);
225 exit;
226 }
227 }
228 }
229 }
[...]
237 unlink("/tmp/rident.pid");
[...]
241 unless (sysopen(PID,"/tmp/rident.pid",O_RDWR | O_CREAT | O_EXCL, 0600)) {
242 print "PANIC: Could not create the pid file /tmp/rident.pid $! $?n";
243 exit;
244 }
[...]
246 $pid=fork();
[...]
252 if ($pid)
253 {
254 # parent
255 unless (syswrite(PID,"$pidn",length("$pidn"))) {
[...]
257 close(PID);
258 kill(9,$pid);
259 }
260 exit;
261 }
|
Keine Symlinks verfolgen
In Zeile 162 öffnet das Skript mit Sysopen die PID-Datei zum Lesen und setzt dazu die »O_NOFOLLOW«-Option. Sie verhindert, dass Sysopen einem Symlink folgt. Damit ist klar, dass die PID-Datei tatsächlich unter »/tmp« liegt. Mit Hilfe von »stat()«, angewendet auf das offene Datei-Handle, stellt das Skript anschließend sicher, dass die Datei auch dem richtigen Benutzer und seiner Gruppe gehört. Ridentd verwendet zu diesem Zweck den Benutzer »nobody«. Wichtig ist die Reihenfolge: Erst die Datei öffnen und danach erst ihre Eigenschaften am Datei-Handle prüfen.
Weil es »O_NOFOLLOW« leider nicht in jedem Unix gibt, blieb der alte Test aus 0.9.2b in Zeile 159 erhalten. Auch ohne den perfekten Schutz ist das immer noch besser als nichts. Der vollständige Code in Version 0.9.3b enthält noch weitere Tests, die herausfinden, ob »O_NOFOLLOW« auf der Zielplattform existiert.
Erst löschen, dann schreiben
Der zweite Open-Aufruf ist noch leichter repariert (Zeile 241). Erst löscht das Skript die alte PID-Datei mit »unlink()« (Zeile 237), dann öffnet Sysopen die Datei zum Schreiben. Die Optionen sorgen dafür, dass Ridentd eine neue Datei erzeugt »O_CREAT«, aber keine bestehende überschreibt »O_EXCL«. In diesem Sinne existiert ein Symlink immer, »O_NOFOLLOW« wird überflüssig. Selbst wenn es einem Angreifer gelingt, zwischen Unlink und Sysopen eine Datei oder einen Symlink einzuschieben, verweigert Sysopen den Dienst.
Weitere offene Wunden
Im Skript stehen weitere Open-Aufrufe, die bisher nicht zur Sprache kamen. Der Block von Zeile 23 bis 35 in den Versionen 0.9.1b und 0.9.2b sucht im Verzeichnis »/usr/lib/ispell« nach einem passenden Wörterbuch, dessen Name mit ».hash« endet. Zeile 39 reicht den Namen an die Perl-Funktion Open weiter:
open(STR1,"/usr/bin/strings /usr/lib/ispell/$usefile|")
Das Zeichen »|« hinter dem Dateinamen weist Perl dazu an, eine Shell zu starten, die folgenden Befehl bearbeitet:
/usr/bin/strings /usr/lib/ispell/Dateiname
Lautet der Dateiname »;rm -rf *;.hash«, löscht die Shell in einem Aufwasch gleich noch das aktuelle Verzeichnis mit. Metazeichen-Probleme, bei denen nachgeschaltete Programme spezielle Zeichensequenzen auf unerwartete Weise interpretieren, waren Thema in den Folgen 3 und 4 der Reihe ([6], [7]).
Strenge Namen
Version 0.9.3b löst das Problem: Der reguläre Ausdruck »/^[^-\’][^\’]*.hash$/« in Zeile 57 (Listing 3) ignoriert Hashdateien, deren Namen einfache Anführungszeichen enthalten oder mit einem Minuszeichen beginnen. Letzteres interpretieren die meisten Befehle als Option. Der Open-Aufruf ändert sich kaum, nur die Variable » steht nun in einfachen Anführungszeichen. Die Shell entfernt diese Zeichen wieder, bevor sie die Option an »strings« übergibt.
Zugegeben ein Angreifer mit Schreibrechten in »/usr/lib/ispell« ist wahrscheinlich sowieso schon Root. Trotzdem zahlt sich Sorgfalt aus, denn allzu oft dienen Skripte als Vorlage für andere. Dass der Angriff auf Ridentd-0.9.2b funktioniert, beweist Abbildung 3.

Abbildung 3: Der Hacker hat Schreibrechte auf »/usr/lib/ispell« erlangt (oben). Er löscht alle Hashdateien und legt eine eigene mit Befehlen im Namen an (gelb hinterlegt). Später startet Root das Skript »ridentd.pl-0.9.2b« (unten). Ridentd hat den Touch-Befehl tatsächlich ausgeführt.
Weitere Macken aus Version 0.9.1b (Listing 1, Zeilen 136 bis 167) tauchten unverändert in Version 0.9.2b auf. Nachdem Ridentd die Prozess-ID eines noch laufenden Daemon-Prozesses gelesen hat (Zeile 139 bis 146), beendet er ihn zwangsweise mit dem Kill-Signal (Zeile 160). Zu diesem Zeitpunkt läuft Ridentd noch mit Root-Rechten.
Ist die vorige Instanz gestorben, ohne die PID-Datei zu löschen, hat der Kernel mittlerweile vielleicht einem anderen Prozess die gleiche ID zugewiesen. Um solche Prozesse zu verschonen, benutzt das Skript in Zeile 148 den Befehl »/bin/ps -p PID« und liest die Ausgabe. Auf Linux sieht diese für PID 4092 ungefähr so aus:
PID TTY TIME CMD 4092 pts/2 00:00:00 ridentd-0.9.2b.pl
Dieses Vorgehen ist für sich genommen schon riskant. Wie der »ps« im Detail arbeitet, hängt von der Unix-Variante ab. Traditionell kocht gerade bei diesem Befehl jeder Hersteller sein eigenes Süppchen. Angenommen das vierte Wort der betreffenden Zeile ist tatsächlich der Prozessname. Das Skript liest in einer Schleife zeilenweise die Ausgabe von »ps« (Zeilen 150 bis 156) und überprüft, ob der reguläre Ausdruck »ridentd.pl« darin auftaucht. Falls das auf irgendeine Zeile zutrifft, setzt es » auf »1« und zerstört dann später den zugehörigen Prozess.
Der reguläre Ausdruck trifft aber auf viele Prozessnamen zu. Zum einen dürfen links und rechts davon noch weitere Zeichen stehen, zum anderen interpretieren reguläre Ausdrücke den Punkt ».« als Platzhalter für ein beliebiges Zeichen. Die Bedingung ist demnach für »ridentXpl« oder »clean_rident.pl« ebenso erfüllt – möglicherweise trifft es also einen falschen Prozess, auch wenn das ziemlich unwahrscheinlich ist. Richtig ist der Ausdruck »bridentd.plb« (Listing 3, Zeile 200). Er versagt allerdings auch, wenn Ridentd unter einem anderen Namen läuft.
Das alles genügt noch nicht, wie die Situation in Abbildung 4 belegt. Der Ridentd findet einen alten Prozess und beschließt ihn zu töten. Noch bevor er dazu kommt, beendet sich der alte Daemon und der Kernel weist einem unbeteiligten Dritten die gleiche PID zu. Mit seinen Root-Rechten schießt Ridentd dann den falschen Prozess ab.

Abbildung 4: Bei ungünstigem Timing trifft der Kill-Befehl im Ridentd bis Version 0.9.2b den falschen Prozess.
Gegenmittel
Dass »ps« auf manchem System vielleicht nicht so funktioniert wie gewünscht, ist nicht zu ändern, aber die Folgen einer Fehlinterpretation lassen sich sehr wohl mildern. Als Hauptfehler erweist sich, dass der Kill-Befehl mit Root-Rechten arbeitet. Das ist unnötig, weil der Daemon-Prozess als »nobody« läuft.
Die fertige Lösung aus Ridentd 0.9.3b zeigt Listing 3. Die Funktion »sysread()« (Zeile 177) liest nun im Block von Zeile 170 bis 188 die Prozess-ID aus der PID-Datei. Genau genommen wäre das gar nicht nötig gewesen, der alte Code hat genauso gut funktioniert.
Interessant wird es in den Zeilen 209 bis 226. Mit »fork()« (Zeile 210) erzeugt das Skript einen Unterprozess und wartet in Zeile 218 auf dessen Beendigung. Währenddessen setzt das Kind in den Zeilen 222 und 223 seine User-ID auf »nobody« und die Group-ID auf die zugehörige Gruppe. Zeile 152 hat vorab die Variablen » und » passend belegt. Nur wenn das Ändern der IDs klappt, setzt Ridentd den Kill-Befehl ab und beendet sich (Zeilen 224). Damit trifft es jetzt schlimmstenfalls andere Prozesse des Benutzers Nobody.
Widrige Umwelt
Ein Thema blieb bisher ausgespart: Die Programmumgebung [4]. Der Ridentd bindet sich an den TCP-Port 113. Dazu braucht er Root-Rechte. Es wäre überhaupt keine gute Idee, ihm diese über das Set-UID-Root-Bit zu verschaffen, weil er dann zahlreiche Einstellungen des Aufrufers übernimmt. Auch von der Verwendung der Wrapper Sudo oder Super sei aus Sicherheitsgründen abgeraten. Am besten startet wirklich nur Root den Daemon.
Dass so viel Vorsicht durchaus angebracht ist, steht in den InSecurity News im Linux-Magazin 02/06. In den Versionen vor 1.6.8p12 konnte der aufrufende Benutzer unter anderem die Umgebungsvariable »PERLLIB« setzen und damit in das Skript eigenen Code einschleusen, der unter Root lief [9].
Die Zeilen 2 bis 8 in Listing 3 sind der etwas hilflose Versuch, einen Aufruf per Set-UID-Root-Bit zu verhindern. Im Ernstfall ist es an dieser Stelle aber schon zu spät und der Schaden bereits entstanden, aber vielleicht wird der Administrator durch die Meldung auf das Problem aufmerksam.
Zu guter Letzt ist es auch immer richtig, wenn ein Daemon das Wurzelverzeichnis als Arbeitsverzeichnis benutzt. Das bewirkt in diesem Fall die Funktion »chdir()« in Zeile 39.
Praktisches Perl
Die beliebte Skriptsprache Perl leidet zum Teil an den gleichen Krankheiten wie die in den bisherigen Folgen dieser Reihe intensiver diskutierten Sprachen C, C++ oder die Shell. Hinzu kommen noch spezifische Fallen wie die Syntax der Open-Funktion. Dass sich erwiesenermaßen mit Perl viele Aufgaben bequem und schnell erledigen lassen darf nicht dazu verleiten, Code unter Umgehung aller Sicherheitsüberlegungen zu schreiben. (fjl)
|
Infos |
|---|
|
[1] Rob J. Meijer, Ridentd: [http://www.xs4all.nl/~rmeijer/rident.html] [2] RFC 1413, “Identification Protocol”: [http://www.ietf.org/rfc/rfc1413.txt] [3] Ridentd-Meldung bei Security Tracker: [http://securitytracker.com/alerts/2004/Mar/1009552.html] [4] Dominik Vogt, “Umweltverschmutzung – Sicheres Programmieren für Administratoren, Folge 1”: Linux-Magazin 02/05, S. 54 [5] Dominik Vogt, “Wurzelbehandlung – Sicheres Programmieren für Administratoren, Folge 2”: Linux-Magazin 04/05, S. 64 [6] Dominik Vogt, “Gesichtskontrolle – Sicheres Programmieren für Administratoren, Folge 3”: Linux-Magazin 07/05, S. 62 [7] Dominik Vogt, “Giftiger Apfel – Sicheres Programmieren für Administratoren, Folge 4”: Linux-Magazin 10/05, S. 54 [8] Dominik Vogt, “Verständigungsfrage – Sicheres Programmieren für Administratoren, Folge 5”: Linux-Magazin 01/06, S 64 [9] InSecurity News, “Sudo”: Linux-Magazin 02/06, S. 31 und Security Tracker: [http://securitytracker.com/alerts/2005/Nov/1015192.html] |
|
Der Autor |
|---|
|
Dipl.-Math. Dominik Vogt ist langjähriger Software-Entwickler und Systemadministrator. Zurzeit arbeitet er als freiberuflicher EDV-Berater mit Schwerpunkt Softwaresicherheit. In seiner Freizeit werkelt er gerne am Windowmanager Fvwm. Für die gute Zusammenarbeit beim Verbessern von Ridentd möchte er Rob Meijer ausdrücklich danken. |





