![79fb67caf8ecf51308c59dbc6ba63d86.png](https://i-blog.csdnimg.cn/blog_migrate/24cfb793abe0d32b0b64b96cfda1108e.png)
0x00 前言
在上一篇文章中,我介绍了如何在具备模拟(impersonation)特权的情况下,将权限提升至SYSTEM
。此外我们也以微软10年前对Service Tracing漏洞的修复措施为例,演示了如何修复这类漏洞。然而这种安全机制实际上可以被绕过,在本文中,我们将研究如何让有10年历史的漏洞焕发生机。
![79fb67caf8ecf51308c59dbc6ba63d86.png](https://i-blog.csdnimg.cn/blog_migrate/24cfb793abe0d32b0b64b96cfda1108e.png)
0x01 背景
大约10年之前,Cesar Cerrudo( @cesarcer )发现攻击者可以使用Windows的Service Tracing功能,通过命名管道来捕捉SYSTEM
令牌。一旦我们具备
SeImpersonatePrivilege
权限,就可以在该用户的安全上下文中执行任意代码。微软当时确认该问题属于漏洞范畴,分配的CVE ID为
CVE-2010-2554
。
这里我们以
RASMAN
服务对应的Service Tracing键值为例。操作过程非常简单,我们首先需要启动一个本地命名管道服务器,然后在注册表中将目标日志文件目录的路径设为该命名管道的路径。
![cccd96c2639d13a8b09c85349af1b66a.png](https://i-blog.csdnimg.cn/blog_migrate/1355f8bda983c54b594c6c3db2e0dc5a.png)
\\localhost\pipe\tracing
。随后,一旦
EnableFileTracing
值被设置为
1
,服务就会使用
\\localhost\pipe\tracing\RASMAN.LOG
作为路径来尝试打开日志文件。因此,如果我们创建名为
\\.\pipe\tracing\RASMAN.LOG
的命名管道,就可以收到连接请求,调用
ImpersonateNamedPipeClient
函数来模拟服务账户。由于
RASMAN
以
NT AUTHORITY\SYSTEM
权限运行,因此我们最终能够拿到
SYSTEM
模拟令牌。
注意:在不同版本的Windows系统上,将EnableFileTracing
设置为1
后系统可能不会立即打开日志文件。由于低权限用户可以通过服务控制管理器(SCM)来启动RASMAN
,因此为了稳定触发该事件,我们可以手动启动该服务。
![b6d8a43f149be1fa1e2b8f2bf703a0fc.png](https://i-blog.csdnimg.cn/blog_migrate/821568d831ed46b957be550417921045.png)
1346
错误,也就是“指定的模拟级别无 效, 或所提供的模拟级别无效”错误。此外我们还会看到错误代码
5
,也就是“访问被拒绝”错误,这是因为微软在Windows系统中部署了相应的防护机制。
我在前一篇文章中详细描述了这种安全更新机制。简而言之,系统现在会在
CreateFile
函数调用中指定
SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION
标志,而该函数负责获取目标日志文件的初始句柄。在这些标志的影响下,我们现在获取的令牌的模拟级别为
SecurityIdentification
(等级2/4)。然而为了完整模拟目标用户,我们必须获取的模拟级别为
SecurityImpersonation
(等级3/4)或者
SecurityDelegation
(等级4/4)。
备注:在上述命令提示符中,我们看到的打印信息为
Unknown error 0x80070542
,而不是实际的Win32错误。这是因为我在模拟用户时想获取错误代码对应的错误信息。由于模拟级别受限,因此我们无法查找代码与消息的对应关系。
那么这是否意味着我们将无功而返呢?我们获得的令牌的确用处不大,但我们可以继续阅读下文,寻找一线生机。
![79fb67caf8ecf51308c59dbc6ba63d86.png](https://i-blog.csdnimg.cn/blog_migrate/24cfb793abe0d32b0b64b96cfda1108e.png)
0x02 UNC路径
根据前文描述,如果我们将日志文件目录设为命名管道名称,就能拿到模拟令牌,但无法利用该令牌创建新进程。然而这里我其实隐藏了一个重要的细节:我们如何设置命名管道名称? 首先我们需要了解最终使用的日志文件路径的计算方式。这是非常简单的字符串拼接操作:\.LOG
,其中
读取自注册表(
FileDirectory
键值)。因此,如果我们为名为
Bar
的服务设置输出的目录为
C:\Temp
,那么该服务就会使用
C:\Temp\BAR.LOG
作为日志文件的路径。
在漏洞利用过程中,我们通过UNC路径来指定管道名称,而不是常规的目录。在Windows系统上我们有许多方法来设置路径,UNC路径是其中一种(这里我们就不展开讲)。为了成功利用漏洞,我们的确需要用到UNC(通用命名约定),但需要稍加改动。
UNC路径通常用来访问本地网络中的远程共享。比如,如果我们想访问
DUMMY
主机
FOO
卷上的
BAR
文件,那么可以使用UNC路径
\\DUMMY\FOO\BAR
。在这种情况下,客户端主机会连接目标服务器的TCP 445端口,使用SMB协议来交换数据。
然而我们也可以使用
\\DUMMY@4444\FOO\BAR
,通过任意端口(而不是默认的TCP 445端口)来访问远程共享(这里为
4444
端口)。尽管这种路径与默认路径差别很小,但带来的影响非常巨大。效果上最明显的区别在于,这种情况下系统不再使用SMB协议,客户端会使用HTTP协议的扩展版本,也就是WebDAV(Web Distributed Authoring and Versioning)。
在Windows系统上,WebDAV由
WebClient
服务负责处理。如果我们查看该服务的描述,可以找到如下信息:
(该服务)使基于Windows的程序可以创建、访问并修改基于Internet的文件。如果停止该服务,这些功能将不再可用。如果该服务被禁用,那么以来该服务的其他服务将无法启动。虽然WebDAV使用的是完全不同的协议,但有个因素始终不变:身份认证。因此,如果我们创建一个本地WebDAV服务器,然后使用该路径作为输出目录时会出现什么情况?
![79fb67caf8ecf51308c59dbc6ba63d86.png](https://i-blog.csdnimg.cn/blog_migrate/24cfb793abe0d32b0b64b96cfda1108e.png)
0x03 拿到模拟令牌
首先我们需要编辑注册表,修改FileDirectory
的值。这里我们不再使用命名管道路径,而是使用
\\127.0.0.1@4444\tracing
。
![2eddf6484591568d9202610cd8fd48cb.png](https://i-blog.csdnimg.cn/blog_migrate/2c654850351a175d2aeb5d342740397f.png)
netcat
打开socket,在本地TCP 4444端口上监听。启用服务跟踪功能后,我们可以收到如下信息:
![180bee08497ff5bb8414aabba800d30c.png](https://i-blog.csdnimg.cn/blog_migrate/b780062abbb93d92b830cecf8cddc3b5.png)
OPTIONS
请求。根据
User-Agent
头部字段,我们可知这是一个WebDAV请求,但目前我们得不到更多信息。基于这些现象,我们知道该服务可以使用WebDAV来通信,因此我们应该回复并发送身份认证请求。
为了完成该任务,我创建了一个简单的PowerShell脚本,使用
System.Net.Sockets.TcpListener
对象在任意端口上监听,然后向连接该socket的第一个客户端发送一个硬编码的HTTP响应。我们准备发送给客户端的HTTP响应数据如下:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: NTLM
如果大家非常熟悉Web应用渗透测试,那么应该经常会遇到带有
Basic
值的
WWW-Authenticate
头(比如Apache
htpasswd
),但不一定经常碰到带有
NTLM
的值。通过这个值,我们能够要求客户端使用3次NTLM认证方案来进行身份认证。这里顺便提一下,如果大家想了解关于NTLM的背景知识,可以参考
@HackAndDo
发表的关于
NTLM中继
的研究文章。
脚本运行后,我们能看到如下结果:
![fadcb2b2c2432d8a96fbbf5b4407c9b7.png](https://i-blog.csdnimg.cn/blog_migrate/3d15fa03e171ac20972f4e5d7bf5f4d9.png)
![9cc4daaee34ff2e683f40d70f2e1be17.png](https://i-blog.csdnimg.cn/blog_migrate/ae701023c9afc9694133fdfedfc9a47d.png)
NEGOTIATE
消息中
NegotiateFlags
值的计算方式。在官方文档中,我们可以找到关于
Identify
标志的一段话:
![be42cffc29a70c0d3c1844afa56ff735.png](https://i-blog.csdnimg.cn/blog_migrate/ea7ced8c604b180c1ef62536470378da.png)
SecurityIdentification
的令牌。也就是说,如果设置了该标志位,我们将无功而返,无法拿到合适的模拟令牌。
在Wireshark中我们可以检查该标志位的设置情况:
![fea433bf178df48d9912de1064f4a93f.png](https://i-blog.csdnimg.cn/blog_migrate/cd7237aed512588110ff2fb637bbbd35.png)
Identify
标志位并没有被设置!
这意味着我们可以绕过补丁,拿到模拟令牌,使用该令牌在
NT AUTHORITY\SYSTEM
上下文执行任意代码。接下来我们只需要完成NTLM认证过程即可,以便将原始的NTLM数据转换成可以使用的令牌。这里我就不展开分析,相关内容可以参考各种Potato漏洞利用工具的原理。
我开发了一个PoC,运行结果如下图所示:
![154ec52eece04c34e409e526ba74acc6.png](https://i-blog.csdnimg.cn/blog_migrate/4fdbb2acdc22b020beaf3d78e852cd47.png)
![79fb67caf8ecf51308c59dbc6ba63d86.png](https://i-blog.csdnimg.cn/blog_migrate/24cfb793abe0d32b0b64b96cfda1108e.png)
0x04 一些小细节
为了完整理解漏洞原理,我们还需要做一些工作,详细分析不再赘述,这里我想与大家分享一些小细节。 首先大家可能会注意到一点:服务正在请求的资源为/tracing
,而不是
/tracing/RASMAN.LOG
,那么为什么会出现这种情况?
由于我们将
\\127.0.0.1@4444\tracing
设置为目录路径,因此可能会认为目标服务会使用
\\127.0.0.1@4444\tracing\RASMAN.LOG
路径,并且会请求
/tracing/RASMAN.LOG
。如果我们分析
rtutils.dll
中的
TraceCreateClientFile
函数,可以看到在打开日志文件前,该函数会检查
TraceCreateClientFile
值中指定的目录是否存在。
如下图所示,如果
CreateDirectory
成功执行(即目标目录不存在,且被成功创建),那么该函数会立即返回。在这种情况下,日志文件永远不会被打开,我们需要禁用跟踪功能,重新启用服务。也就是说,如果想让
TraceCreateClientFile
成功完成,
CreateDirectory
必须返回失败值。
![cc6a0f9cf082cfb6e60eb14c4d067d09.png](https://i-blog.csdnimg.cn/blog_migrate/4e542a8cc4f79a41629ae0483a29ffd2.png)
CreateDirectory
实际上只是
NtCreateFile
函数的一个封装函数(在Windows上同样所有对象都是文件)。
CreateDirectory
函数使用起来非常方便,但有一个问题:该函数并不能设置自定义标志,比如用来限制令牌模拟级别的标志,这也解释了为什么我们能够通过这种技巧拿到可用的模拟令牌。
BOOL CreateDirectoryW(
LPCWSTR lpPathName,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
那么如果服务端通过强化版的
CreateFile
文件来请求
/tracing/RASMAN.LOG
时会出现什么情况?为了回答该问题,我编译了如下代码:
HANDLE hFile = CreateFile(
argv[1],
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, //
NULL);
if (hFile)
{
wprintf(L"CreateFile OK\n");
CloseHandle(hFile);
}
else
{
PrintLastErrorAsText(L"CreateFile");
}
然后我们可以不必等待
RASMAN
服务连接,而是以低权限用户身份,通过该测试应用来触发WebDAV访问行为。测试结果如下:
![80f51f83bbcc5f27b66205d269d26408.png](https://i-blog.csdnimg.cn/blog_migrate/ed11d3251dbf48ec383ac3489b9f9a50.png)
CreateFile
函数调用中设置了
SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION
标志,我们还是能够拿到带有
SecurityImpersonation
模拟级别的令牌!因此我们可以得出结论:
WebClient
服务同样存在缺陷。
![79fb67caf8ecf51308c59dbc6ba63d86.png](https://i-blog.csdnimg.cn/blog_migrate/24cfb793abe0d32b0b64b96cfda1108e.png)
0x05 总结
微软在早期部署的安全补丁可以阻止恶意服务器应用程序利用Service Tracing功能获取可用的模拟令牌,在本文中,我们介绍了如何轻松绕过这种安全机制。这里我还得感谢另一个小伙伴,他几年前写的 MS16-075 利用代码给了我不少启发。 后续我不一定发布利用工具,由于许多Service Tracing键值可以被触发,因此想开发出一款可用的工具还需要一些工作要处理。此外如果我们想利用这种方式,还需满足一个前提条件:目标系统上必须安装并启用WebClient
服务。尽管这是Workstation版系统上的默认设置,但并不适用于Server版系统。在Server系统上,我们需要通过附加功能来安装/启用WebDAV组件。
这里我们还可以继续研究,比如我们可以去分析为什么来自
WebClient
的请求并没有在调用
CreateFile
时考虑到
SECURITY_IDENTIFICATION
标志。在我看来这应该算是一个漏洞,但官方不一定也这么认为。
![79fb67caf8ecf51308c59dbc6ba63d86.png](https://i-blog.csdnimg.cn/blog_migrate/24cfb793abe0d32b0b64b96cfda1108e.png)
0x06 参考资料
CVE-2010-2554https://www.cvedetails.com/cve/CVE-2010-2554/
MS10-059 – Vulnerabilities in the Tracing Feature for Services Could Allow Elevation of Privilegehttps://docs.microsoft.com/en-us/security-updates/securitybulletins/2010/ms10-059
GitHub – Chimichurri exploithttps://github.com/Re4son/Chimichurri/
Hackndo – NTLM Relayhttps://en.hackndo.com/ntlm-relay/
MS16-075 exploit leveraging the WebClient servicehttps://github.com/NotGlop/SysExec
译文声明
译文仅供参考,具体内容表达以及含义原文为准。
![e5a4a41243b72a17913824c272c21000.png](https://i-blog.csdnimg.cn/blog_migrate/270788f34af882472f4cf06b65de0c58.png)
![09739d9906d310b5a19acafe58703a0a.gif](https://i-blog.csdnimg.cn/blog_migrate/fa7460b0ad3a5505861d30aeb0cc8501.gif)