IIS - SOAP
This page describes how to run shellcode from a webshell with a .soap extension. Sometimes web applications use upload blacklists and forget about this extension type.
Last updated
This page describes how to run shellcode from a webshell with a .soap extension. Sometimes web applications use upload blacklists and forget about this extension type.
Last updated
Final proof of concept at https://github.com/0xbad53c/webshells/blob/main/iis/soapshell.soap
During one of our regular Purple Team workshops, we focused around so-called edge attacks: techniques to acquire an initial foothold on an internet-facing device. For this particular session, we deployed 4 Windows and Linux machines. For every OS type, there was 1 test box without defenses and 3 others, each with a top-tier EDR solution installed.
The machines had various vulnerable services, such as IIS with ASP and unrestricted file upload, PHP applications with known vulnerabilities, a Java Spring app with the recently disclosed Spring4Shell issue and an application with a buffer overflow vulnerability.
The goal of the workshop was to identify gaps in the detection of the default configuration to strenghten our own defenses with custom rules and improve our toolset for during Red Team engagements. We employed various techniques to gain a foothold and collaborated closely with our internal Blue Team to analyze detections.
When checking our the IIS possibilities, we stumbled accross a SOAP handler, which appears to be a lesser-known vector to acquire a webshell on the target.
Our journey begun with the discovery of the strange soap extension handler in the default ASP web.config. This means that the extension is likely enabled on any out of the box IIS installation with ASP support. The config file can be found at the path below:
C:\Windows\Microsoft.NET\Framework64\{Framework Version}\Config\Web.config
Two HTTP handlers immediately stood out. I never encountered these extensions in a web application before and it seemed quite strange for them to be enabled by default
You can also find these in the IIS Handler Mappings, as shown below.
Not much documentation of these extensions exist, so I decided to go for the trial and error approach by uploading a test file for each extension. Strangely enough, the .rem test file threw an error.
This can be verified by checking the Web.Config file again. Note how .rem does not have a build provider, but .soap does! Interesting fact: The build provider appeared to be the same as .asmx.
To verify this, I accessed the soap test file. There appeared to be an attempt to parse ASP - style code.
As most offensive security folks know, time is limited and we do not want to reinvent the wheel. I went ahead and navigated my way through existing .soap and .asmx webshell samples. There appeared to be very limited proof of concepts. The two that stood out were basically almost the same code but different extensions.
Sadly, I could not get the above webshells to work in my lab environment. However, one could easily spot the structure and differences for both extensions from the samples. With this knowledge, I tried to build my own stager webshell implementation.
First, I declared the webservice to be parsed by the ASP engine.
Next, I imported the libraries I wanted to use in the stager.
Followed by the webservice binding and namespace declaration.
More info at the following link:
Next, I defined the SoapStager class, which is an implementation of MarshalByRefObject. This is the main difference with the asmx extension.
The class begins with some unmanaged code imports, like VirtualAlloc and CreateThread to allocate executable memory and move the shellcode to a new thread of the webserver process (w3wp.exe)
Finally, I implemented the loadStage SOAP method to download raw shellcode from a local webserver via System.Net.webClient, allocate executable memory and copy the binary data to it. After this, the web method should create a new thread from the w3wp.exe IIS worker process via the CreateThread API call.
To verify if the shell worked, I uploaded it to an IIS webserver with unrestricted file upload. I chose to upload it as soap_final.soap.
Next, I accessed the newly uploaded page in the browser. This resulted in the following message, containing a link to the WSDL and loadStage method information:
At this point, the easiest way to build the correct soap request was to parse the WSDL XML automatically. In this case, I used BurpSuite's Wsdler extension. This was as easy as right clicking the request for the WSDL specification (add ?WSDL to the request to your uploaded SOAP file) and executing Extensions > Wsdler > Parse WSDL.
This resulted in a new entry in the Wsdler tab:
Finally, the SOAP request to execute the loadStage method was sent via Burp Repeater. HTTP Request:
Which resulted in the following HTTP Response, indicating successful execution:
In this case, a Cobalt Strike beacon successfully launched in w3wp.exe:
We tested these against some of the top-tier EDRs and surprisingly, the detection rate appeared to be quite low out of the box. Though, there is no need for most web server processes to be writing/modifying .soap extension files. Adding a detection rule for this should therefore be quite trivial.
Additionally, there is little documentation to available for development of pages with this .soap extension. Therefore, there is no reason for it to be enabled by default. Harden your IIS configuration by disabling this in your web.config. Perhaps Microsoft can disable this in future IIS with ASP deployments?