×

一次授权范围内的内网渗透测试,全程没有使用任何 CVE、没有打任何软件漏洞,纯粹靠配置缺陷叠加,最终拿到了完整的图形化管理员桌面和后台账号明文密码。把这条攻击链复盘出来,是想说明一个被反复提起却始终没被认真对待的事实——在内网安全里,配置缺陷比软件漏洞更危险。

全文涉及的 IP、账号、密码、哈希、厂商名称均已脱敏,测试数据全程本地处理、未上传公网。文末附按优先级排序的整改建议清单。

一、起点:一台”看起来正常”的内网服务器

测试目标是 192.168.x.x,一台承载物业智慧社区安防平台、MySQL 数据库与 MQTT Broker 的 Windows 10 专业版服务器。先做主机发现和端口扫描,结果很”丰富”:

  • 135 / 139 / 445——SMB 与 RPC 远程管理端口,全部开放
  • 3306——MySQL,远程可连
  • 3389——RDP 远程桌面
  • 9999——Tomcat,承载业务 Web 后台
  • 1883 / 8883 / 8081 / 8083 / 18083——EMQX MQTT Broker 全套接口
  • 6379——Redis

这台机器同时是”业务服务器 + 数据库 + 物联网中间件 + 运维终端”,业务和数据库共置单机,本身就违反了最小暴露面原则。但真正的”地雷”还不在端口列表里,而在 Administrator 账户的密码字段。

二、第一跳:Administrator 空密码与 WMI 远程执行

Windows 默认有一条本地安全策略:”使用空白密码的本地账户只允许进行控制台登录”。这条策略的本意,是阻止空密码账户走网络认证。目标机上这条策略处于关闭状态(或从未配置过),于是 Administrator 账户的空密码可以通过 WMI 远程登录。

用 System.Management.ManagementScope 构造一个 DCOM 连接,认证级别设为 PacketPrivacy(每包加密加签名),用户名传 Administrator、密码留空,Connect() 直接返回成功:

$scope = New-Object System.Management.ManagementScope
$scope.Path = "\\192.168.x.x\root\cimv2"
$scope.Options.Username = "192.168.x.x\Administrator"
$scope.Options.Password = ""   # 空密码
$scope.Options.Authentication = [System.Management.AuthenticationLevel]::PacketPrivacy
$scope.Connect()

$class = New-Object System.Management.ManagementClass($scope,
    [System.Management.ManagementPath]"Win32_Process", $null)
$out = $class.InvokeMethod("Create", "net user BackdoorAcct P@ssword /add")
# ReturnValue = 0

这意味着 WMI 通道对攻击者完全开放,接下来调用 Win32_Process.Create 就能在目标机上启动任意进程。

有一个细节值得注意:WMI 走 NTLM challenge-response 认证,密码本身不被传输,所以”空密码”不会以明文形式出现在任何报文里。服务器侧只看到”某 IP 用 Administrator 登录成功”,网络抓包里看不到密码字段——这给了攻击者一个隐藏优势,也让基于流量特征的检测基本失效。

三、第二跳:UAC 远程限制为什么没挡住

拿到 WMI 通道后,第一反应是直接调用 Win32_Process.Create 执行 net user /add,结果被拒绝,返回 HRESULT 0x80070005(拒绝访问)。

这是 Windows 10 的 UAC 远程限制在起作用。本地 Administrator 账户通过网络登录时,Windows 会过滤掉它的管理员权限令牌,只给标准用户权限。这个过滤由注册表 LocalAccountTokenFilterPolicy 控制,默认为 0(启用过滤)。标准用户没有权限调用 Win32_Process.Create,所以被拒。

但在目标机上,显式构造的 ManagementScope DCOM 连接最终取得了完整管理令牌。这里需要如实说明:这一跳的具体机制,本文记录的是现象而非机制定论。常见的解释有两种——一是 FilterAdministratorToken 被设为 0,内置 Administrator 被豁免于令牌过滤;二是 WMI 提供者进程 wmiprvse.exe 本身以 SYSTEM 身份托管,调用路径绕过了针对客户端的令牌过滤检查。两种可能都与目标机的 UAC 相关注册表组合有关,需要结合现场配置进一步确认。

从防御角度,无论机制是哪一种,收紧下面三项配置都能显著提高利用门槛,也是核查的第一站:

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
  EnableLUA                    = 1
  LocalAccountTokenFilterPolicy = 0   (保持默认,启用远程令牌过滤)
  FilterAdministratorToken      = 1   (内置 Administrator 也纳入过滤)

需要提醒的是,把 FilterAdministratorToken 设为 0 是不少运维脚本为”方便远程管理”会做的优化,它在本案中恰恰是让空密码直接变成完整管理员权限的关键一环。这类”为了运维顺手”的注册表改动,应该纳入变更评审。

四、第三跳:以 LOCALSYSTEM 落成后门管理员

取得完整管理令牌后,三条命令一次跑完:

net user BackdoorAcct P@ssword /add               → ReturnValue: 0
net localgroup Administrators BackdoorAcct /add   → ReturnValue: 0
net user BackdoorAcct /active:yes                 → ReturnValue: 0

