写在前面的话
近期,我一直在我客户的网络环境中分析PowerShell攻击,根据我的分析以及研究结果,我发现了几种方法来帮助研究人员检测潜在的PowerShell攻击。这种方法主要利用的是Windows的事件日志,首先我们需要了解攻击者是如何使用PowerShell来实施攻击的,然后我们再来看一看相关的检测和防御机制。
PowerShell如何被用于网络攻击之中
PowerShell的能力大家有目共睹,近期也有越来越多的攻击者开始在攻击活动中使用PowerShell了。PowerShell是Windows操作系统自带的工具,因此目标Windows用户的主机中自然也就包含了这种工具。 在我们所观察到的攻击活动中,PowerShell一般会被攻击者用来下载恶意文件。攻击者可以利用PowerShell将远程服务器中托管的恶意文件下载至目标用户的设备之中。不仅如此,他们甚至还可以使用类似Start-Porcess、Invoke-Item或Invoke-Expression (-IEX)的命令直接将远程文件的恶意内容下载至目标设备的内存中,并直接在内存中运行。 在真实攻击场景下,System.net.Webclient中下面的这两种方法使用频率比较高:
−(New-object System.net.webclient).DownlodFile() −(New-object System.net.Webclient).DownloadString()
(New-object System.net.webclient).DownlodFile()
下面给出的是这种方法的简单使用样例(可使用类似Xampp等软件搭建http/https服务器来检测该方法的功能):
在这个样本中,恶意文件evilfile.txt会下载到目标设备的磁盘中,并通过调用环境变量$Appdata将该文件存储在路径C:Userskirtar_ozaAppDataRoaming中,然后使用“Invoke-Item”命令执行该文件。 下面给出的是真实场景中的攻击实例:
在这个样例中,攻击者使用了.downloadfile()方法来下载恶意文件,并使用环境变量将其存储在了用户的Appdata目录中,然后使用“Start-Process”命令在执行恶意代码。 除此之外,还有很多利用PowerShell来下载并调用恶意内容的例子:
(New-object System.net.Webclient).DownloadString()
DownloadString()方法不会在目标磁盘中下载任何的文件,而是直接将远程文件中的内容拷贝到目标设备的内存中。这些文件一般来说都是一些恶意脚本,并且能够使用Powershell –Command参数在内存中直接执行。这项技术在很多所谓的无文件恶意软件攻击中得到了广泛使用,因为恶意脚本可以直接在目标设备的内存中运行而不会在硬盘中留下任何痕迹。除此之外,这种技术还可以绕过基于签名的检测机制。 下面给出的是一个简单的样例:
其中,cmd.js是一个远程脚本,它能够从目标设备的内存中远程调用calc.exe,整个过程不会在硬盘中留下任何痕迹。 下面给出的真实场景中的攻击样例:
在这个样例中同时使用了DownloadString()和DownlodFile()这两种方法,其中的DownloadString()方法可从远程主机中下载PHP代码。
PowerShell可增强攻击的隐蔽性
攻击者会使用PowerShell所提供的各种参数选项来尽可能地增强攻击活动的隐蔽性,下面给出的是一些在攻击活动中常用的参数选项,我们可以用这些信息来构建我们的入侵威胁指标(IoC)列表:
–WindowStyle hidden / -w hidden: 隐藏程序的窗口 –Exec Bypass: 绕过类似Restricted之类的程序执行策略 –Command / -c : 利用PowerShell终端执行各种命令 –EncodedCommand / -e / -Enc: 在命令行中传递编码后的参数 –Nop / -Noprofile : 忽略Profile文件中的命令
下面给出的真实场景中的攻击样例:
入侵威胁指标IoC
接下来我们一起看一看相关的入侵威胁指标,它们可以帮助我们在各种环境中检测可疑的PowerShell活动。 观察PowerShell父进程和子进程之间的关系 一般来说,当我们从开始菜单或磁盘目录中直接运行PowerShell的话,它会在explorer.exe进程下运行。你可以使用进程管理器等工具来查看父进程和子进程之间的关系,你可以从下图中看到,Explorer.exe是PowerShell.exe的父进程:
但是在大多数PowerShell攻击中,PowerShell脚本或命令会通过命令行进程执行。因此,在这种场景下,PowerShell.exe的父进程将会是cmd.exe:
所以说,我们可以通过观察PowerShell父进程和子进程之间的关系来作为我们的IoC。除此之外,如果cmd.exe是通过脚本来生成的,并且父进程是 winword.exe、mshta.exe、wscript.exe或wuapp.exe的话,那么脚本的内容就值得我们去仔细检查了。 因此,我们需要注意并记录以下PowerShell进程:
-由 winword.exe生成的PowerShell进程(父进程是winword.exe) -由cmd.exe生成的PowerShell进程(父进程是winword.exe),并且cmd.exe是由winword.exe生成的(winword.exe为PowerShell的祖父进程)。 -由mshta.exe、wscript.exe、wuapp.exe或tasking.exe生成的PowerShell进程。
命令行为王
很多PowerShell攻击可以通过监控传递给PowerShell进程的命令行参数来进行检测。比如说,如果目标使用了DownloadFile()方法, 说明它很可能已经在目标设备的硬盘中下载了恶意文件,而且我们也许可以从中发现用于托管恶意文件的远程服务器。根据这些信息,我们可以对攻击活动的行为以及影响进行更加深入的分析。
Windows的安全事件日志如何帮助我们检测PowerShell攻击
接下来,我们一起看看Windows的事件日志如何帮助我们识别上述介绍的IoC。通过启用并记录下这些事件的EventID,我们就可以更有效率地检测PowerShell攻击了。 我将要介绍的是Windows安全事件ID 4688-进程创建。没错,它确实会生成大量的事件记录,但是我们可以通过简单的过滤来记录并监控我们所感兴趣的事件。默认情况下,系统会禁用掉进程创建审计功能,所以我们首先要使用GPO来开启这个功能。 相关功能介绍以及启用方法可访问以下资料获取:[阅读原文] 事件ID 4688可以根据SIEM生成的警报信息来给我们提供三条关键信息,我们可以使用这两条信息来检测PowerShell攻击:
1. 创建了哪个进程; 2. 进程创建时传递了哪些命令行参数; 3. 父进程信息;
接下来,我将会用一个Splunk样本来解释如何利用警报信息来检测可疑的PowerShell活动。 首先,我们需要捕捉到PowerShell攻击互动,所以我们需要监控与PowerShell.exe进程创建相关的事件。一般来说,事件ID 4688的内容如下所示:
所以,我们需要使用下列搜索语句来搜索这些事件信息:
接下来,我们需要检查PowerShell进程初始化时传递过来的命令行参数。Process_Command_Line中包含了传递给新创建进程(例如PowerShell)的命令行参数信息,我们可以基于一些常见参数(例如 –e, -Encod, -windowstyle , Bypass , -c , -command)来创建警报:
除此之外,你也可以创建一个包含了可疑命令行参数的输入查询列表来配置和查询警报信息。 从Windows 10和Windows Server 2016开始,微软在事件ID 4688中添加了一个名叫“Creator Process Name”的数据域,其中包含了父进程信息。而我们就可以利用这个新添加的数据域(可疑父进程)来创建警报:
总结
对于网络管理员来说,监控环境中PowerShell的执行其实是非常重要的,如果命令行经过了混淆处理,那么你很大概率已经遇到了网络攻击。而此时,我们就需要记录事件ID 4688,然后过滤并记录下任何关于PowerShell进程创建的活动以及传递给PowerShell的命令行参数,并以此来检测可疑的PowerShell攻击活动。