原文地址:https://hausec.com/2019/08/12/offensive-lateral-movement/
所谓横向渗透,实际上就是通过一台已被攻陷的主机渗透其他主机的过程。为了完成这项任务,渗透测试人员和红队队员的通常做法是,利用powershell.exe在远程主机上运行base64编码的命令,以返回相应的beacon。这种方法的问题在于,攻击性的PowerShell早就被人们司空见惯了,因此,这些代码很容易被检测到并被阻止。横向渗透的难点在于,要求实施过程安全可靠(OpSec),这意味着产生的日志要尽可能少,或者生成的日志看起来是正常的,即隐藏在显眼的地方以避免被发现。本文的目的不仅是展示某些横向渗透技术,而且说明其幕后发生了什么,以及与之相关的检测指标。在这篇文章中,我们将用到许多Cobalt Strike语法,因为本文中主要利用它来实现C2,但是Cobalt Strike内置的横向渗透技术的动静过大,因而无法支持OpSec特性。此外,并非所有人都拥有Cobalt Strike,所以,Meterpreter也会出现在大多数的例子中,因为技术是通用的。
在本文中,我们将为读者详细介绍多种横向渗透技巧。对于这些技术,我们首先会进行概要的介绍,然后介绍其工作原理。为了便于读者理解下文,让我们先来厘清几个术语。
换句话说,访问令牌提供了用户的身份信息,可以用来判断该用户是否有权访问系统上的特定内容。如果您对Windows身份验证机制并不是非常了解的话,可以简单的把访问令牌看作是用户登录Windows时创建的一个登录会话。
PsExec是微软的Sysinternals套件提供的一款工具,允许用户通过端口445(SMB)使用命名管道在远程主机上执行PowerShell。首先,它会通过SMB连接到目标系统上的ADMIN$共享,上传PSEXESVC.exe,并使用服务控制管理器启动这个.exe程序,后者会在远程系统上创建一个命名管道,并最终将该管道用于I/O。
下面,我们举例说明PsExec的语法:
psexec \test.domain -u Domain\User -p Password ipconfig
如果使用Cobalt Strike(CS)来完成这项任务的话,过程会略有不同。它首先创建一个Powershell脚本,该脚本将对从内存运行的嵌入式payload进行base64编码,并将其压缩成一个one-liner,然后连接到ADMIN$或C$共享并运行Powershell命令,具体如下所示:
问题在于,这个脚本创建了一个服务并运行了base64编码命令,这些举动是很不正常的,将引发各种警报并生成相应的日志。此外,这里的命令是通过命名管道进行发送的,而命名管道在CS中都具有默认的名称(不过,这些默认的名称是允许进行修改的)。关于如何检测这些活动,请参阅Red Canary撰写的相关文章。
Cobalt Strike提供了两个PsExec内置函数,一个名为PsExec,另一个名为PsExec(psh)。两者之间的区别在于,PsExec(psh)会调用Powershell.exe,因此,我们的beacon将作为Powershell.exe进程运行;而不带(psh)的PsExec将作为rundll32.exe运行。
通过Cobalt Strike查看进程ID
默认情况下,PsExec将生成rundll32.exe进程以在其中运行。并且,它不会将DLL存放到磁盘中,所以从蓝队的角度来看,如果rundll32.exe不带参数运行的话,那就非常可疑了。
服务控制器的用途就不用多讲了吧——控制服务。它对于攻击者来说是特别有用的,因为调度任务可以通过SMB完成,所以启动远程服务的语法为:
sc \host.domain create ExampleService binpath= "c:\windows\system32**calc.exe"
sc \host.domain** start ExampleService
唯一需要注意的是,这里的可执行文件必须是特定服务对应的二进制文件。服务的二进制文件与普通的二进制文件有所不同——它们必须“签入”到服务控制管理器(SCM)中,如果没有签入的话,则退出执行。因此,如果这里使用服务之外的二进制文件的话,那么返回的代理/beacon马上就会挂掉。
使用CS时,我们可以专门为服务创建相应的可执行文件:
通过CoBalt Strike为服务生成的可执行文件
上面的攻击过程,也可以借助Metasploit完成,具体如下所示:
Windows Management Instrumentation(WMI)是Windows系统内置的一项服务,用户可以通过该服务远程访问各种Windows组件。由于可以通过端口135使用远程过程调用(RPC)进行远程访问(并借助于稍后介绍的临时端口),这样一来,管理员就能够远程执行自动管理任务了,例如,远程启动服务或远程执行命令等。当然,我们也可以直接通过wmic.exe进行交互。下面给出一个WMI查询示例:
wmic /node:target.domain /user:domain\user /password:password process call create "C:\Windows\System32\calc.exe"
Cobalt Strike在目标系统上利用WMI服务执行Powershell payload时,PowerShell.exe程序会在启动内置的WMI服务时打开,这就会导致OpSec问题,因为执行的是经过base64编码的payload。
我们可以看到,借助于WMI服务的情况下,仍然会创建一个命名管道——尽管wmic.exe能够通过PowerShell在目标系统上运行命令,那么,为什么要首先创建一个命名管道呢?命名管道虽然并非执行payload所必需的,但是使用CS创建payload时,必须使用命名管道进行通信(通过SMB)。
对于WMI服务,这里只是介绍了一些皮毛。对于这方面感兴趣的读者,建议参阅我的同事@mattifestation在Blackhat 2015大会上的精彩演讲。
Windows远程管理服务通常用于管理服务器硬件,其通信方式为WMI over HTTP(S)。跟传统的Web流量不同,它并没有使用80/443端口,而是使用5985(HTTP)和5986(HTTPS)端口。通常情况下,WinRM虽然是Windows系统默认安装的组件,但用户必须手动开启;不过,服务器操作系统则是一个例外,因为从2012R2版本开始,该服务就是默认开启的。即使启动了WinRM服务,也必须在客户端上使用侦听器(听起来是不是很耳熟?),否则就无法处理相应的请求。这些工作,我们既可以在Powershell中执行命令完成,也可以通过WMI和Powershell远程完成:
Enable-PSRemoting -Force
如果不使用CS的话,可以执行下列命令(大家可以利用自己的二进制文件替换掉calc.exe):
winrs -r:EXAMPLE.lab.local -u:DOMAIN\user -p:password calc.exe
如果借助于CobaltStrike,则可以:
当然,这里的问题在于必须使用PowerShell启动它。如果要想远程操作的话,那么还要借助于DCOM或WMI。虽然打开PowerShell通常不会引起人们的怀疑,启动WinRM侦听器也问题不大,但是在执行payload时就会闹出动静了,因为如果运行Cobalt Strike内置的WinRM模块的话,通常就会引起防御系统的警报了。
这里的警示指标为:
"c:\windows\syswow64\windowspowershell\v1.0\powershell.exe" -Version 5.1 -s -NoLogo -NoProfile
SchTasks是Scheduled Tasks的缩写,最初在端口135上运行,之后会使用临时端口,并通过DCE/RPC进行通信。这相当与Linux中创建的cron-job,我们可以指定任务的执行时间和执行内容。
对于PS,我们可以执行下列命令:
schtasks /create /tn ExampleTask /tr c:\windows\system32\calc.exe /sc once /st 00:00 /S host.domain /RU System
schtasks /run /tn ExampleTask /S host.domain
schtasks /F /delete /tn ExampleTask /S host.domain
对于CobaltStrike来说,我们可以使用下列命令:
shell schtasks /create /tn ExampleTask /tr c:\windows\system32\calc.exe /sc once /st 00:00 /S host.domain /RU System
shell schtasks /run /tn ExampleTask /S host.domain
然后,删除该任务(opsec!):
shell schtasks /F /delete /tn ExampleTask /S host.domain
(未完待续)