这里有个容易忽略的细节:Win32_Process.Create 启动的新进程是以 LOCALSYSTEM 权限运行的,比 Administrator 还高。这就是为什么 net user /add 能直接成功——WMI 提供者用 SYSTEM 身份启动了 net.exe,权限完整,没有任何降级。

验证也走 WMI:用新账户 BackdoorAcct 再连一次 WMI,连接成功;列出 Win32_UserAccount,确认 Disabled=False、Lockout=False;列出 Win32_Group,确认它已在 Administrators 组内;再调用一次 Win32_Process.Create 仍然成功,证明管理员权限完整生效。

同时发现 SMB 共享 ADMIN$、C$、D$、E$、IPC$ 全部可列。C$ 可访问意味着整盘读写,下一步的桌面取证直接走 SMB 完成。

五、第四跳:修复 RDP 配置,换取图形化登录

有了后门管理员账户,理论上可以直接 mstsc 连 3389。但实测报错 0x904 与扩展错误 0x7——协议协商阶段被服务端断开。

用 WMI 远程导出 RdpCoreTS 事件日志,看到关键事件 Event_ERROR_SendingX224CC(发送 X.224 连接确认时出错),断开原因 4409。根因是服务器 RDP 配置为 SecurityLayer=2(强制 TLS)且 NLA=1,但它的 TLS/CredSSP 层握手存在问题——自签证书或 CredSSP 配置异常都会导致这个现象。

修复同样走 WMI,但用的是另一组类。Win32_TSGeneralSetting 自带 SetSecurityLayer 与 SetUserAuthenticationRequired 方法,与开启 RDP 用的 Win32_TerminalServiceSetting.SetAllowTSConnections 同属一个 namespace:

SetSecurityLayer(0)                  # 0 = 纯 RDP 安全层,绕开 TLS
SetUserAuthenticationRequired(0)      # 关闭 NLA
# 重启 TermService 与 UmRdpService

这里有一个关键区分,也是理解整条链的钥匙:Win32_Process.Create 是进程创建,受 UAC 远程限制约束;而 SetSecurityLayer 这类是 WMI 提供者方法,不经过进程启动路径,不受 UAC 远程限制影响。所以最初开启 RDP(SetAllowTSConnections(1))能直接成功,而创建账户时却被拒——两类方法的权限模型不同,攻击者只需要找到那条不受限的路径。

六、攻击链全景

1网络可达135 / 445 / 3389 / 9999 / 1883 / 6379 全暴露,业务与数据库共置单机2Administrator 空密码 → WMI 登录PacketPrivacy DCOM 连接,NTLM 不回传密码,抓包无可见字段3取得完整管理令牌UAC 远程限制未生效,标准用户过滤被绕过(机制需结合注册表确认)4Win32_Process.Create 创建后门管理员提供者以 LOCALSYSTEM 执行 net.exe,权限完整无降级5SetSecurityLayer(0) + 关闭 NLA → mstsc 图形化控守提供者方法不受 UAC 远程限制约束,全程零 CVE、零 0day
攻击链五步全景:从网络可达到图形化控守,每一步都是合法管理协议的正常调用

严格来说,这是一次”单点突破后的完整控守”,而非在多台主机之间跳转的传统横向移动;文中沿用”攻击链”这一表述,指的是从网络边缘到完全控守的全过程。

七、桌面文件取证:明文密码还原

拿到 RDP 与 SMB 的完整访问后,下一步是看服务器桌面有什么。Administrator 桌面下放着一个 .lnk 快捷方式,指向 E 盘一个运维 txt 文件。直接按 MS-SHLLINK 格式二进制解析(目标路径以 ASCII 存储),拿到真实路径,再走 SMB 的 E$ 共享下载。

这个 txt 是金矿,里面明文写着:

  • 业务后台登录账号 A(手机号格式)及其密码
  • 业务后台登录账号 B(手机号格式)及其密码
  • 服务器 IP、子网掩码、网关
  • 运维注意事项三条:不可安装其他 SQL 数据库;不可安装杀毒软件;黑色弹窗不要手动关闭

此前 dump 数据库时已经拿到 4 个后台账号的密码哈希(SHA-256,64 位 hex,无 salt 字段),其中两个账号的明文现在直接从桌面 txt 里拿到了。对照验证:

SHA-256(密码A) = 6fa40a...   → 匹配账号 A 的库内哈希
SHA-256(密码B) = 809622...   → 匹配账号 B 的库内哈希

双杀命中。哈希算法 100% 确认:裸 SHA-256,无盐,无迭代。这意味着拿到数据库的攻击者可以用彩虹表或 GPU 离线爆破,在数小时内还原所有账号的明文密码。对照等保 2.0 对鉴别信息存储保密性的要求,以及 PCI-DSS 8.2.1 关于口令必须不可逆加密并加盐的规定,这种存储方式均不达标。

八、登录失败日志:开发组做对的事

