++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++GOBBLES+SECURITY+RESEARCH+TEAM+INCORPORATED+++++++++++++++++ ALERT! ALERT! OFF-BY-ONE OVERFLOW IN THTTPD! ALERT! ALERT! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #include "/usr/share/examples/kld/.../include/note.h" GOBBLES say he English not very good but he try best to impart idea across with help from dictionary.com and joe editor ^[L with ispell. So GOBBLES by no mean linguist but he do best so reader understand security issue at hand and patch immediately so darkside malicious cracker out there in wild not given time to do destroying valuable data and belong to national security. Please keep in mind that GOBBLES try to be accurate with information but he can only do he best to not make error. Like joke goes what fly say to bee: "Just BEE yourself!" hehehee ok so GOBBLES just be himself and hope public understand he mean well and not here provide information to attacker but to team bugtraq penetrator and vendor who help fix issue. ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo PRODUCT ******* program: thttpd 2.20b (latest stable) and earlier website: http://www.acme.com/software/thttpd/thttpd.html SECURITY HISTORY **************** Mr Bernstein disclose gaping hole in thttpd 2.04: http://archives.neohapsis.com/archives/vuln-dev/1999-q4/0185.html DiGiT disclose gaping hole in thttpd CGI application 'ssi': http://packetstorm.decepticons.org/0005-exploits/ssibug Other bug like '%2e%2e' directory traversal vulnerability also disclosed to team bugtraq penetrator. BACKGROUND ********** GOBBLES members were in lab thinking about new way to punch hole in Internet when we thought about how WWW need webserver or it be quite useless hehe. So we start exploring possibility of webserver having hole and come across thttpd as promising security. GOBBLES now prove that promise broken. We did like so... bash-2.05$ cd thttpd-2.20b bash-2.05$ gtags bash-2.05$ htags -van ... so we could then use web browser to navigate webserver src because cscope just require much finger acrobatics he he he ;) What follows is technical details of hole and you going to see how mind of GOBBLES work to make critical program fall to its knees >:| TECHNICAL DETAILS ***************** bash-2.05$ pwd /home/GOBBLES/hacking/projects/current/thttpd-2.20b bash-2.05$ ls *.c fdwatch.c match.c strerror.c tdate_parse.c timers.c libhttpd.c mmc.c syslog.c thttpd.c Bug is in libhttpd.c/auth_check(): static int auth_check( httpd_conn* hc, char* dirname ) { static char* authpath; static int maxauthpath = 0; struct stat sb; char authinfo[500]; char* authpass; [...] l = b64_decode( &(hc->authorization[6]), authinfo, sizeof(authinfo) ); authinfo[l] = '\0'; Notice authinfo buffer and its total size (500) go b64_decode function so username and password in HTTP header 'Authorization' field may get decode from base64 for processing (processed by the process hehehe >8^) ). Then notice auth_check() terminate authinfo with a NUL. Notice only automatic variable above authinfo in source code is stat structure 'sb' since 'static' qualifier make compiler put variable in data or bss segment depending on initialization. Variable 'l' get assigned result of b64_decode() function. How big it can be??? GOBBLES paste full b64_decode function... static int b64_decode( const char* str, unsigned char* space, int size ) { const char* cp; int space_idx, phase; int d, prev_d = 0; unsigned char c; space_idx = 0; phase = 0; for ( cp = str; *cp != '\0'; ++cp ) { d = b64_decode_table[(int) *cp]; if ( d != -1 ) { switch ( phase ) { case 0: ++phase; break; case 1: c = ( ( prev_d << 2 ) | ( ( d & 0x30 ) >> 4 ) ); if ( space_idx < size ) space[space_idx++] = c; ++phase; break; case 2: c = ( ( ( prev_d & 0xf ) << 4 ) | ( ( d & 0x3c ) >> 2 ) ); if ( space_idx < size ) space[space_idx++] = c; ++phase; break; case 3: c = ( ( ( prev_d & 0x03 ) << 6 ) | d ); if ( space_idx < size ) space[space_idx++] = c; phase = 0; break; } prev_d = d; } } return space_idx; } Notice formal argument 'size' come from sizeof(authinfo) == 500. Then data stored in 'space' buffer which really 'authinfo' from other function. The variable 'space_idx' set to 0 and incremented as it used to index 'space' array. Size check "space_idx < size" mean space_idx can only reach 499. But then "space[space_idx++] = c" post-increment from 499 to 500. At end of function there is "return space_idx". Moving back... l = b64_decode( &(hc->authorization[6]), authinfo, sizeof(authinfo) ); authinfo[l] = '\0'; It made 'l' == 500 so "authinfo[500] = '\0'" be made and buffer is made overflow by one byte! THIS IS VERY BAD PROGRAMMING AND PROGRAMMER MUST LEARN NOT TO DO THIS SILLY KIND BUGS. WHEN PEOPLE LEARN????? Exploitable? Yes. If compiler arrange 'authinfo' first on stack, then on x86 machine it possible to overwrite saved register ebp value and fuck over process like described by Olaf Kirch in 1998 team bugtraq post which describe "Poison NUL Byte" method of punching hole in software to get in computer. DEMONSTRATION ************* 1) Apply following diff: --- libhttpd.c Tue Nov 20 14:50:00 2001 +++ libhttpd-new.c Tue Nov 20 14:22:12 2001 @@ -886,6 +886,7 @@ /* Decode it. */ l = b64_decode( &(hc->authorization[6]), authinfo, sizeof(authinfo) ); authinfo[l] = '\0'; + printf("%02x\n", authinfo[499]); /* Split into user and password. */ authpass = strchr( authinfo, ':' ); if ( authpass == (char*) 0 ) This allow us see what final element in array end up like. 2) Build and then: [terminal 1] mkdir test echo "joe:blow" > test/.htpasswd ./thttpd -D -p 7777 [terminal 2] (printf "GET /test/ HTTP/1.0\r\nAuthorization: Basic " ; printf `perl -e 'print "A"x550'` | openssl enc -base64 -e -in /dev/stdin ; printf \ "\r\n\r\n") | nc 0 7777 [terminal 1] We see '41'. This mean off-by-one overflow is really present! EXPLOIT ******* GOBBLES not release exploit until developer have time patch. Then it safe to provide exploit for team bugtraq commercial penetrator research community and so signature IDS vendor can add string for gobbles-exploit.c (but maybe not catch gobbles-exploit2.c hehehee j/k or other-exploit.c, but we provide enough information for IDS vendor to separate string from exploit ;)))) ) GREETS ****** dianora, tsk, snow, carolyn meinel, john vranesevich, steve gibson, kimble, emmanuel goldstein, box.sk, @stake, securityfocus, blackhat.com, defcon.org, 2600.com, #phrack@efnet, #hackphreak@undernet, bugtraq (thanks aleph1 and david ahmad for devoting your time to a great list), ntbugtraq (russel the love muscle ;D), cert.org, paul vixie, vesselin bontchev, reese witherspoon, kirstin dunst, katie holmes, aleister crowley, all our friends and family, and finally to everyone from #!GOBBLES on the irc. GOBBLES SECURITY http://www.bugtraq.org/