在 PowerShell v5 中有几个令人信服的安全功能,使得它很有必要部署在生产环境。我曾在2015年的几个安全会议上提到过这些安全功能。
这些安全功能包括:
脚本块日志记录
脚本块日志会记录 PowerShell 真正执行的代码,如果此功能被禁用,则只会记录混淆过的代码,这使得创建有用的检测指标变得更加困难。
完整的脚本副本记录
当此功能被启用后,每个计算机上的每个用户执行的 PowerShell 代码将被写入到“只写”的共享文件中。如果计算机是离线状态,那么计算机就会将文件数据缓存起来,直到其重新联机后再同步到日志中心。
使用 AppLocker 强制 PowerShell 进入 约束模式
受限的“语言模式”会阻止PowerShell 访问 Windows API。
反恶意软件扫描接口 (AMSI)
Windows 10 中的 反恶意软件扫描接口 (AMSI) 会在所有的脚本代码执行之前通过 PowerShell 和其他的 Windows 脚本引擎进行安全扫描。统上安装的反病毒/反恶意软件解决方案需要支持 AMSI 以便于能进行代码扫描。这样的做法最大的好处就在于所有的代码在传递到 PowerShell 引擎之前就会被扫描,甚至是那些被混淆过的,注入到内存或者从其他地方下载的代码都会被扫描。截止目前,只有 Microsoft Defender 和 AVG 支持 AMSI。
在 PowerShell 中也有与 Defender 交互获取威胁检测状态的 cmdlets。
第一个检测显示的是在磁盘上的几个不同的文件中检测到了威胁。
第二个检测显示的是在“PowerShell.exe_10.0.1058.0000000000010”中检测到了威胁。这很奇怪 ;|。
它在内存中检测到了从互联网下载并在内存中执行的威胁。
尽管微软提供了传统的反病毒/反恶意软件无法提供的安全扫描能力,并在这个领域大步向前,BTW,Windows 10 的 AMSI 依然存在问题。
到目前,至少有两种方法可以绕过 AMSI:
使用自定义的 EXE 调用自定义的 amsi.dll。
Matt Graeber 描述了如何使用反射来绕过 AMSI[Ref].Assembly.GetType(‘System.Management .Automation.AmsiUtils’).GetField(‘amsiInitFailed’,’NonPublic,Static’).SetValue($null,$true)
另外,如果拥有适当的权限,也可以轻易的禁用掉反恶意软件,虽然与此活动有关的事件会被记录。
在有些时候,“恶意”的 PowerShell 代码就会通过执行检查。
限制 PowerShell 的能力
要找到锁定 PowerShell 的各种建议并不是很难。
主要包括以下几点:
从系统中移除 PowerShell(不太可能)
锁定 PowerShell.exe禁止其运行(并不是100%有效,因为 PowerShell 并不只是Powershell.exe)
通过 AppLocker 控制 PowerShell(如果部署正确的话,将会非常有效)
PowerShell 的约束语言模式
由于 PowerShell 常常用于系统管理和登录脚本(以及越来越多的应用程序管理,如 Exchange 和 DSC ),禁止 PowerShell 的运行是不现实的(另外,这也不是非常有效)。
我个人更趋向于配置 PowerShell 的约束语言模式,将 PowerShell 锁定到基础的核心功能(不能调用 Windows API 或访问 .NET )。
使用约束语言模式限制 PowerShell 攻击能力
除此之外,PowerShell 支持多种语言模式以限制 PowerShell 可以执行哪些操作。 PowerShell 的约束语言模式是为 Surface RT 平板设备而开发的,但是此模式在标准的 Windows 中的 PowerShell 也是可用的。 约束语言模式限制了 PowerShell 使其只有基础的功能,移除了一些高级功能的支持(例如 .NET 和 Windows API 的调用以及 COM 对象的访问)。 缺乏这些高级功能的支持,将会使大多数基于 PowerShell 的攻击工具无法正常运行,因为他们依赖这些功能。 不过,这种方法的缺点是,为了配置 PowerShell 在约束模式下运行,必须设置环境变量,可以在 PowerShell 中运行命令或通过组策略进行配置。
约束语言模式是一种有用的临时性的 PowerShell 安全缓解措施,可以缓解许多初期的 PowerShell 攻击,但是很明显它不是万能的。 它应该被认为是一种轻量级的“白名单”的缓解措施。 要注意的是, PowerShell 的约束模式很可能会被绕过,另外,并不是所有的 PowerShell “攻击脚本”都会被阻止运行 —— 当然,那些使用高级功能或者通过反射加载到内存中的 DLL 如 Invoke-Mimikatz 则能够被阻止运行。
启用约束语言模式:
[Environment]::SetEnvironmentVariable(‘__PSLockdownPolicy‘, ‘4’, ‘Machine‘)
通过组策略启用步骤:
Computer Configuration(计算机配置)\Preferences(偏好设置)\Windows Settings (Windows 设置)\Environment(环境变量)
一旦 PowerShell 的约束语言模式启用后,大多数基于 Powershell 的攻击工具都不能正常运行,因为他们依赖于这些被约束模式禁用的组件。
攻击者一旦获得对系统的控制权后,就可以修改此环境变量。 需要注意的是,攻击者必须生成一个新的 PowerShell 实例,以便在更改环境后以完整的语言模式运行代码。 这些更改操作将会被记录,并且可以帮助防御者识别系统上的异常活动。
移除约束语言模式:
Remove-Item Env:__PSLockdownPolicy
检查语言模式:
$ExecutionContext.SessionState.LanguageMode
启用 PowerShell 的约束语言模式是缓解基于 PowerShell 攻击的另外一种措施。
组合 PowerShell v5 与 AppLocker – 约束语言模式不再轻易被绕过。
PowerShell v5 支持自动锁定降级,这需要 AppLocker 部署在"允许"模式才行。Applocker 允许模式是真正的程序白名单,它可以有效防止未经授权的任何二进制文件执行。当 PowerShell v5 检测到 Applocker 在允许模式下时,PowerShell 会自动将其语言模式设置为约束模式,这就极大地限制了系统上的受攻击面。在Applocker 允许模式开启并且 PowerShell 是在约束模式下运行的时候,攻击者不可能将 PowerShell 的语言模式更改为完整的模式也无法运行任何 PowerShell 攻击工具。当 AppLocker 配置在"允许模式"时,PowerShell 会将自身功能降级到"约束模式",只允许交互式输入以及用户编写的脚本的功能。约束模式下的 PowerShell 只允许核心的 PowerShell 功能目的是防止执行那些经常使用扩展语言特点的且带攻击性的 PowerShell 工具 (如:操作 .NET 的脚本,通过 Add-Type cmdlet 调用 Win32 API 以及与 COM 对象进行交互的脚本) 。
需要注意的是,AppLocker 策略允许执行的脚本(例如企业签名过的代码或受信任的目录)的代码将会在完整的 PowerShell 模式下执行,而不是在受约束的 PowerShell 环境中执行。 所以,即使攻击者拥有管理员权限也不能轻易绕过这种限制。
如果你胆子够大,你完全可以锁定系统的 PowerShell 到“无语言模式”,这意味着 PowerShell 将会被限制到“极限”。
NO LANGUAGE
在 NoLanguage 语言模式下,用户可以运行命令,但是他们不能使用任何语言元素。
点此查看PowerShell 的“语言模式”
PS>Attack
PS>Attack 是一个自包含了自定义的 PowerShell 控制台的攻击工具,其中包括许多常见的其他 PowerShell 攻击工具,它通过 .NET 调用 PowerShell(System.Management.Automation.dll)。 其中包含的 PowerShell 攻击工具是加密的(为了躲避 AV 查杀),并在运行时解密到内存执行。
其这中还有一个自定义的构建工具,用于确保每个构建的 exe 都是不同的(绕过 AV 查杀)。
PS>Attack 包含了如下几个非常流行的 Powershell 攻击工具:
Powersploit
Invoke-Mimikatz
Get-GPPPassword
Invoke-NinjaCopy
Invoke-Shellcode
Invoke-WMICommand
VolumeShadowCopyTools
PowerTools
PowerUp
PowerView
Nishang
Powercat
Inveigh
PS>Attack 作为一种攻击者无需运行 PowerShell.exe 就能够利用 PowerShell 攻击工具的方法,确实非常有效。
由于 PS>Attack 是在一个 exe 中调用 PowerShell ,因此,可以绕过约束语言模式执行 PowerShell 代码。
Windows 10 提供了移除 PowerShell v2.0 的功能,但是这并非彻底删除了 PowerShell。
一旦从 Windows 10 中移除了 PowerShell v2 , PS>Attack 的使用就会被完整清楚的记录。
检测调用 PowerShell 的自定义 EXE
事件ID 400: HostApplication 不是标准的Microsoft 工具(PowerShell,PowerShell ISE等)。
事件ID 800:HostVersion 和 EngineVersion 的版本不匹配(有问题)。
System.Management.Automation.dll 被加载到了非标准的进程中。
需要注意的是,自定义的 EXE 可以直接调用本地的 .NET 和 Windows API 而不需要使用 PowerShell。
检测 PowerShell 攻击工具
我已经注意到在大多数基于 PowerShell 的攻击工具中的几个必需的元素。
可以使用以下检测指标以及 PowerShell 模块日志记录(最好使用脚本块日志记录),可以检测出大多数的 PowerShell 攻击工具。
另外,确保您在您的环境中适当调整这些检测指标,以消除一些误报。
AdjustTokenPrivileges
IMAGENTOPTIONALHDR64MAGIC
Management.Automation.RuntimeException
Microsoft.Win32.UnsafeNativeMethods
ReadProcessMemory.Invoke
Runtime.InteropServices
SEPRIVILEGEENABLED
System.Security.Cryptography
System.Reflection.AssemblyName
System.Runtime.InteropServices
LSAUNICODESTRING
MiniDumpWriteDump
PAGEEXECUTEREAD
Net.Sockets.SocketFlags
Reflection.Assembly
SECURITY_DELEGATION
TOKENADJUSTPRIVILEGES
TOKENALLACCESS
TOKENASSIGNPRIMARY
TOKEN_DUPLICATE
TOKEN_ELEVATION
TOKEN_IMPERSONATE
TOKENINFORMATIONCLASS
TOKEN_PRIVILEGES
TOKEN_QUERY
Metasploit
Advapi32.dll
kernel32.dll
msvcrt.dll
ntdll.dll
secur32.dll
user32.dll