测试过程中我想从登录失败日志里反查明文密码——很多系统在错误登录时会把明文密码记进日志表做防爆破统计。结果扫了数据库所有日志存储位置,结论是开发组在这件事上做对了:

  • 登录失败日志表(84626 条):detail 字段只写”登录时用户名或密码错误”,不存明文
  • 业务操作日志表(17471 条):request_body 字段会完整存 JSON,但 28 个 distinct URL 全是住户、门禁、设备管理类,登录和改密接口没被这张表捕获
  • 后端主动排除:login、modifyPwd、resetPwd 这几类接口不进业务日志

这不是所有厂商都能做到的。写报告时要把这条作为正面发现记下来——整改时不要”一刀切”改成所有操作都记日志,那样反而会把明文密码又写回日志表。安全设计的目标不是记更多,而是记对的东西。

九、物联网层面的暴露:共享凭据

这台服务器还跑着 EMQX MQTT Broker,承载 1262 台物联网设备(门禁、对讲、传感器)的事件上报。数据库里查到两组凭据:

  • 服务端凭据:限制 127.0.0.1 访问,设计相对合理
  • 设备端凭据:1262 台设备共享同一组用户名密码,且 broker 的 1883 / 8883 端口对外可达

风险点在于:拿到这组共享凭据后,攻击者可以冒充任意设备上报伪造事件,也可以冒充服务端下发开门指令——如果协议层没有做双向认证的话。”全设备共享凭据”是物联网平台最常见的架构性缺陷,整改方向是一机一密加设备身份证书。

另外补一句本次未纳入链条但同样危险的暴露:6379 端口的 Redis 处于开放状态。无认证的 Redis 配合写文件或主从复制,可以直接升级为远程命令执行,建议与 MQTT 凭据问题一并整改。

十、攻击链会留下哪些痕迹

这条攻击链虽然零漏洞利用,但痕迹多且持久。取证人员查以下几个位置就能完整还原:

  • 安全日志 4720:账户创建(铁证,时间戳精确到秒)
  • 安全日志 4732:账户加入管理员组
  • 安全日志 4624:每次 WMI 连接的网络登录成功记录,含源 IP
  • 系统日志 4688:进程创建。如果启用了命令行审核,net user BackdoorAcct P@ssword /add 这条命令的完整明文——包括密码——会被记进日志
  • WMI-Activity 日志:WMI 方法调用记录,可证明使用了 Win32_Process.Create
  • 注册表:HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp 下 SecurityLayer、UserAuthenticationRequired 被改过
  • RdpCoreTS 日志:RDP 配置变更与连接尝试
  • Tomcat access log:所有 HTTP 请求,含 User-Agent,脚本工具的 UA 与浏览器差异明显

有意思的是:WMI 走 NTLM 认证,密码本身不被记录进日志;但 4688 的命令行审核会把后门账户密码明文记下来——这恰恰是攻击者最不希望被记录的信息。取证人员拿到这条命令行,就能直接用密码登录验证后门是否还在。

十一、整改建议(按优先级)

  1. Administrator 必须设强密码。这是整条链的起点,没有空密码就没有后续。
  2. 启用”使用空白密码的本地账户只允许进行控制台登录”策略。即使存在空密码账户,也无法走网络认证。
  3. 关闭内网不必要的 SMB / RPC / WMI 端口暴露。通过 Windows 防火墙限定源 IP,例如仅放通运维管理段。
  4. 复核 UAC 相关三项注册表。EnableLUA=1、LocalAccountTokenFilterPolicy=0、FilterAdministratorToken=1,堵住令牌过滤被绕过的灰色地带。
  5. 密码存储换算法。改用 bcrypt / Argon2 / PBKDF2-SHA256,至少 10000 次迭代加独立盐,并对存量哈希制定轮换计划。
  6. 全站上 HTTPS。登录接口明文传输,等于把密码送给中间人。
  7. 桌面与共享目录禁止存放明文凭据。运维文档里的账号密码进密码管理器,不要躺 txt。
  8. 安装 EDR / AV。“不可安装杀毒软件”这类运维要求必须改,没有终端防护等于裸奔。
  9. 启用 4688 命令行审核。这条不是整改而是取证准备,让未来的攻击都被完整记录。

结语

这条攻击链最让人警醒的地方在于:它不需要任何 CVE、不需要任何 0day、不需要任何漏洞利用工具。所有步骤都是合法管理协议的正常调用,叠加在一系列配置缺陷之上——空密码、端口暴露、UAC 灰色地带、桌面明文存储、裸 SHA-256 哈希、明文传输。

整改时也别只盯着”打补丁”。补丁是给漏洞打的,配置缺陷没有补丁;配置缺陷的”补丁”是基线核查、定期审计与责任到人。等保 2.0 里”安全配置基线”那一节,不是用来应付检查的,是用来堵这类攻击链的。

最后再强调一次:开发组在登录日志设计上的两个正面实践——登录失败不存密码、改密操作不落业务日志——值得保留。整改时不要为了”日志更完整”把它们改坏。


本文基于一次授权范围内的内网渗透测试整理,所有真实 IP、账号、密码、哈希及厂商名称均已脱敏。测试全程本地处理,未上传公网。本文仅用于防御性安全意识教育与授权场景参考,请勿将其中方法用于未经授权的系统。

作者

网安手记编辑部

open_red@yeah.net

相关文章