PowerSploit Privesc 模块 Get-ApplicationHost:从 IIS applicationHost.config 解密恢复应用池与虚拟目录密码
【免费下载链接】PowerSploitPowerSploit - A PowerShell Post-Exploitation Framework项目地址: https://gitcode.com/gh_mirrors/po/PowerSploit
导读
Get-ApplicationHost是 PowerSploit 项目 Privesc 模块 中提供的一个无参数 PowerShell 函数,用于从目标系统的 IISapplicationHost.config配置文件中恢复(解密)应用程序池(Application Pool)与虚拟目录(Virtual Directory)中存储的加密凭据。它面向 Windows 上 IIS 6 及以上版本,利用 IIS 自带的appcmd.exe命令行工具读取并解密配置项,并把结果输出为可直接流入管道的结构化数据,便于后续格式化与审计。读完本文,你将掌握该函数的调用方式、输出结构、底层实现原理(包括 DataTable 构建与 appcmd.exe 调用链),以及它在提权/凭据收集场景中的定位与适用边界。
函数概览
Get-ApplicationHost的完整实现位于 Privesc/PowerUp.ps1,其注释文档(comment-based help)与独立文档 docs/Privesc/Get-ApplicationHost.md 完全对应,是 PowerUp 中"杂项检查(Miscellaneous Checks)"的一员。核心元信息如下:
| 项目 | 内容 |
|---|---|
| 功能 | 从系统上的applicationHost.config恢复加密的应用池与虚拟目录密码 |
| 作者 | Scott Sutherland(2014,NetSPI) |
| 版本 | Get-ApplicationHost v1.0 |
| 许可证 | BSD 3-Clause |
| 依赖 | 无(Required Dependencies: None) |
| 兼容性 | IIS 6 及以上(Should work on IIS 6 and Above) |
| 输出类型 | System.Data.DataTable/System.Boolean |
| 参数 | 无(Param()为空,[CmdletBinding()]) |
函数通过 Privesc/Privesc.psd1 的FunctionsToExport导出(同时也在顶层 PowerSploit.psd1 的导出清单中),模块加载时由 Privesc/Privesc.psm1 以点源(dot-source)方式引入PowerUp.ps1等脚本文件。
使用场景与威胁模型
在 Windows 服务器提权与横向移动评估中,IIS 站点管理员常常在applicationHost.config中为应用池进程身份(process model identity)和虚拟目录访问配置独立的域账号/本地账号。这些凭据会被 IIS 以机器级密钥加密保存,普通文本查看applicationHost.config只能看到密文。Get-ApplicationHost的价值在于:它借用 IIS 官方工具appcmd.exe的"解密后输出"能力,把密文还原为明文,从而让审计人员发现隐藏的高权限账号。
该函数与 PowerUp 中的姊妹函数Get-WebConfig(检查web.config中的加密连接字符串)互补,两者常配合用于完整收集 IIS 凭据面。
语法与参数
函数无参数,语法极简:
Get-ApplicationHost从源码看,Param()为空块,仅声明了[CmdletBinding()](见 Privesc/PowerUp.ps1),因此函数本身不接受位置参数或命名参数;同时通过SuppressMessageAttribute压制了PSShouldProcess与PSAvoidUsingInvokeExpression两条 PSScriptAnalyzer 规则警告(因为实现中使用了Invoke-Expression来构造 appcmd 命令,见 Privesc/PowerUp.ps1)。
环境前提
- 目标系统必须存在
%SystemRoot%\System32\inetsrv\appcmd.exe(即安装了 IIS 管理工具)。源码在函数入口处用Test-Path检查该文件是否存在(见 Privesc/PowerUp.ps1),不存在时输出Write-Verbose 'Appcmd.exe does not exist in the default location.'并返回$False。 - 函数内部将
$ErrorActionPreference临时设为SilentlyContinue并在结尾恢复(见 Privesc/PowerUp.ps1),因此即使某个池/目录读取失败也不会中断整体执行。
输出结构详解
函数将所有结果汇总到一张System.Data.DataTable中,表结构在源码中通过$DataTable.Columns.Add(...)显式创建(见 Privesc/PowerUp.ps1),共 5 列:
| 列名 | 含义 | 应用池记录取值 | 虚拟目录记录取值 |
|---|---|---|---|
user | 凭据用户名 | processmodel.username | userName |
pass | 明文密码 | processmodel.password | password |
type | 记录类型 | Application Pool | Virtual Directory |
vdir | 虚拟目录名 | NA | vdir.name |
apppool | 应用池名 | 池名称 | NA |
结果在返回前会经过Sort-Object type,user,pass,vdir,apppool排序,并用Select-Object ... -Unique去重(见 Privesc/PowerUp.ps1)。
- 若解析到至少一条凭据:输出 DataTable 记录(管道友好);
- 若未发现任何密码:输出
Write-Verbose 'No application pool or virtual directory passwords were found.'并返回布尔值$False(见 Privesc/PowerUp.ps1); - 若
appcmd.exe不存在:返回$False。这也是文档中OUTPUTS同时列出System.Data.DataTable与System.Boolean两种类型的原因。
使用示例
示例 1:默认列表视图输出
直接运行即可返回所有应用池与虚拟目录凭据:
Get-ApplicationHost文档给出的典型输出如下(字段以冒号分隔的列表形式呈现):
user : PoolUser1 pass : PoolParty1! type : Application Pool vdir : NA apppool : ApplicationPool1 user : PoolUser2 pass : PoolParty2! type : Application Pool vdir : NA apppool : ApplicationPool2 user : VdirUser1 pass : VdirPassword1! type : Virtual Directory vdir : site1/vdir1/ apppool : NA user : VdirUser2 pass : VdirPassword2! type : Virtual Directory vdir : site2/ apppool : NA示例 2:管道 + Format-Table 美化
由于输出支持管道,可将其导入Format-Table生成对齐表格:
Get-ApplicationHost | Format-Table -Autosize输出形如:
user pass type vdir apppool ---- ---- ---- ---- ------- PoolUser1 PoolParty1! Application Pool NA ApplicationPool1 PoolUser2 PoolParty2! Application Pool NA ApplicationPool2 VdirUser1 VdirPassword1! Virtual Directory site1/vdir1/ NA VdirUser2 VdirPassword2! Virtual Directory site2/ NA示例 3:与 Web 配置检查组合使用
Get-ApplicationHost专注于applicationHost.config中的应用池/虚拟目录凭据,而Get-WebConfig负责扫描各站点的web.config连接字符串,两者结果均为表格型数据,可一并导出用于审计报告:
$AppHost = Get-ApplicationHost $WebConfigs = Get-WebConfig $AppHost + $WebConfigs | Format-Table -Autosize底层实现原理
第一步:定位并调用 appcmd.exe
函数首先检查%SystemRoot%\System32\inetsrv\appcmd.exe是否存在。appcmd.exe是 IIS 7+ 自带的命令行管理工具,支持以/text:参数直接输出指定配置项的"解密后"值——这正是本函数能够恢复明文密码的关键能力来源。
第二步:枚举应用池并提取凭据
Invoke-Expression "$Env:SystemRoot\System32\inetsrv\appcmd.exe list apppools /text:name" | ForEach-Object { $PoolName = $_ $PoolUserCmd = "$Env:SystemRoot\System32\inetsrv\appcmd.exe list apppool " + "`"$PoolName`" /text:processmodel.username" $PoolUser = Invoke-Expression $PoolUserCmd $PoolPasswordCmd = "$Env:SystemRoot\System32\inetsrv\appcmd.exe list apppool " + "`"$PoolName`" /text:processmodel.password" $PoolPassword = Invoke-Expression $PoolPasswordCmd ... }实现细节(见 Privesc/PowerUp.ps1):
- 用
list apppools /text:name拿到所有应用池名称; - 对每个池执行
list apppool "<name>" /text:processmodel.username与/text:processmodel.password,读取进程模型(process model)中配置的身份账号与密码; - 过滤条件:
$PoolPassword -ne ""且$PoolPassword -isnot [system.array]——后者用于排除"该属性配置了多条值"的异常情形,确保只把单值密码加入结果; - 写入 DataTable:
Rows.Add($PoolUser, $PoolPassword, 'Application Pool', 'NA', $PoolName)。
第三步:枚举虚拟目录并提取凭据
Invoke-Expression "$Env:SystemRoot\System32\inetsrv\appcmd.exe list vdir /text:vdir.name" | ForEach-Object { $VdirName = $_ $VdirUserCmd = "$Env:SystemRoot\System32\inetsrv\appcmd.exe list vdir " + "`"$VdirName`" /text:userName" $VdirUser = Invoke-Expression $VdirUserCmd $VdirPasswordCmd = "$Env:SystemRoot\System32\inetsrv\appcmd.exe list vdir " + "`"$VdirName`" /text:password" $VdirPassword = Invoke-Expression $VdirPasswordCmd ... }实现细节(见 Privesc/PowerUp.ps1):
- 用
list vdir /text:vdir.name枚举全部虚拟目录; - 对每个目录执行
list vdir "<name>" /text:userName与/text:password; - 同样的空值与数组过滤后,写入 DataTable:
Rows.Add($VdirUser, $VdirPassword, 'Virtual Directory', $VdirName, 'NA')。
第四步:结果汇总与返回
DataTable 记录数大于 0 时,先按type,user,pass,vdir,apppool排序再-Unique去重后输出;否则返回$False。
测试验证
仓库在 Tests/Privesc.tests.ps1 中为该函数提供了 Pester 测试用例:
Describe 'Get-ApplicationHost' { It 'Should not throw.' { {Get-ApplicationHost} | Should Not Throw } }该用例验证函数在任意环境(即使appcmd.exe不存在)下调用都不会抛出异常——得益于$ErrorActionPreference = 'SilentlyContinue'与Test-Path前置检查,函数总能以优雅方式返回(有数据返回 DataTable,无环境/无数据返回$False)。
注意事项与适用边界
- 权限要求:读取并解密
applicationHost.config中的凭据需要相应权限(通常需管理员/高权限上下文)。函数本身不包含提权逻辑,它属于"凭据收集"而非"漏洞利用"工具。 - 适用版本:文档注释明确说明 "Should work on IIS 6 and Above",但
appcmd.exe自 IIS 7 起才成为标准组件,因此在较老的 IIS 6 环境中可能因缺少该工具而返回$False(可加-Verbose查看具体原因)。 - 依赖系统工具:函数强依赖
appcmd.exe的存在与行为,若 IIS 未安装或工具被加固移除,将无法工作。 - 脚本加载方式:在 PowerSploit 环境中,可通过导入模块使用:
Import-Module .\Privesc\Privesc.psd1(由 Privesc/Privesc.psm1 点源加载PowerUp.ps1);或直接点源脚本文件:. .\Privesc\PowerUp.ps1后调用。 - 输出语义:DataTable 的
-Unique去重基于排序后的全部五列,理论上会消除完全重复的记录;如只需用户/密码对,可自行Select-Object user,pass -Unique进一步收敛。
【免费下载链接】PowerSploitPowerSploit - A PowerShell Post-Exploitation Framework项目地址: https://gitcode.com/gh_mirrors/po/PowerSploit
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考