Pangram verdict · v3.3
We believe that this document is primarily AI-generated with some human-written content
AI likelihood · overall
AIArticle text · 1,568 words · 6 segments analyzed
March 18, 2026 · 13 minutes read
A friend of mine once told me:
If you ever spot an IIS blue screen, don’t stop there; there must be something.
Yep, he was right. That IIS splash page is not a dead end. Behind that blue window sits one of the most consistently misconfigured web servers on the www, and it’s begging you to look deeper.
So let me walk you through how I approach IIS targets during bug bounty:
table of contents
psst, psst, IIS servers, where are you? shodan google dorking active tech fingerprinting ok, I found an IIS server. now what? internal IP disclosure pwn time nuclei templates: automate the boring stuff the HTTPAPI 2.0 dead end that isn’t IIS tilde enumeration: the gift that keeps giving using LLMs github dorks to resolve shortnames using BigQuery to resolve shortnames bruteforcing the rest with crunch fuzzing: the IIS-specific wordlist matters web.config: the keys to the kingdom path traversal to web.config bin directory DLL exposure via cookieless sessions reverse proxy path confusion authentication bypass via NTFS hacks file upload tricks bypassing WAFs via HPP
psst, psst, IIS servers, where are you?
Here are some techniques I use to find IIS servers.
shodan
Before you even touch a target, go see what Shodan already knows:
ssl:"target.com" http.title:"IIS" ssl.cert.subject.CN:"target.com" http.title:"IIS" org:"target" http.title:"IIS"
These sample queries will list IIS boxes tied to the target’s org or SSL certificates. You’ll sometimes find staging servers, forgotten admin panels, and internal tools that nobody realized were internet-facing.
Feel free to replace or combine shodan with other platforms like fofa, censys, netlas, odin, etc. They all index different slices of the internet.
🍕
google dorking
Google can find IIS servers for you before you even fire up a scanner. These dorks are all about locating IIS targets within a scope: site:target.com intitle:"IIS Windows Server" site:target.com inurl:aspnet_client site:target.com ext:aspx | ext:ashx | ext:asmx site:target.com intext:"Microsoft-IIS" | intext:"X-Powered-By: ASP.NET" site:target.com inurl:_vti_bin site:target.com intitle:"Microsoft Internet Information Services"
The aspnet_client folder and _vti_bin (FrontPage extensions) are dead giveaways for IIS; if Google has indexed them, you’ve got a target. The ext:aspx dork catches any indexed ASP.NET pages, which means IIS is underneath.
Also, expand your scope with stacked wildcards to catch nested subdomains that basic enumeration misses: site:*.target.com intitle:"IIS" site:*.*.target.com intitle:"IIS"
That second one has surfaced dev/staging boxes for me more than once.
active tech fingerprinting
The easiest way to know you’re staring at IIS is the response headers. Hit it with a raw request:
nc -v target.com 80
Or if it’s TLS:
openssl s_client -connect target.com:443
What you’re looking for something like this in the response headers:
Server: Microsoft-IIS/10.0 X-Powered-By: ASP.NET
But probably you want to do this at scale. Then just keep calm and use httpx (or nuclei):
httpx -l targets.txt -td | grep IIS | tee iis-targets.txt
ok, I found an IIS server. now what?
First off, let’s confirm what we’re dealing with and grab as much information as the server is willing to give away for free.
internal IP disclosure
Here’s a freebie most people miss.
Send an HTTP/1.0 request to certain IIS setups (especially Exchange or OWA fronts) and the server will sometimes hand you an internal IP in the Location header:
curl -v --http1.0 http://example.com
You might get back something like:
HTTP/1.1 302 Moved Temporarily Location: https://192.168.5.237/owa/ Server: Microsoft-IIS/10.0 X-FEServer: NHEXCHANGE2016
That internal IP and that X-FEServer header just told you the internal hostname of the Exchange server. File that away. It’s information disclosure that we could leverage in the following steps.
pwn time
Enough recon by now, let’s get to the juicy parts.
nuclei templates: automate the boring stuff
Once you’ve got your list of IIS targets, blast them with nuclei using relevant tags:
nuclei -l iis-targets.txt \ -tags microsoft,windows,asp,aspx,iis,azure,config,exposure -silent
I like to fire this in the background while I’m doing manual recon.
the HTTPAPI 2.0 dead end that isn’t
You’ll hit a lot of IIS boxes that respond with a generic HTTPAPI 2.0 404 error. Most people see this and think “nothing here.” Wrong.
What this actually means is the server didn’t receive the right domain name in the Host header. The IIS instance is there, it’s running something, but it’s bound to a specific virtual host. You need to figure out which one.
Two approaches:
check the SSL certificate. The subject or SAN field often contains the hostname you need. Just hit it in a browser and inspect the cert. if the cert doesn’t help, you brute-force virtual hosts. Tools like ffuf with a Host header wordlist work well here:
ffuf -u https://TARGET_IP/ -H "Host: FUZZ.target.com" -w vhosts.txt -fs 0
When you land on the right hostname, the server suddenly wakes up and serves you a real application instead of that useless 404.
IIS tilde enumeration: the gift that keeps giving
This is, one of the most underrated techniques. IIS has a legacy behavior inherited from the old DOS 8.3 filename convention. By sending specially crafted requests, you can enumerate the short names of files and directories on the server even if directory listing is disabled.
The tool you want is shortscan:
shortscan https://target.com/ -F -p 1
Note -F -p 1 parameters tell shortscan to fuzz the directories (full urls) and enumerate the shortnames (-p stands for patience).
Another tool you can use is burp’s IIS Tilde Enumeration Scanner.
This will spit out shortname fragments like:
File: WEB~1.CON File: GLOBAL~1.ASA File: SITEBA~1.ZIP Dir: ADMIN~1
Now here’s the thing: WEB~1.CON is obviously web.config. But what’s SITEBA~1.ZIP? Is it sitebackup.zip? sitebase.zip? sitebatch.zip? If we can guess the full name, we can try to download it.
Let’s explore some options for wordlist generation:
using LLMs
Something like:
Return only a list of words, separated by newlines, and nothing else. Ensure that the words contain only alphanumeric characters. Make a list of guesses, for what the rest of the word could be from this snippet. Ensure that the snippet is a substring of your guess. Make the list as extensive as possible. Snippet: {shortname}
github dorks to resolve shortnames
GitHub’s code search is basically a free filename database. Millions of repos means millions of real-world filenames you can pattern-match against your shortname fragments. Way more effective than guessing blindly.
The idea: take the first 6 characters from your shortname (everything before ~1) and search GitHub for filenames that start with those characters and end with the right extension.
Using GitHub’s code search UI directly:
# In GitHub's search bar, select "Code" and use path: filters path:/.ds_st path:/global*.asa path:/connec*.config
To pseudo-automate this, check out GSNW (GitHub Short Name Wordlist).
You feed it your shortname fragments and it scrapes GitHub code search for matching filenames:
python gsnw.py "siteba" output.txt
There’s also GitHub-IIS-Shortname-Generator which does the same thing and outputs a clean wordlist:
python scanner.py WEBDEV
Found matches: -------------------------------------------------- - WebDev.md - WebDeveloper.java - webdev.txt - webdevicons.lua -------------------------------------------------- Total unique matches: 86
Another cool option is shortnameguesser, which takes shortname scanner output and generates targeted wordlists by querying multiple sources to resolve the fragments.
using BigQuery to resolve shortnames
This is where it gets interesting. This technique is inspired by Assetnote’s research on using BigQuery to find hidden files on IIS. The idea is simple: use Google BigQuery’s public GitHub dataset to search the entire GitHub codebase for filenames that match your shortname pattern.
If your shortname scan returned SITEBA~1.ZIP, you run this in BigQuery:
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
You’ll get back real filenames from real projects: sitebackup.zip, sitebase.zip, and so on. Now you have a focused wordlist instead of blindly guessing.
bruteforcing the rest with crunch
When LLMs, GitHub, and BigQuery all come up empty, sometimes you just need to go dumb and brute-force the remaining characters. crunch generates wordlists of every possible combination for a given character length:
crunch 4 6 abcdefghijklmnopqrstuvwxyz -o wordlist.txt
This generates every lowercase alphabetic string from 4 to 6 characters long. Since 8.3 shortnames show you the first 6 characters, you typically only need to guess the remaining portion.
Say shortscan gave you DESKTO~1.ZIP. You know the filename starts with deskto and ends with .zip. Now you need to figure out what comes after deskto. The file could be desktop.zip, desktopbackup.zip, desktop-files.zip, etc.
Use ffuf with pattern-based fuzzing to cover the variations:
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
Note the different separators: hyphen, underscore, URL-encoded space, and no separator at all. Developers are inconsistent with naming conventions, so you want to cover all patterns. The %20 variant catches the surprisingly common case where someone named their file with a space in it — Windows doesn’t care, and IIS will serve it just fine.
This is the brute-force fallback when the smart approaches fail, and honestly, it works more often than you’d expect.
fuzzing: the IIS-specific wordlist matters
Generic wordlists are fine for generic servers. IIS is not generic. You need to fuzz for things that only exist in the IIS/.NET ecosystem.
These are high-value targets to fuzz for:
/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
For instance, trace.axd is the ASP.NET trace viewer. If it’s enabled, you get full request/response logs including headers, cookies, and sometimes credentials. elmah.axd is the error log viewer; same deal.