{
	"id": "fa7dbf24-ea51-4955-bdc1-321568bb5a85",
	"created_at": "2026-04-06T00:10:00.407725Z",
	"updated_at": "2026-04-10T13:11:43.898619Z",
	"deleted_at": null,
	"sha1_hash": "82647c7d13cc4bf61f74a35426bc180742fa9272",
	"title": "FoggyWeb: Targeted NOBELIUM malware leads to persistent backdoor | Microsoft Security Blog",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 3688970,
	"plain_text": "FoggyWeb: Targeted NOBELIUM malware leads to persistent backdoor\r\n| Microsoft Security Blog\r\nBy Ramin Nafisi, Microsoft Threat Intelligence\r\nPublished: 2021-09-27 · Archived: 2026-04-05 18:54:21 UTC\r\nMicrosoft continues to work with partners and customers to track and expand our knowledge of the threat actor we refer to\r\nas NOBELIUM, the actor behind the SUNBURST backdoor, TEARDROP malware, and related components. As we stated\r\nbefore, we suspect that NOBELIUM can draw from significant operational resources often showcased in their campaigns,\r\nincluding custom-built malware and tools. In March 2021, we profiled NOBELIUM’s GoldMax, GoldFinder, and Sibot\r\nmalware, which it uses for layered persistence. We then followed that up with another post in May, when we analyzed the\r\nactor’s early-stage toolset comprising EnvyScout, BoomBox, NativeZone, and VaporRage.\r\nThis blog is another in-depth analysis of newly detected NOBELIUM malware: a post-exploitation backdoor that Microsoft\r\nThreat Intelligence Center (MSTIC) refers to as FoggyWeb. As mentioned in previous blogs, NOBELIUM employs\r\nmultiple tactics to pursue credential theft with the objective of gaining admin-level access to Active Directory Federation\r\nServices (AD FS) servers. Once NOBELIUM obtains credentials and successfully compromises a server, the actor relies on\r\nthat access to maintain persistence and deepen its infiltration using sophisticated malware and tools. NOBELIUM uses\r\nFoggyWeb to remotely exfiltrate the configuration database of compromised AD FS servers, decrypted token-signing\r\ncertificate, and token-decryption certificate, as well as to download and execute additional components. Use of FoggyWeb\r\nhas been observed in the wild as early as April 2021.\r\nMicrosoft has notified all customers observed being targeted or compromised by this activity. If you believe your\r\norganization has been compromised, we recommend that you\r\nAudit your on-premises and cloud infrastructure, including configuration, per-user and per-app settings, forwarding\r\nrules, and other changes the actor might have made to maintain their access\r\nRemove user and app access, review configurations for each, and re-issue new, strong credentials following\r\ndocumented industry best practices.\r\nUse a hardware security module (HSM) as described in securing AD FS servers to prevent the exfiltration of secrets\r\nby FoggyWeb.\r\nMicrosoft security products have implemented detections and protections against this malware. Indicators of compromise\r\n(IOCs), mitigation guidance, detection details, and hunting queries for Azure Sentinel and Microsoft 365 Defender\r\ncustomers are provided at the end of this analysis and in the product portals. Active Directory Federation Services (AD FS)\r\nservers run on-premises and customers can also follow detailed guidance on securing AD FS servers against attacks.\r\nFoggyWeb is a passive and highly targeted backdoor capable of remotely exfiltrating sensitive information from a\r\ncompromised AD FS server. It can also receive additional malicious components from a command-and-control (C2) server\r\nand execute them on the compromised server.\r\nAfter compromising an AD FS server, NOBELIUM was observed dropping the following two files on the system\r\n(administrative privileges are required to write these files to the  folders listed below):\r\n%WinDir%\\ADFS\\version.dll\r\n%WinDir%\\SystemResources\\Windows.Data.TimeZones\\pris\\Windows.Data.TimeZones.zh-PH.pri\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 1 of 25\n\nFoggyWeb is stored in the encrypted file Windows.Data.TimeZones.zh-PH.pri, while the malicious file version.dll can be\r\ndescribed as its loader. The AD FS service executable Microsoft.IdentityServer.ServiceHost.exe loads the said DLL file via\r\nthe DLL search order hijacking technique that involves the core Common Language Runtime (CLR) DLL files (described in\r\ndetail in the FoggyWeb loader section). This loader is responsible for loading the encrypted FoggyWeb backdoor file and\r\nutilizing a custom Lightweight Encryption Algorithm (LEA) routine to decrypt the backdoor in memory.\r\nAfter de-obfuscating the backdoor, the loader proceeds to load FoggyWeb in the execution context of the AD FS application.\r\nThe loader, an unmanaged application, leverages the CLR hosting interfaces and APIs to load the backdoor, a managed\r\nDLL, in the same Application Domain within which the legitimate AD FS managed code is executed. This grants the\r\nbackdoor access to the AD FS codebase and resources, including the AD FS configuration database (as it inherits the AD FS\r\nservice account permissions required to access the configuration database).\r\nWhen loaded, the FoggyWeb backdoor (originally named Microsoft.IdentityServer.WebExtension.dll by its developer)\r\nfunctions as a passive and persistent backdoor that allows abuse of the Security Assertion Markup Language (SAML) token.\r\nThe backdoor configures HTTP listeners for actor-defined URIs that mimic the structure of the legitimate URIs used by the\r\ntarget’s AD FS deployment. The custom listeners passively monitor all incoming HTTP GET and POST requests sent to the\r\nAD FS server from the intranet/internet and intercept HTTP requests that match the custom URI patterns defined by the\r\nactor. This version of FoggyWeb configures listeners for the following hardcoded URI patterns (which might vary per\r\ntarget):\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 2 of 25\n\nHTTP GET URI pattern:\r\n/adfs/portal/images/theme/light01/profile.webp\r\n/adfs/portal/images/theme/light01/background.webp\r\n/adfs/portal/images/theme/light01/logo.webp\r\nHTTP POST URI pattern:\r\n/adfs/services/trust/2005/samlmixed/upload\r\nEach HTTP GET/POST URI pattern above corresponds to a C2 command:\r\nWhen the AD FS server receives an HTTP GET request containing the URI pattern\r\n/adfs/portal/images/theme/light01/profile.webp, the backdoor retrieves the token signing certificate of the\r\ncompromised AD FS server and then obfuscates and returns the certificate to the issuer of the request.\r\nSimilarly, when the AD FS server receives an HTTP GET request containing the URI pattern\r\n/adfs/portal/images/theme/light01/background.webp, the backdoor retrieves the token decryption certificate of the\r\ncompromised AD FS server and then obfuscates and returns the certificate to the issuer of the request.\r\nWhen the AD FS server receives an HTTP GET request containing the URI pattern\r\n/adfs/portal/images/theme/light01/logo.webp, the backdoor retrieves the AD FS configuration data of the\r\ncompromised server, obfuscates the data, and returns the obfuscated data to the issuer of the request.\r\nWhen the AD FS server receives an HTTP POST request containing the URI pattern\r\n/adfs/services/trust/2005/samlmixed/upload, the backdoor treats the obfuscated and compressed POST data as either\r\n.NET assembly or source code. If assembly, the backdoor executes the assembly in the execution context of the AD\r\nFS process. If source code, the backdoor dynamically compiles the source code and proceeds to execute the resulting\r\nmemory-resident assembly in the execution context of the AD FS process.\r\nThe diagram below illustrates the methodology used by the actor to communicate with the FoggyWeb backdoor located on a\r\ncompromised internet-facing AD FS server.\r\nSince FoggyWeb runs in the context of the main AD FS process, it inherits the AD FS service account permissions required\r\nto access the AD FS configuration database. This contrasts with tools such as ADFSDump that must be executed under the\r\nuser context of the AD FS service account. Also, because FoggyWeb is loaded into the same application domain as the AD\r\nFS managed code, it gains programmatical access to the legitimate AD FS classes, methods, properties, fields, objects, and\r\ncomponents that are subsequently leveraged by FoggyWeb to facilitate its malicious operations. For example, this allows\r\nFoggyWeb to gain access to the AD FS configuration data without connecting to the WID named pipe or manually running\r\nSQL queries to retrieve configuration information (for example, to obtain the EncryptedPfx blob from the configuration\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 3 of 25\n\ndata). FoggyWeb is also AD FS version-agnostic; it does not need to keep track of legacy versus modern configuration table\r\nnames and schemas, named pipe names, and other version-dependent properties of AD FS.\r\nFoggyWeb loader\r\nThe file version.dll is a malicious loader responsible for loading an encrypted backdoor file from the file system, decrypting\r\nthe backdoor file, and loading it in memory. This malicious DLL, which shares a name with a legitimate Windows DLL\r\nlocated in the %WinDir%\\System32\\ folder, is meant to be placed in the main AD FS folder %WinDir%\\ADFS\\, where the\r\nAD FS service executable Microsoft.IdentityServer.ServiceHost.exe is located (for reasons described later in this section).\r\nWhen the AD FS service (adfssrv) is started, the service executable Microsoft.IdentityServer.ServiceHost.exe gets executed.\r\nAs a .NET-based managed application, Microsoft.IdentityServer.ServiceHost.exe imports an unmanaged Windows DLL\r\nnamed mscoree.dll.\r\nThe file mscoree.dll dynamically loads another unmanaged Windows/CLR DLL named mscoreei.dll. As shown below,\r\nmscoreei.dll has a delay load import (Delay Import) named version.dll.\r\nNOBELIUM, with existing administrative permissions, was observed to drop a malicious loader named version.dll in the\r\n%WinDir%\\ADFS\\ folder where the AD FS service executable Microsoft.IdentityServer.ServiceHost.exe is located. Once the\r\nsystem or the AD FS service is restarted, Microsoft.IdentityServer.ServiceHost.exe loads mscoree.dll, which in turn loads\r\nmscoreei.dll. As mentioned above, mscoreei.dll has a delay load import named version.dll. Once loaded, instead of loading\r\nthe legitimate version.dll from the %WinDir%\\System32\\ folder mscoreei.dll loads the malicious version.dll planted by the\r\nattacker in %WinDir%\\ADFS\\ folder (referred to as DLL search order hijacking), as shown in the call stack below.\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 4 of 25\n\nThe malicious loader version.dll behaves as a proxy for all legitimate version.dll export function calls. As shown below, it\r\nexports the same 17 function names as the legitimate version of version.dll.\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 5 of 25\n\nThe export functions of the malicious version.dll are all short stubs that call a single trampoline function labeled\r\nTrampolineFunction, as seen in the screenshot below.\r\nBelow is a pseudocode for the trampoline function.\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 6 of 25\n\nThis trampoline function is responsible for the following:\r\nCalling a function (labeled as LoadDecryptExecuteBackdoor() by the analyst) to load a backdoor file from the file\r\nsystem, and then decrypting and executing the file in memory\r\nTransferring execution to the initially called target function from the legitimate version of version.dll.\r\nThe trampoline function preserves the value of the arguments/registers intended for the function from the legitimate version\r\nof version.dll by saving the value of certain CPU registers. It first pushes them onto the stack before calling the\r\nLoadDecryptExecuteBackdoor() function above and then restoring them before transferring execution to the function from\r\nthe legitimate version of version.dll.\r\nWhen called, LoadDecryptExecuteBackdoor() attempts to create a Windows event named {2783c149-77a7-5e51-0d83-\r\nac0566daff96} to ensure that only one copy of the loader is actively running on the system. In a new thread, it then checks if\r\nthe following file is present (hardcoded path string):\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 7 of 25\n\nC:\\Windows\\SystemResources\\Windows.Data.TimeZones\\pris\\Windows.Data.TimeZones.zh-PH.pri\r\nWindows.Data.TimeZones.zh-PH.pri is an encrypted backdoor file that is placed in the folder above. MSTIC refers to this\r\nbackdoor file as FoggyWeb, and our analysis is in the next section.\r\nMicrosoft.IdentityServer.ServiceHost.exe in and of itself is an unmanaged Windows executable that is generated when the\r\nhigh-level AD FS managed code is compiled. When executed, the unmanaged code inside\r\nMicrosoft.IdentityServer.ServiceHost.exe leverages Common Language Runtime (CLR) to run the managed AD FS code\r\nwithin a virtual runtime environment. This virtual runtime environment is comprised of one or more application domains,\r\nwhich provide a unit of isolation for the runtime environment and allow different applications to run inside separate\r\ncontainers within a process. The managed AD FS code is executed within an application domain inside the virtual runtime\r\nenvironment.\r\nThe FoggyWeb backdoor (also a managed DLL) is intended to run alongside the legitimate AD FS code (that is, within the\r\nsame application domain). This means that for the FoggyWeb loader to load the backdoor alongside the AD FS code, it\r\nneeds to gain access to the same application domain that the AD FS code is executed within. Since the FoggyWeb loader\r\nversion.dll is an unmanaged application, it cannot directly access the virtual runtime environment that the managed AD FS\r\ncode is executed within. The loader overcomes this limitation and loads the backdoor alongside the AD FS code by\r\nleveraging the CLR hosting interfaces and APIs to access the virtual runtime environment within which the AD FS code is\r\nexecuted.\r\nThe loader performs the following high-level actions:\r\nEnumerate all CLRs loaded in the AD FS process Microsoft.IdentityServer.ServiceHost.exe\r\nFor each CLR, enumerate all running application domains and perform the following actions for each domain:\r\nRead the contents of the following encrypted FoggyWeb backdoor file into memory:\r\nC:\\Windows\\SystemResources\\Windows.Data.TimeZones\\pris\\Windows.Data.TimeZones.zh-PH.pri\r\nDecrypt the encrypted FoggyWeb backdoor file using the Lightweight Encryption Algorithm (LEA). The\r\nLEA-128 key schedule uses the following hardcoded master key to generate the round keys:\r\nAfter decrypting each 16-byte cipher block, the loader uses the following XOR key to decode each individual\r\ndecrypted/plaintext block:\r\nThis is equivalent to first LEA decrypting the entire file and then XOR decoding the decrypted data (instead of decrypting\r\nand XOR decoding each individual 16-byte block).\r\nCreate a Safe Array and copy the decrypted FoggyWeb backdoor bytes to the array. It then calls the Load() function\r\nfor the current application domain to load the FoggyWeb DLL into the application domain. After the FoggyWeb DLL\r\nis loaded into the current application domain, the loader invokes the following method from the DLL:\r\nMicrosoft.IdentityServer.WebExtension.WebHost.\r\nAt this point in the execution cycle, the FoggyWeb DLL is loaded into one or more application domains where the legitimate\r\nAD FS code is running. This means the backdoor code runs alongside the AD FS code with the same access and permissions\r\nas the AD FS application. Because the backdoor is loaded in the same application domain as the AD FS code, it gains\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 8 of 25\n\nprogrammatical access to the legitimate classes, methods, properties, fields, objects, and components used by various AD FS\r\nmodules to carry out their legitimate functionality. Such access allows the FoggyWeb backdoor to directly interact with the\r\nAD FS codebase (that is, not an external disk-resident tool) and selectively invoke native AD FS methods needed to\r\nfacilitate its malicious operations.\r\nFoggyWeb backdoor\r\nThis malicious memory-resident DLL (originally named Microsoft.IdentityServer.WebExtension.dll by its developer)\r\nfunctions as a backdoor targeting AD FS. It is loaded by the main AD FS service process\r\nMicrosoft.IdentityServer.ServiceHost.exe through a malicious loader component.\r\nWhen loaded, the backdoor starts an HTTP listener that listens for HTTP GET and POST requests containing the following\r\nURI patterns:\r\nHTTP GET URI pattern: /adfs/portal/images/theme/light01/\r\nHTTP POST URI pattern: /adfs/services/trust/2005/samlmixed/upload\r\nAs shown below, the URI patterns are hardcoded in the backdoor and mimic the structure of the legitimate URIs used by the\r\ntarget’s AD FS deployment.\r\nOnce the backdoor receives an HTTP request that contains one of the URI patterns above, the listener proceeds to handle the\r\nrequest using either an HTTP GET or HTTP POST callback/handler method (ProcessGetRequest() and\r\nProcessGetRequest(), respectively).\r\nHTTP GET handler\r\nThe incoming HTTP GET requests that contain the URI pattern /adfs/portal/images/theme/light01/ are handled by\r\nbackdoor’s ProcessGetRequest() method.\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 9 of 25\n\nIf an incoming HTTP GET request is issued for a file/resource with the file extension of .webp, the ProcessGetRequest()\r\nmethod proceeds to handle the request. Otherwise, the request is ignored by the backdoor. Also, if the requested file name\r\nmatches one of the three hardcoded names below, the backdoor treats the request as a C2 command issued by the attacker.\r\nThe following URL patterns are treated as C2 commands:\r\n/adfs/portal/images/theme/light01/profile.webp\r\n/adfs/portal/images/theme/light01/background.webp\r\n/adfs/portal/images/theme/light01/logo.webp\r\nThe first two C2 commands, profile.webp and background.webp (UrlGetFileNames[0] and UrlGetFileNames[1] in the\r\nscreenshot above), are handled by calling the backdoor’s Service.GetCertificate() method.\r\nAs the name suggests, this method is responsible for retrieving an AD FS certificate (either the token- signing or the token\r\nencryption certificate, depending on the value of the certificateType parameter passed to the method) from the AD FS\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 10 of 25\n\nservice configuration database.\r\nAnalyst note: Refer to the Appendix for an in-depth analysis of the Service.GetCertificate() method and how it obtains and\r\ndecrypts either the token signing or encryption certificate.\r\nAs shown in the screenshot above, when the C2 command profile.webp (UrlGetFileNames[0]) is issued to the backdoor (by\r\nissuing an HTTP GET request for the URI /adfs/portal/images/theme/light01/profile.webp), the backdoor retrieves the\r\ntoken-signing certificate of the compromised AD FS server. Similarly, when the C2 command background.webp\r\n(UrlGetFileNames[1]) is issued to the backdoor (by issuing an HTTP GET request for the URI\r\n/adfs/portal/images/theme/light01/background.webp), the backdoor retrieves the token encryption certificate of the\r\ncompromised AD FS server.\r\nThe third C2 command, logo.webp (UrlGetFileNames[2]), is triggered by sending an HTTP GET request to the following\r\nURI: /adfs/portal/images/theme/light01/logo.webp. The C2 command is handled by calling the backdoor’s GetInfo()\r\nmethod.\r\nThe GetInfo() method is responsible for dumping the AD FS service configuration data of the compromised server.\r\nAs shown above, the AD FS service configuration data is obtained via the ServiceSettingsData property, which retrieves the\r\ndata from the AD FS service configuration database, Windows Internal Database (WID).\r\nBefore returning the output of the C2 commands (that is, the token-signing certificate, the token encryption certificate, or the\r\nAD FS service configuration data) to the C2 in an HTTP 200 response, the backdoor first obfuscates the output by calling its\r\nmethod named GetWebpImage().\r\nThe GetWebpImage() method is in charge of masquerading the output of the C2 commands as a legitimate WebP file (by\r\nadding appropriate RIFF/WebP file header magic/fields) and encoding the resulting WebP file.\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 11 of 25\n\nGetWebpImage() uses the following helper methods to create and encode the fake WebP file that contains the C2 command\r\noutput:\r\nGetWebpImage() first invokes the Webp.GetFrame() method, which is responsible for compressing the output of the\r\nC2 command and copying the compressed version to a new array (0 padded to a multiple of 32 bytes). The length of\r\nthe compressed data is added as the first four bytes of the new array.\r\nTo compress the data, GetFrame() invokes the Common.Compress() method, which is used to compress the data by\r\nleveraging the C# GZipStream compression class.\r\nFor demonstration purposes, assume the C2 command yields the following data (a 256-byte pseudo-randomly generated\r\nbyte array).\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 12 of 25\n\nGiven the data above (that is, sample C2 command output), GetFrame() returns the following byte array.\r\nNext, GetWebpImage() invokes the Webp.GetWebpHeader() method, passing in the size of the byte array returned by\r\nGetFrame() in the step above. GetWebpHeader() is responsible  for creating and returning an array containing\r\ncustom RIFF WebP file magic/header bytes.\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 13 of 25\n\nThe array variable above contains the following 32-byte hardcoded RIFF/WebP header bytes.\r\nIf the size of the array passed to GetWebpHeader() (returned by GetFrame()) exceeds 8,192 bytes, the bytes at index 26 and\r\n28 of the header bytes (initially set to 0x00) are replaced with 0x80. Otherwise, the bytes at index 26 and 28 are replaced\r\nwith 0x40, as shown below.\r\n GetWebpHeader() then returns the custom RIFF/WebP header above to GetWebpImage().\r\nNext, GetWebpImage() creates a new array by appending the custom RIFF/WebP header bytes returned by\r\nGetWebpHeader() to the array returned by GetFrame() (the array containing the compressed version of the C2\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 14 of 25\n\ncommand output).\r\nGetWebpImage() calls the Common.ProtectData() method of the backdoor to encode the portion of the new array that\r\ncontains the compressed bytes (that is, it does not encode the custom RIFF/WebP header). As the second argument,\r\nGetWebpImage() passes the offset of the first compressed byte to ProtectData() (as shown in the table above, 0x20 or 32 is\r\nthe offset of the first compressed byte in this case). ProtectData() uses a dynamic XOR key and a custom XOR methodology\r\nto XOR encode the compressed data.\r\nInitially, the 12-byte hardcoded XOR key array contains the following (seed) bytes.\r\nAs shown in the screenshot above, each byte of compressed data is XOR’d with a byte from the XOR key array. The first\r\nbyte of the compressed data (0x17) is XOR’d with the XOR key byte located at offset 8 of the key array (0x77).\r\nAfter XOR’ing the first byte of the compressed data with the XOR key byte located at offset 8 of the key array, the XOR key\r\nbyte itself gets overwritten with a new value.\r\nFor example, the XOR key byte located at offset 8 of the XOR key array (0x77) gets overwritten with 0xEE via the\r\nfollowing operations.\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 15 of 25\n\nThe second byte of the compressed data (0x01) is XOR’d with the XOR key byte located at offset 9 of the key array (33 %\r\n12 = 9) and so on until the key rolls to the first byte of the XOR array (as mentioned above, the XOR key bytes get\r\noverwritten after each encoding operation). Below is the XOR encoded version of the sample compressed array.\r\nAfter the steps outlined above, GetWebpImage() returns the following sample data to the method that invokes it to obfuscate\r\nand conceal the output of each C2 command (ProcessGetRequest()).\r\nAs previously mentioned, ProcessGetRequest() returns the fake RIFF/WebP file generated above (containing stolen token-signing certificate, token encryption certificate, or the AD FS service configuration data) to the C2 in an HTTP 200\r\nresponse.\r\nIf the backdoor cannot execute a C2 command successfully, it returns an HTTP 404 response to the C2 instead.\r\nHTTP POST handler\r\nIncoming HTTP POST requests that match the URI pattern /adfs/services/trust/2005/samlmixed/upload are handled by the\r\nProcessPostRequest() method.\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 16 of 25\n\nThis method ensures that the ContentType value of an incoming HTTP POST request ends with “xml” (case-insensitive),\r\nand the HTTP POST data contains two XML elements named X509Certificate and SignatureValue (for example, a blob that\r\nstarts with the string “\u003cX509Certificate\u003e” and ends with the string “\u003c/X509Certificate\u003e”).\r\nIf the XML data contains the two elements, the backdoor performs the following actions:\r\nDecode the values of the SignatureValue and X509Certificate elements by first decoding the values using Base64 and\r\nthen calling the Common.UprotectData() method on each decoded value.\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 17 of 25\n\nThe UprotectData() method treats the first two bytes of the Base64 decoded value as a two-byte XOR key. It invokes the\r\nCommon.ProtectData() method (covered in the previous section) on the rest of the data (that is, third byte on) and then uses\r\nthe two-byte XOR key to XOR decode the data returned by Common.ProtectData(). In other words, UprotectData()\r\nleverages Common.ProtectData() to remove the first layer of XOR encoding and then another XOR routine to remove the\r\nsecond layer of XOR encoding applied to the data.\r\nInvoke the Service.ExecuteAssembly() method to handle the decoded SignatureValue and X509Certificate values. As\r\nshown below, the decoded X509Certificate value is the first GZip decompressed/inflated by calling the\r\nCommon.Decompress() method.\r\nIn a new thread, Service.ExecuteAssembly() calls Service.ExecuteAssemblyRoutine() method to handle the data.\r\nExecuteAssemblyRoutine() checks if the decoded X509Certificate value starts with “MZ” (or the bytes 0x4D 0x5A,\r\nthe hexadecimal representation of the decimal numbers 77 and 90, as seen in the screenshot below).\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 18 of 25\n\nIf the decoded X509Certificate value starts with “MZ,” the backdoor treats the decoded data as a .NET-based\r\nassembly/payload and proceeds to call its Service.ExecuteBinary() method to load and execute the DLL payload in\r\nmemory. After loading the DLL in memory, ExecuteBinary() proceeds to invoke a specific method from the loaded\r\nDLL. The method name and parameters needed to invoke the method are supplied to the backdoor within the\r\ndecoded SignatureValue data.\r\nIf the decoded X509Certificate value does not start with MZ, the backdoor treats the decoded X509Certificate value as\r\nsource code for a C#-based payload and calls its Service.ExecuteSource() method to dynamically compile and execute the\r\npayload in memory.\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 19 of 25\n\nAfter handling the HTTP POST request containing the XML elements X509Certificate and SignatureValue, the backdoor\r\nresponds to the request with an HTTP 204 response code. If the HTTP POST does not have the elements mentioned above,\r\nthe backdoor responds to the request with an HTTP 404 response code.\r\nAs the name suggests, the Service.GetCertificate() method is responsible for retrieving an AD FS certificate (either the\r\ntoken- signing or the token encryption certificate, depending on the value of the certificateType parameter passed to the\r\nmethod) from the AD FS service configuration database.\r\nThe method performs the following actions to retrieve the desired certificate:\r\nInvoke another one of its methods named GetServiceSettingsDataProvider() to create an instance of type\r\nMicrosoft.IdentityServer.PolicyModel.Configuration.ServiceSettingsDataProvider from the already loaded assembly\r\nMicrosoft.IdentityServer.\r\nInvoke the GetServiceSettings() member/method of the above ServiceSettingsDataProvider instance to obtain the AD\r\nFS service configuration settings.\r\nObtain the value of the AD FS service settings (from the SecurityTokenService property), extract the value of the\r\nEncryptedPfx blob from the service settings, and decode the blob using Base64.\r\nInvoke another method named GetAssemblyByName() to enumerate all loaded assemblies by name and locate the\r\nalready loaded assembly Microsoft.IdentityServer.Service. This method retrieves the value of two fields named _state\r\nand _certificateProtector from an object of type\r\nMicrosoft.IdentityServer.Service.Configuration.AdministrationServiceState (from the Microsoft.IdentityServer.Service\r\nassembly).\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 20 of 25\n\nThe AdministrationServiceState class/object contains configuration information necessary for the execution and handling of\r\nclient requests. The field _state is used to maintain the current state of the AdministrationServiceState class/object\r\n(screenshot from Microsoft.IdentityServer.Service.dll).\r\nThe AdministrationServiceState object (stored in the _state field) contains another field named _certificateProtector.\r\nThe field _certificateProtector stores an instance of the Data Protector class DkmDataProtector for Distributed Key\r\nManagement (DKM). The DkmDataProtector class implements a method named Unprotect(), which ultimately calls the\r\nUnprotect() method of DKM/IDKM (screenshot from Microsoft.IdentityServer.dll).\r\nThe DKM Unprotect() method inherits a method named Unprotect() from Microsoft.IdentityServer.Dkm.DKMBase\r\n(screenshot from Microsoft.IdentityServer.Dkm.dll).\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 21 of 25\n\nThe Unprotect() method from Microsoft.IdentityServer.Dkm.DKMBase (shown above) provides the functionality to decrypt\r\nthe encrypted certificate (a PKCS12 object) stored in the EncryptedPfx blob.\r\nArmed with the knowledge about the availability of the Unprotect() method accessible via the _certificateProtector field, the\r\nbackdoor invokes the Unprotect() method to decrypt the encrypted certificate stored in the EncryptedPfx blob of the desired\r\ncertificate type (either the AD FS token signing or encryption certificate).\r\nA variant of the technique described in this Appendix was publicly presented by Douglas Bienstock and Austin Baker at the\r\nTROOPERS conference in 2019 (I am AD FS and so can you: Attacking Active Directory Federated Services). However,\r\nthe method used by FoggyWeb differs from the publicly presented method, in that FoggyWeb leverages the _state and\r\n_certificateProtector fields from the AdministrationServiceState class/object to facilitate access to the Data Protector class\r\nDkmDataProtector (used to gain access to and invoke the Unprotect() method).\r\nIndicators of compromise (IOCs)\r\nType\r\nThreat\r\nName\r\nThreat\r\nType\r\nIndicator\r\nMD5 FoggyWeb Loader 5d5a1b4fafaf0451151d552d8eeb73ec\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 22 of 25\n\nSHA-1\r\nFoggyWeb Loader c896ece073dd01191cbc1d462bc2f47161828a83\r\nSHA-256\r\nFoggyWeb Loader 231b5517b583de102cde59630c3bf938155d17037162f663874e4662af2481b1\r\nMD5 FoggyWeb\r\nBackdoor\r\n(encrypted)\r\n9ff9401315d0f7258a9fcde0cfdef02b\r\nSHA-1\r\nFoggyWeb\r\nBackdoor\r\n(encrypted)\r\n4597431f26424cb814c917168fa8d74d01ab7cd1\r\nSHA-256\r\nFoggyWeb\r\nBackdoor\r\n(encrypted)\r\nda0be762bb785085d36aec80ef1697e25fb15414514768b3bcaf798dd9c9b169\r\nMD5 FoggyWeb\r\nBackdoor\r\n(decrypted)\r\ne9671d294ce41fe6dbb9637dc0157a88\r\nSHA-1\r\nFoggyWeb\r\nBackdoor\r\n(decrypted)\r\n85cfeccbb48fd9f498d24711c66e458e0a80cc90\r\nSHA-256\r\nFoggyWeb\r\nBackdoor\r\n(decrypted)\r\n568392bd815de9b677788addfc4fa4b0a5847464b9208d2093a8623bbecd81e6\r\nMitigations\r\nCustomers should review their AD FS Server configuration and implement changes to secure these systems from attacks:\r\nBest Practices for securing AD FS and Web Application Proxy\r\nWe strongly recommend for organizations to harden and secure AD FS deployments through the following best practices:\r\nEnsure only Active Directory Admins and AD FS Admins have admin rights to the AD FS system.\r\nReduce local Administrators’ group membership on all AD FS servers.\r\nRequire all cloud admins to use multi-factor authentication (MFA).\r\nEnsure minimal administration capability via agents.\r\nLimit on-network access via host firewall.\r\nEnsure AD FS Admins use Admin Workstations to protect their credentials.\r\nPlace AD FS server computer objects in a top-level OU that doesn’t also host other servers.\r\nEnsure that all GPOs that apply to AD FS servers apply only to them and not to any other servers. This limits\r\npotential privilege escalation through GPO modification.\r\nEnsure that the installed certificates are protected against theft. Don’t store these on a share on the network and set a\r\ncalendar reminder to ensure they get renewed before expiring (expired certificate breaks federation auth).\r\nAdditionally, we recommend protecting signing keys or certificates in a hardware security module (HSM) attached to\r\nAD FS.\r\nSet logging to the highest level and send the AD FS (and security) logs to a SIEM to correlate with AD authentication\r\nas well as Azure AD (or similar).\r\nRemove unnecessary protocols and Windows features.\r\nUse a long (\u003e25 characters) and complex password for the AD FS service account. We recommend using a Group\r\nManaged Service Account (gMSA) as the service account, as it removes the need for managing the service account\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 23 of 25\n\npassword over time by managing it automatically.\r\nUpdate to the latest AD FS version for security and logging improvements (as always, test first).\r\nWhen federated with Azure AD follow the best practices for securing and monitoring the AD FS trust with Azure\r\nAD.\r\nDetections\r\nProtecting AD FS servers is key to mitigating NOBELIUM attacks. Detecting and blocking malware, attacker activity, and\r\nother malicious artifacts on AD FS servers can break critical steps in known NOBELIUM attack chains. Microsoft Defender\r\nAntivirus detects the new NOBELIUM components discussed in this blog as the following malware:\r\nLoader: Trojan:Win32/FoggyWeb.A!dha\r\nBackdoor: Trojan:MSIL/FoggyWeb.A!dha\r\nMicrosoft 365 Defender\r\nEndpoint detection and response (EDR) capabilities in Microsoft Defender for Endpoint detect malicious behavior related to\r\nthis malware which is surfaced as alerts with the following titles:\r\nA suspicious DLL was loaded by the ADFS service\r\nSuspicious service launched\r\nSuspicious file dropped\r\nThis kind of attack can also be detected in the cloud using Azure AD Identity Protection. It is recommended that you\r\nmonitor the Azure AD Identity Protection Risk detections report for the “Token Issuer Anomaly” detection. This detection\r\nlooks for anomalies in the SAML token presented to the Azure AD tenant.\r\nAdvanced hunting queries\r\nMicrosoft Defender for Endpoint\r\nTo locate related activity, run the following advanced hunting queries in Microsoft 365 Defender:\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 24 of 25\n\nDeviceImageLoadEvents\r\n| where FolderPath has @\"C:\\Windows\\ADFS\"\r\n| where FileName has @\"version.dll\"\r\nAzure Sentinel\r\nAzure Sentinel customers can use the following detection queries to look for this activity:\r\nDetection query: https://github.com/Azure/Azure-Sentinel/tree/master/Detections/MultipleDataSources/Nobelium_FoggyWeb.yaml\r\nIndicator file: https://github.com/Azure/Azure-Sentinel/tree/master/Sample%20Data/Feeds/FoggyWebIOC.csv\r\nSource: https://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nhttps://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/\r\nPage 25 of 25",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE",
		"ETDA"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://www.microsoft.com/security/blog/2021/09/27/foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor/"
	],
	"report_names": [
		"foggyweb-targeted-nobelium-malware-leads-to-persistent-backdoor"
	],
	"threat_actors": [
		{
			"id": "b43e5ea9-d8c8-4efa-b5bf-f1efb37174ba",
			"created_at": "2022-10-25T16:07:24.36191Z",
			"updated_at": "2026-04-10T02:00:04.954902Z",
			"deleted_at": null,
			"main_name": "UNC2452",
			"aliases": [
				"Dark Halo",
				"Nobelium",
				"SolarStorm",
				"StellarParticle",
				"UNC2452"
			],
			"source_name": "ETDA:UNC2452",
			"tools": [],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "1d3f9dec-b033-48a5-8b1e-f67a29429e89",
			"created_at": "2022-10-25T15:50:23.739197Z",
			"updated_at": "2026-04-10T02:00:05.275809Z",
			"deleted_at": null,
			"main_name": "UNC2452",
			"aliases": [
				"UNC2452",
				"NOBELIUM",
				"StellarParticle",
				"Dark Halo"
			],
			"source_name": "MITRE:UNC2452",
			"tools": [
				"Sibot",
				"Mimikatz",
				"Cobalt Strike",
				"AdFind",
				"GoldMax"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "a241a1ca-2bc9-450b-a07b-aae747ee2710",
			"created_at": "2024-06-19T02:03:08.150052Z",
			"updated_at": "2026-04-10T02:00:03.737173Z",
			"deleted_at": null,
			"main_name": "IRON RITUAL",
			"aliases": [
				"APT29",
				"Blue Dev 5 ",
				"BlueBravo ",
				"Cloaked Ursa ",
				"CozyLarch ",
				"Dark Halo ",
				"Midnight Blizzard ",
				"NOBELIUM ",
				"StellarParticle ",
				"UNC2452 "
			],
			"source_name": "Secureworks:IRON RITUAL",
			"tools": [
				"Brute Ratel C4",
				"Cobalt Strike",
				"EnvyScout",
				"GoldFinder",
				"GoldMax",
				"NativeZone",
				"RAINDROP",
				"SUNBURST",
				"Sibot",
				"TEARDROP",
				"VaporRage"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "46b3c0fc-fa0c-4d63-a38a-b33a524561fb",
			"created_at": "2023-01-06T13:46:38.393409Z",
			"updated_at": "2026-04-10T02:00:02.955738Z",
			"deleted_at": null,
			"main_name": "APT29",
			"aliases": [
				"Cloaked Ursa",
				"TA421",
				"Blue Kitsune",
				"BlueBravo",
				"IRON HEMLOCK",
				"G0016",
				"Nobelium",
				"Group 100",
				"YTTRIUM",
				"Grizzly Steppe",
				"ATK7",
				"ITG11",
				"COZY BEAR",
				"The Dukes",
				"Minidionis",
				"UAC-0029",
				"SeaDuke"
			],
			"source_name": "MISPGALAXY:APT29",
			"tools": [
				"SNOWYAMBER",
				"HALFRIG",
				"QUARTERRIG"
			],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "70872c3a-e788-4b55-a7d6-b2df52001ad0",
			"created_at": "2023-01-06T13:46:39.18401Z",
			"updated_at": "2026-04-10T02:00:03.239111Z",
			"deleted_at": null,
			"main_name": "UNC2452",
			"aliases": [
				"DarkHalo",
				"StellarParticle",
				"NOBELIUM",
				"Solar Phoenix",
				"Midnight Blizzard"
			],
			"source_name": "MISPGALAXY:UNC2452",
			"tools": [
				"SNOWYAMBER",
				"HALFRIG",
				"QUARTERRIG"
			],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "20d3a08a-3b97-4b2f-90b8-92a89089a57a",
			"created_at": "2022-10-25T15:50:23.548494Z",
			"updated_at": "2026-04-10T02:00:05.292748Z",
			"deleted_at": null,
			"main_name": "APT29",
			"aliases": [
				"APT29",
				"IRON RITUAL",
				"IRON HEMLOCK",
				"NobleBaron",
				"Dark Halo",
				"NOBELIUM",
				"UNC2452",
				"YTTRIUM",
				"The Dukes",
				"Cozy Bear",
				"CozyDuke",
				"SolarStorm",
				"Blue Kitsune",
				"UNC3524",
				"Midnight Blizzard"
			],
			"source_name": "MITRE:APT29",
			"tools": [
				"PinchDuke",
				"ROADTools",
				"WellMail",
				"CozyCar",
				"Mimikatz",
				"Tasklist",
				"OnionDuke",
				"FatDuke",
				"POSHSPY",
				"EnvyScout",
				"SoreFang",
				"GeminiDuke",
				"reGeorg",
				"GoldMax",
				"FoggyWeb",
				"SDelete",
				"PolyglotDuke",
				"AADInternals",
				"MiniDuke",
				"SeaDuke",
				"Sibot",
				"RegDuke",
				"CloudDuke",
				"GoldFinder",
				"AdFind",
				"PsExec",
				"NativeZone",
				"Systeminfo",
				"ipconfig",
				"Impacket",
				"Cobalt Strike",
				"PowerDuke",
				"QUIETEXIT",
				"HAMMERTOSS",
				"BoomBox",
				"CosmicDuke",
				"WellMess",
				"VaporRage",
				"LiteDuke"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "f27790ff-4ee0-40a5-9c84-2b523a9d3270",
			"created_at": "2022-10-25T16:07:23.341684Z",
			"updated_at": "2026-04-10T02:00:04.549917Z",
			"deleted_at": null,
			"main_name": "APT 29",
			"aliases": [
				"APT 29",
				"ATK 7",
				"Blue Dev 5",
				"BlueBravo",
				"Cloaked Ursa",
				"CloudLook",
				"Cozy Bear",
				"Dark Halo",
				"Earth Koshchei",
				"G0016",
				"Grizzly Steppe",
				"Group 100",
				"ITG11",
				"Iron Hemlock",
				"Iron Ritual",
				"Midnight Blizzard",
				"Minidionis",
				"Nobelium",
				"NobleBaron",
				"Operation Ghost",
				"Operation Office monkeys",
				"Operation StellarParticle",
				"SilverFish",
				"Solar Phoenix",
				"SolarStorm",
				"StellarParticle",
				"TEMP.Monkeys",
				"The Dukes",
				"UNC2452",
				"UNC3524",
				"Yttrium"
			],
			"source_name": "ETDA:APT 29",
			"tools": [
				"7-Zip",
				"ATI-Agent",
				"AdFind",
				"Agentemis",
				"AtNow",
				"BEATDROP",
				"BotgenStudios",
				"CEELOADER",
				"Cloud Duke",
				"CloudDuke",
				"CloudLook",
				"Cobalt Strike",
				"CobaltStrike",
				"CosmicDuke",
				"Cozer",
				"CozyBear",
				"CozyCar",
				"CozyDuke",
				"Danfuan",
				"EnvyScout",
				"EuroAPT",
				"FatDuke",
				"FoggyWeb",
				"GeminiDuke",
				"Geppei",
				"GoldFinder",
				"GoldMax",
				"GraphDrop",
				"GraphicalNeutrino",
				"GraphicalProton",
				"HAMMERTOSS",
				"HammerDuke",
				"LOLBAS",
				"LOLBins",
				"LiteDuke",
				"Living off the Land",
				"MagicWeb",
				"Mimikatz",
				"MiniDionis",
				"MiniDuke",
				"NemesisGemina",
				"NetDuke",
				"OnionDuke",
				"POSHSPY",
				"PinchDuke",
				"PolyglotDuke",
				"PowerDuke",
				"QUIETEXIT",
				"ROOTSAW",
				"RegDuke",
				"Rubeus",
				"SNOWYAMBER",
				"SPICYBEAT",
				"SUNSHUTTLE",
				"SeaDaddy",
				"SeaDask",
				"SeaDesk",
				"SeaDuke",
				"Sharp-SMBExec",
				"SharpView",
				"Sibot",
				"Solorigate",
				"SoreFang",
				"TinyBaron",
				"WINELOADER",
				"WellMail",
				"WellMess",
				"cobeacon",
				"elf.wellmess",
				"reGeorg",
				"tDiscoverer"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434200,
	"ts_updated_at": 1775826703,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/82647c7d13cc4bf61f74a35426bc180742fa9272.pdf",
		"text": "https://archive.orkl.eu/82647c7d13cc4bf61f74a35426bc180742fa9272.txt",
		"img": "https://archive.orkl.eu/82647c7d13cc4bf61f74a35426bc180742fa9272.jpg"
	}
}