PowerShell是微软为Windows平台制作的新一代命令行操作环境。和传统的命令行环境相比,PowerShell的功能更加强大,使用方式也非常灵活。但这些新特性给用户和系统运维人员带来便捷的同时,也存在很大的安全风险。美国赛门铁克公司发布的一份报告指出,该公司在2016年分析的49127个PowerShell脚本样本中,有95. 4%的样本是恶意的。腾讯公司发布的2019年度企业安全报告也指出,在被恶意利用的系统组件中,利用PowerShell组件实现远程下载占比达90%。敌对势力在近年来对我国发起的网络攻击中,PowerShell恶意脚本也成为经常使用的攻击手段之一。本文将在介绍PowerShell的功能特点和安全机制的基础上,概述部分安全机制绕过方法,并提出针对PowerShell攻击的检测和防御方法。
一、PowerShell简介
从Windows 95正式脱离DOS系统、成为可独立运行的操作系统到现在,微软在各版Windows系统中都保留了命令行窗口,即“命令提示符”,用于兼容DOS程序、便于用户执行命令操作。随着技术的演进,功能有限的“命令提示符”已经不能满足运维需求。为此,微软于2006年发布了新一代命令行环境,即PowerShell1.0。从Windows7和Windows Server2008 R2开始,微软正式将PowerShell集成到系统中,便于管理员进行系统管理。在2016年,微软将PowerShell开源,并提供了跨平台支持,使用户在Linux等系统中也可以使用PowerShell的部分功能。
PowerShell基于.Net架构研制,既兼容原“命令提示符”的所有功能,又吸收了Linux系统中Bash命令行的诸多优点。PowerShell的主要特性有:一是具备强大的系统管理功能,不仅可以直接操作注册表,还可以通过WMI(WindowsManagement Instrumentation)接口对操作系统进行各类配置;二是支持管道操作,即前一条命令的返回结果可直接作为后一条命令的参数,因此可以通过管道将多条命令组合成一条命令,而且可以通过查询、筛选等命令对经过管道传输的数据进行过滤;三是支持网络和远程处理,除下载和传输文件等常规网络操作之外,还支持通过远程管理的方式在一组网络可达的计算机中执行PowerShell命令或脚本。此外,PowerShell还支持对象操作、后台异步运行等特性。
PowerShell最大的优势是支持脚本解析运行和调试,而且脚本编写方式非常灵活。在脚本文件中,除PowerShell的内置命令外,还可以直接调用.Ne t框架的类库实现非常复杂的程序逻辑。PowerShell脚本文件的正文一般为纯文本形式,语法规则与其他脚本语言类似,常用的扩展名为ps1、psc1和psm1,分别表示通用脚本、命令行脚本和脚本模块。可以根据上述特征初步判断一个文件是否为PowerShell脚本文件。
二、 PowerShell安全机制
PowerShell强大的功能在给运维人员和用户带来方便的同时,也给攻击者带来了可乘之机。从上节介绍的PowerShell特性可以看出,攻击者一旦能够从远程执行PowerShell脚本,或诱使用户执行恶意的PowerShell脚本,就可能执行非常危险的操作,例如修改系统安全配置、窃取用户数据文件等,甚至可以进一步植入后门进行持续性攻击。为了降低可能存在的安全风险,微软为PowerShell提供了一些基本安全机制,限制恶意脚本的直接运行。最常见的安全机制有“执行策略” 和反恶意程序扫描接口(Anti-Malware ScanInterface,AMSI)。
“执行策略”主要通过检测和验证签名的方法限制脚本文件的运行,该策略的默认取值为Restricted,即除了部分带有微软数字签名的脚本文件外,其他脚本一律无法直接运行。此外常见的取值还有:AllSigned,即经数字签名后的脚本才可运行;RemoteSigned,即本地脚本可直接运行,远程脚本则需数字签名才能运行;Unrestricted,即所有脚本文件均可运行。用户可以在PowerShell命令行中运行Get-ExecutionPolicy命令查看当前的策略取值。
AMSI用于为Microsoft Defender等杀毒软件提供PowerShell脚本检测接口。脚本在运行时,AMSI将对脚本的代码进行检测,并通过接口传递给系统内的杀毒软件。如杀毒软件发现代码存在恶意特征,将中止脚本的执行,并将结果反馈给用户。
除了以上2种安全机制外,PowerShell还能够对可运行的语言和函数进行限制,这些机制都可以在一定程度上提高PowerShell运行环境的安全性。
三、PowerShell攻击方法
利用PowerShell进行攻击一般分为2个方面:一方面是攻击者利用系统漏洞向用户终端释放恶意的PowerShell脚本,另一方面是攻击者通过发送钓鱼邮件等方式诱导用户下载和运行恶意PowerShell脚本。尽管PowerShell提供了相应的安全机制,但是攻击者依然可以通过多种方法绕过这些机制进行攻击。针对“执行策略”对运行脚本文件的限制,攻击者可诱导用户关闭这一限制,或通过参数设置等方法绕过该限制,而由于脚本文件大多为纯文本形式,攻击者可以很容易地对脚本的内容进行编码、混淆,使其绕过AMSI机制的检测,也绕过用户肉眼的识别。
下面以输出“Hello World”为例介绍几种常见的绕过“执行策略”、对代码进行编码和混淆的方法。为了便于介绍,我们首先创建一个脚本文件,内容为“write-host'HelloWorld'”,保存在D:\test.ps1。如果用户在该文件的图标上点击右键,选择“使用PowerShell运行”,是可以作为主动执行的方式运行该脚本文件的。如果在PowerShell命令行中直接输入上述内容,同样可以运行,如图1的①所示。但是,受“执行策略”的限制,在PowerShell命令行中无法直接运行该脚本文件,如图1 的②所示。然而,如果通过Get-Content方法读取文件内容,再将内容通过管道作为PowerShell的输入,则可绕过这一限制,如图1的③所示。
图1 在Pow erShell中执行命令
即使用户依然将“命令提示符”作为默认的命令行环境,也同样可以调用PowerShell来执行脚本文件和命令。例如:(1)可以通过临时修改“执行策略”的方式运行脚本文件;(2)可以将图1在PowerShell中执行命令经过Base64编码后的命令直接解码执行;(3)可以从网络直接下载脚本文件并执行;(4)经过内容混淆的命令依然可以执行。上述事例分别如图2的①~④所示。
图2 在传统的“命令提示符”中执行Pow erShell命令
此外,PowerShell的很多安全机制需要3.0或更高的版本才能支持。然而,由于兼容性等原因,系统中可能同时存在多个版本的PowerShell。在高、低版本共存的环境下,即使默认使用的是高版本,攻击者也可能通过命令行参数调用低版本PowerShell,发起“降级攻击”,从而绕过某些安全机制。
需要说明的是,PowerShell脚本的执行权限和当前用户的权限是一致的。如当前用户具有系统管理员权限,且未通过Windows内的用户账户控制(UserAccountControl,UAC)进行必要的防护,则以该用户权限执行的PowerShell脚本就可能对系统造成非常大的危害。但是,即使当前用户是普通用户,通过PowerShell脚本也能够窃取该用户有权访问的所有文件,包括其工作文件和私人文件等。
四、 PowerShell攻击的检测
从上面的介绍可以看出,PowerShell脚本文件可以通过编码、混淆、网络下载、转换为命令行命令等多种方式执行。如果将这些方式复合起来,可以仅用一条命令就从网络下载经编码和混淆的脚本文件并在本地运行。这使得PowerShell攻击不仅难以被发现,还可能因为不落盘存储等原因难以被追踪。但是,攻击事件依然可能会在终端系统中留下一些痕迹,这为我们检测攻击事件提供了可能。下面介绍几种检测方法。
查看系统日志是最有效的检测方法之一。Windows系统默认会记录包括PowerShell引擎启动事件等在内的一些基础日志。在系统的管理工具中找到“事件查看器”的图标,或在命令行中运行eventvwr.msc,打开“事件查看器”。然后在左侧依次展开“应用程序和服务日志—Windows PowerShell”,即可查看关于PowerShell的日志,如图3所示。
图3 查看Pow erShell的事件日志
在系统日志中,事件ID为400的事件表示引擎启动成功,403则表示引擎停止。用户主动打开PowerShell命令行,命令行加载时会生成400事件。如用户通过命令行调用PowerShell执行脚本文件,则会在脚本执行开始时生成400事件,在脚本执行完成时生成403事件。根据事件的时间,结合其他异常情况,可以对是否发生过PowerShell攻击做出一定的判断。此外,其他类型的事件日志也可以提供相应的辅助参考。
系统默认记录的PowerShell事件类型是有限的,可通过修改系统策略的方法补充其他需记录的事件类型。具体方法是:首先在系统的管理工具中找到“编辑组策略”的图标,或在命令行中运行gpedit.msc,打开“组策略编辑器”;然后依次展开“本地计算机策略—计算机配置—管理模板—Windows组件—WindowsPowerShell”,在右侧选择“启用模块日志记录”,设置为“已启用” ,并根据需要将相应模块名称添加到列表中,如“Microsoft.PowerShell.* ”等;最后再在右侧选择“打开PowerShell脚本块日志记录”,设置为“已启用”,并勾选下方的“记录脚本块调用启动/停止日志”。这些操作将进一步丰富PowerShell日志的内容,为分析后续可能发生的攻击事件提供支持。
除了系统日志外,PowerShell攻击还可能留下其他一些蛛丝马迹。例如,有的PowerShell攻击脚本需周期性执行,或在终端开机时自动运行,那么系统的计划任务列表和启动项中可能会保留有相应的记录,可通过相应的管理工具或微软提供的autoruns等工具进行检查。
此外,对于一些落盘存储和执行的PowerShell脚本,攻击者为确保攻击成功,通常会使用绝对路径。因此,一些权限较低的目录很可能成为恶意脚本文件临时存储的地方,特别是用户的数据目录(如C:\Users\用户名\AppData下的各个子目录)等。可以检查相应目录中是否存在异常的脚本文件,特别是以ps1、psc1和psm1等为扩展名的PowerShell脚本文件。必要时,还可以通过数据恢复工具检查相关目录中是否存在被删除的脚本文件。
五、针对PowerShell攻击的防御方法
在Windows 7及更高版本的系统中,PowerShell是内置组件,无法直接卸载。为了降低PowerShell攻击的风险隐患,提高系统的安全性,可采取以下措施。
升级PowerShell 到更新版本。在命令行中运行“Get-Host”即可查看当前PowerShell的版本号。为使用PowerShell内置的安全特性,建议升级到5.0 以上版本。
检查是否存在旧版本。由于PowerShell支持多版本并存,即使已安装高版本,也应当在命令行中尝试运行形如“PowerShell.exe -version 2 Get-Host”的命令,判断系统中是否依然存在较低版本的PowerShell,避免“降级攻击”。
检查“执行策略”是否已设置为“Restricted”。如果不是,可通过“Set-ExecutionPolicy Restricted”命令进行设置。
限制PowerShell的语言模式。如仅需保留PowerShell最基本的运行环境,不需要调用.Net 框架的类库,则可限制PowerShell支持的语言种类。具体做法是,首先在系统的环境变量中添加名为“__PSLockdownPolicy”的变量,取值为“4”;然后可以在PowerShell命令行中输入“$ExecutionContext.SessionState.LanguageMode” 进行验证,如返回结果由“FullLanguage” 变为“ConstrainedLanguage”,则表明语言模式修改成功。此时,大部分恶意程序都会因无法调用.Net 框架的类库而无法正常运行,从而不会对系统造成显著破坏。
安装杀毒软件并定期升级。一些杀毒软件能够检测PowerShell 脚本文件的恶意特征,有的还能够在执行PowerShell 脚本文件时发现其恶意行为,这也有助于防范恶意PowerShell 脚本的运行。
对于Windows XP系统,由于PowerShell是可选组件,如在日常工作中确实无需使用PowerShell的,还可通过控制面板中的“添加/删除程序”功能卸载该组件。
与此同时,用户还应提高辨别意识,养成良好的上网习惯,不访问来路不明的网站、邮件及其附件,不运行可疑的程序和脚本文件,定期更新杀毒软件和系统补丁,防止PowerShell恶意脚本的植入和运行。
(原载于《保密科学技术》杂志2020年2月刊)