Microsoft says attackers increasingly use malicious Internet Information Services (IIS) web server extensions to backdoor unpatched Exchange servers as they have lower detection rates compared to web shells.
“In most cases, the actual backdoor logic is minimal and cannot be considered malicious without a broader understanding of how legitimate IIS extensions work, which also makes it difficult to determine the source of infection,” the Microsoft 365 Defender Research Team said Tuesday.
Custom IIS modules
Threat actors rarely deploy such malicious extensions after compromising a server using exploits for various unpatched security flaws in a hosted app. They’re usually deployed after a web shell is deployed as the first payload in the attack. The IIS module is deployed later to provide stealthier and persistent (update resistant) access to the hacked server.
After deployment, malicious IIS modules allow threat actors to harvest credentials from system memory, collect information from the victims’ network and infected devices, and deliver more payloads.
More recently, in a campaign between January and May 2022 that targeted Microsoft Exchange servers, attackers deployed malicious IIS extensions to gain access to victims’ email mailboxes, run commands remotely, and steal credentials and confidential data.
“After a period of reconnaissance, dumping credentials, and establishing a remote access method, the attackers installed a custom IIS backdoor called FinanceSvcModel.dll in the folder C:\inetpub\wwwroot\bin\,” Microsoft added.
The newly created extension should then be mapped with the target application to complete the registration. Generally, there are several methods that can be used to map managed modules for legitimate purposes.
Register with global assembly cache (GAC) PowerShell API: Every device with Common Language Runtime (CLR) hosts a device-wide cache called the global assembly cache (GAC). The GAC stores assemblies specifically designated to be shared by several applications on the device. GacInstall() is a PowerShell API to add modules into the global cache. Once installed, the module is available under the path %windir%\Microsoft.NET\assembly and is mapped to IIS (w3wp.exe) using appcmd.exe.
Register using appcmd.exe: Appcmd.exe is the single command line tool for managing IIS. All critical aspects, such as adding or removing modules and handlers, can be performed using the utility. In this case, the attackers drop the malicious extension in the target application’s /bin folder and map it using the add module command.
Register using gacutil.exe: Gacutil.exe is a Visual Studio shipped .NET GAC utility. The tool allows the user to view and manipulate the contents of the GAC, including installing new modules using the -I option.
Upon successful registration, the module is visible inside the IIS manager application.
Between January and May 2022, our IIS-related detections picked up an interesting campaign targeting Microsoft Exchange servers. Web shells were dropped in the path %ExchangeInstallPath%\FrontEnd\HttpProxy\owa\auth\ via Proxyshell exploit.
Indicators of compromise (IOCs)
File name | SHA-256 |
HttpCompress.dll | 4446f5fce13dd376ebcad8a78f057c0662880fdff7fe2b51706cb5a2253aa569 |
HttpSessionModule.dll | 1d5681ff4e2bc0134981e1c62ce70506eb0b6619c27ae384552fe3bdc904205c |
RewriterHttpModule.dll | c5c39dd5c3c3253fffdd8fee796be3a9361f4bfa1e0341f021fba3dafcab9739 |
Microsoft.Exchange.HttpProxy. HttpUtilities.dll | d820059577dde23e99d11056265e0abf626db9937fc56afde9b75223bf309eb0 |
HttpManageMoudle.dll | 95721eedcf165cd74607f8a339d395b1234ff930408a46c37fa7822ddddceb80 |
IIS_backdoor.dll | e352ebd81a0d50da9b7148cf14897d66fd894e88eda53e897baa77b3cc21bd8a |
FinanceSvcModel.dll | 5da41d312f1b4068afabb87e40ad6de211fa59513deb4b94148c0abde5ee3bd5 |
App_Web_system_web.ashx.dll | 290f8c0ce754078e27be3ed2ee6eff95c4e10b71690e25bbcf452481a4e09b9d |
App_Web_error.ashx.dll | 2996064437621bfecd159a3f71166e8c6468225e1c0189238068118deeabaa3d |
Detection & Response
Splunk:
source="WinEventLog:*" AND ((ParentImage="*\\w3wp.exe") AND ((((Image="*\\appcmd.exe") AND (CommandLine="*add module*" OR CommandLine="*appcmd.exe add module*")) OR (Image="*\\powershell.exe" AND (CommandLine="*system.enterpriseservices.internal.publish*"))) OR (Image="*\\gacutil.exe" AND (CommandLine="*/I*" OR CommandLine="*gacutil.exe /I*"))))
Qradar:
SELECT UTF8(payload) from events where LOGSOURCETYPENAME(devicetype)='Microsoft Windows Security Event Log' and ("ParentImage" ilike '%\w3wp.exe') and (((("Image" ilike '%\appcmd.exe') and ("Process CommandLine" ilike '%add module%' or "Process CommandLine" ilike '%appcmd.exe add module%')) or ("Image" ilike '%\powershell.exe' and ("Process CommandLine" ilike '%system.enterpriseservices.internal.publish%'))) or ("Image" ilike '%\gacutil.exe' and ("Process CommandLine" ilike '%/I%' or "Process CommandLine" ilike '%gacutil.exe /I%')))
Elastic Query:
(process.parent.executable.text:*\\w3wp.exe AND (((process.executable.text:*\\appcmd.exe AND process.command_line.text:(*add\ module* OR *appcmd.exe\ add\ module*)) OR (process.executable.text:*\\powershell.exe AND process.command_line.text:*system.enterpriseservices.internal.publish*)) OR (process.executable.text:*\\gacutil.exe AND process.command_line.text:(*\/I* OR *gacutil.exe\ \/I*))))
CarbonBlack:
(parent_name:*\\w3wp.exe AND (((process_name:*\\appcmd.exe AND process_cmdline:(*add\ module* OR *appcmd.exe\ add\ module*)) OR (process_name:*\\powershell.exe AND process_cmdline:*system.enterpriseservices.internal.publish*)) OR (process_name:*\\gacutil.exe AND process_cmdline:(*\/I* OR *gacutil.exe\ \/I*))))
Crowdstike:
((ParentBaseFileName="*\\w3wp.exe") AND ((((ImageFileName="*\\appcmd.exe") AND ((CommandLine="*add module*" OR CommandLine="*appcmd.exe add module*") OR (CommandHistory="*add module*" OR CommandHistory="*appcmd.exe add module*"))) OR (ImageFileName="*\\powershell.exe" AND ((CommandLine="*system.enterpriseservices.internal.publish*") OR (CommandHistory="*system.enterpriseservices.internal.publish*")))) OR (ImageFileName="*\\gacutil.exe" AND ((CommandLine="*/I*" OR CommandLine="*gacutil.exe /I*") OR (CommandHistory="*/I*" OR CommandHistory="*gacutil.exe /I*")))))
Fireeye:
(metaclass:`windows` pprocess:`*\w3wp.exe` (((process:`*\appcmd.exe` args:[`add module`,`appcmd.exe add module`]) OR (process:`*\powershell.exe` args:`system.enterpriseservices.internal.publish`)) OR (process:`*\gacutil.exe` args:[`/I`,`gacutil.exe /I`])))
Graylog:
(ParentImage.keyword:*\\w3wp.exe AND (((Image.keyword:*\\appcmd.exe AND CommandLine.keyword:(*add\ module* *appcmd.exe\ add\ module*)) OR (Image.keyword:*\\powershell.exe AND CommandLine.keyword:*system.enterpriseservices.internal.publish*)) OR (Image.keyword:*\\gacutil.exe AND CommandLine.keyword:(*\/I* *gacutil.exe\ \/I*))))
Logpoint:
(ParentImage IN "*\\w3wp.exe" (((Image IN "*\\appcmd.exe" CommandLine IN ["*add module*", "*appcmd.exe add module*"]) OR (Image="*\\powershell.exe" CommandLine IN "*system.enterpriseservices.internal.publish*")) OR (Image="*\\gacutil.exe" CommandLine IN ["*/I*", "*gacutil.exe /I*"])))
Microsoft Defender:
DeviceProcessEvents | where ((InitiatingProcessFolderPath endswith @"\w3wp.exe") and ((((FolderPath endswith @"\appcmd.exe") and (ProcessCommandLine contains "add module" or ProcessCommandLine contains "appcmd.exe add module")) or (FolderPath endswith @"\powershell.exe" and (ProcessCommandLine contains "system.enterpriseservices.internal.publish"))) or (FolderPath endswith @"\gacutil.exe" and (ProcessCommandLine contains "/I" or ProcessCommandLine contains "gacutil.exe /I"))))
RSA Netwitness:
((ParentImage contains '\w3wp\.exe') && ((((Image contains '\appcmd\.exe') && (CommandLine contains 'add module', 'appcmd\.exe add module')) || ((Image contains 'powershell.exe') && (CommandLine contains 'system\.enterpriseservices\.internal\.publish'))) || ((Image contains 'gacutil.exe') && (CommandLine contains '/I', 'gacutil\.exe /I'))))
Microsoft Sentinel:
SecurityEvent | where EventID == 4688 | where ((ParentProcessName endswith @'\w3wp.exe') and ((((NewProcessName endswith @'\appcmd.exe') and (CommandLine contains 'add module' or CommandLine contains 'appcmd.exe add module')) or (NewProcessName endswith @'\powershell.exe' and (CommandLine contains 'system.enterpriseservices.internal.publish'))) or (NewProcessName endswith @'\gacutil.exe' and (CommandLine contains '/I' or CommandLine contains 'gacutil.exe /I'))))
Sumologic:
(_sourceCategory=*windows* AND (ParentImage = "*\w3wp.exe") AND ((((((Image = "*\appcmd.exe") AND (CommandLine = "*add module*" OR CommandLine = "*appcmd.exe add module*")) OR (Image="*\powershell.exe" AND (CommandLine = "*system.enterpriseservices.internal.publish*")))) OR (Image="*\gacutil.exe" AND (CommandLine = "*/I*" OR CommandLine = "*gacutil.exe /I*")))))
Source/Credits: https://www.bleepingcomputer.com/news/microsoft/microsoft-iis-extensions-increasingly-used-as-exchange-backdoors/
Malicious IIS extensions quietly open persistent backdoors into servers