推荐:https://zhuanlan.zhihu.com/p/25226349
推荐:https://blog.stealthbits.com/ways-to-detect-and-mitigate-powershell-attacks
转载内容如下:
PowerShell 从诞生至今,已经被大多数攻击者滥用在了各种攻击场景中,如内网渗透,APT攻击甚至包括现在流行的勒索软件中。PS之所以被广泛的“滥用”在攻击中,就是因为PS的功能强大且调用方式十分灵活。随着利用PS进行攻击的趋势愈演愈烈,掌握有效的防御和检测PS攻击的方法是十分有必要的。
PowerShell 成为攻击工具的演变过程
PowerShell 是一个内置在每个受支持的Windows版本中 (Windows 7 / Windows 2008 R2 和更高版本)的命令行程序,它能够提供令人难以置信的灵活性和功能化管理 Windows 系统的能力。这种能力使得 PowerShell 正在吸引攻击者使它逐渐成为一个非常流行且得力的攻击工具。一旦攻击者可以在一台计算机上运行代码,他们就会执行 PowerShell 代码,因为PS代码可以运行在防病毒软件不能看到的地方如内存中。攻击者还可能会下载 PowerShell 脚本文件 (.ps1) 到磁盘中,因为 PowerShell 能够提供从网站下载代码并在内存中运行的能力,不过这没有必要。
Dave Kennedy & Josh Kelley 在 DEF CON 18(2010 年) 演讲了攻击者如何利用 PowerShell进行攻击的主题。Matt Graeber 开发了 PowerSploit 并在 Monday.com 发表了博文—— 为什么 PowerShell 是一个强大的攻击平台。"PowerSploit"在 2012 年被发布后,PowerShell 被用来作为攻击平台的趋势快速上升,直到大约一年后 Mimikatz 开始支持 PowerShell 调用 (aka Invoke-Mimikatz) ,这使得 PowerShell 作为攻击工具的使用变得更为流行。PowerShell 提供了强大的能力,因为它可以运行从其他主机 (或互联网) 上下载的 .Net 代码并动态执行,甚至无需写到磁盘中执行,也能够在内存中执行。这些特点使得 PowerShell 在获得和保持对系统的访问权限时, 就成为了攻击者首选的攻击手段,利用PS的诸多特点攻击者可以持续攻击而不会被轻易发现。PowerShell v5 极大的提高了 PowerShell 的安全性并且在 Windows 10 系统上运行 PowerShell 时,PowerShell 的攻击能力将会大大降低。
PowerShell 并不只是 “PowerShell.exe”
阻止对 PowerShell.exe 的访问是限制 PowerShell 执行的一个比较"简单"的方法,至少,它看上去很简单。但现实情况是 PowerShell 并不仅仅是一个可执行文件这么简单。PowerShell 是 Windows 系统的一个核心组件 (且不可移除),它存在于 System.Management.Automation.dll 动态链接库文件 (DLL) 中并且可以附加到不同的运行空间中而且可以有效的进行 PowerShell 实例化 (想想 PowerShell.exe 和 PowerShell_ISE.exe)。可以通过代码在自定义的 PowerShell 运行空间实例化,所以 PowerShell 可以通过一个自定义的可执行文件进行启动 (例如 MyPowershell.exe) 。实际上,已经有一些无需 Powershell.exe 就能运行 PowerShell 代码的几种方法了。Justin Warner (@SixDub) 在 2014 年底发表了一篇博文 如何启动受限的Powershell.exe ,也叫做 PowerPick)。
由于 PowerShell 代码可在不运行 PowerShell.exe 的情况下执行,因此限制 Powershell.exe 可执行文件的运行并不是理想的解决方案,也不能很好的阻止攻击。
禁止运行 Powershell.exe 并不能阻断 基于 Powershell 的攻击。要阻止基于PowerShell 的攻击,只是禁止 Powershell.exe 运行还不够,还需要另外一种更加可靠的方法 (见 PowerShell 约束语言模式和 PowerShell v5安全增强功能)。
PowerShell 执行策略并不能提供真正的安全
默认情况下,PowerShell 执行策略是设置为限制PS1 文件不能自动执行。微软吸取了攻击者在 Windows 上可以轻松地进行动态代码执行的教训。这意味着在默认情况下,虽然禁用了所有的脚本文件执行,但仍然可以通过手动输入执行命令。
"PowerShell 执行策略并不是一种安全边界"
轻松绕过 PowerShell 执行策略的限制:
PowerShell.exe 可以使用一些参数在没有执行策略的情况下实例化要执行的脚本文件:
PowerShell 是一个攻击平台!
PowerShell作为一个攻击平台的逐渐兴起,使许多组织感到十分惊讶,因为传统的防御措施无法缓解甚至阻止攻击者利用PowerShell取得成功。 攻击者一般使用PowerShell作为“后期漏洞利用”工具;在攻击者获得了系统的访问权限后就开始运行恶意的PowerShell代码。 在一些攻击中,用户被诱骗打开并执行文件或直接通过利用漏洞进行代码执行。 无论如何,一旦攻击者获得了系统的访问权限,那么所有的操作系统标准工具和实用程序都可为攻击者所用。
既然攻击者可以在你的环境中的计算机上运行他们的代码,那你在面对这种新攻击方式的现实时该如何调整防御策略?
PowerShell作为一个理想的攻击平台的原因如下:
能够在内存中运行代码,而不需要写入磁盘文件。
能够从另一个系统中下载并执行代码。
能够直接调用.Net 和 Windows API。
CMD.exe 通常会被限制运行而 PowerShell 不会。
大多数企业组织都不太关注 PowerShell 的活动情况。
一般来说,PowerShell经常被用在整个攻击的一部分中,比如前期攻击中往往会针对工作组中的用户进行攻击:
可以使用以下方式调用PowerShell攻击代码:
Microsoft Office宏(VBA)
WMI
HTA脚本(HTML应用程序 - 控制面板扩展)
CHM(编译的HTML帮助文件)
Java JAR文件
其他脚本类型(VBS / WSH / BAT / CMD)
用典型的编码命令进行编码执行
PS的“编码命令”的命令会混淆攻击代码,甚至可以压缩代码,以避免Windows控制台字符限制(8191)。
Powershell.exe –WindowStyleHidden -noprofile -EncodedCommand
使用约束语言模式限制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攻击在系统网络上的活动(包括PowerShell Empire和PowerSploit)可以从PowerShell日志记录功能开始。启用PowerShell日志记录功能需要PowerShell v3及更高版本的支持。另外,PowerShell v4版本中添加了一些额外的日志详情(打了KB300850补丁的Windows 2012 R2和Windows 8.1),这有助于发现和跟踪攻击活动。
可以通过组策略为PowerShell模块启用PowerShell日志记录功能:
Microsoft.PowerShell。* - 记录PowerShell主要的核心功能。
ActiveDirectory – 记录Active Directory 相关的cmdlet的使用情况。
BITSTransfer - 记录有关BITS cmdlet的使用情况。
CimCmdlets(2012R2 / 8.1) - 记录与CIM接口相关的cmdlet的使用情况。
GroupPolicy-记录组策略相关的cmdlet的使用情况。
Microsoft.WSMan.Management - 记录管理Web服务管理器(WS-Management)和Windows远程管理器(WinRM)相关的cmdlet的使用情况。
NetAdapter / NetConnection – 记录网络相关的cdmdlet的使用情况。
PSScheduledJob / ScheduledTasks(PSv5) - 记录管理计划任务作业对象相关的cmdlet的使用情况。
ServerManager – 记录与Server Manager 相关的cmdlet 的使用情况。
SmbShare - 记录SMB共享活动情况。
PowerShell日志记录还可以配置为记录所有的PowerShell模块(“*”)的活动情况,这也是我的偏好设置,记录所有的PowerShell cmdlet 会对所有的模块起作用。即使攻击者导入了自定义的PowerShell模块进行攻击,也是可以记录到的。
组策略:
计算机配置\策略\管理模板\ Windows组件\ Windows PowerShell
为了使这些日志变得有用,它们需要被集中存储到一台具有告警已知攻击方式的中央日志记录系统中。
感兴趣的活动:
通过.Net下载 (New-Object Net.WebClient.DownloadString)
Invoke-Expression(&或者:“iex”)。
BITS的活动
计划任务的创建/删除。
PowerShell远程连接功能。
下图显示了多个PowerShell攻击行为:通过Invoke-Expression(IEX)调用.Net Web Client下载功能下载互联网上的PowerShell代码并执行。
PowerShell v5提供了增强的安全性以及改进的日志记录功能。
脚本块日志记录
脚本块日志提供了在事件日志中记录反混淆的 PowerShell 代码的能力。大多数的攻击工具都会进行混淆处理,通常会使用 Base64 编码,在执行代码之前很难发现或确认这些代码实际上会做些什么事情。由于脚本块日志会在实际的代码传递到 PowerShell 引擎之前进行记录,这就使得在代码执行之前就能进行日志记录,因为脚本代码在执行之前需要进行反混淆处理。
由于许多 PowerShell 攻击攻击都对攻击代码进行了混淆处理,所以很难识别脚本代码的具体功能。脚本块日志会对要执行的代码进行反混淆和记录。由于代码已经被反混淆且进行了记录,所以当集中化的日志系统捕捉到可疑的日志时就能够及时的进行告警。
识别带有攻击性的 PowerShell 代码的一个关键挑战是大多数情况下代码都是混淆过的 (Base64,Base64 + XOR 等)。这使得几乎不可能实现实时分析,因为没有触发警报的关键字消息。
更深度的脚本块记录可疑记录它处理过的脚本文件内容也就是在执行时所生成的脚本的文件内容。
Microsoft 提供了一个经过混淆处理的命令代码示例:
## Malware function SuperDecrypt { param($script) $bytes = [Convert]::FromBase64String($script) \## XOR “encryption” $xorKey = 0x42 for($counter = 0; $counter -lt $bytes.Length; $counter++) { $bytes[$counter] = $bytes[$counter] -bxor $xorKey } [System.Text.Encoding]::Unicode.GetString($bytes) } $decrypted = SuperDecrypt “FUIwQitCNkInQm9CCkItQjFCNkJiQmVCEkI1QixCJkJlQg==” Invoke-Expression $decrypted
传递给 PowerShell 处理的原始的脚本块内容 (如上文所述)就是 PowerShell 执行的实际命令。
请注意,脚本块记录默认是启用的。
完整的脚本副本
完整的脚本副本功能可以通过组策略启用并为系统上每个用户在该系统上执行的每个 PowerShell 命令和代码块提供一个"更加丰富"的副本文件。这份副本可以定向传输到“只写”的网络共享上为后续的分析和 SIEM 工具进行读取。
另外,PowerShell 具有将控制台输出的文本信息写入到一个副本文件中,这需要用户或脚本在运行时使用 “start-transcript $FileName”执行。这就提供了一个简单的脚本日志文件。这种方法的缺点是在同一时间只能有一个副本记录活动。PowerShell ISE 编辑器不支持副本记录,Start-Transcript 必须被添加到每个用户的 PowerShell 配置文件中以便按顺序保存记录所运行的命令。
完整的脚本副本提供简单的方法把所有的 PowerShell 命令 (包括那些内部运行的或其他位置的脚本) 都写入到一个特定于计算机上的且存储在网络共享中的记录文件中。这样就可以以接近实时分析的效果对 PowerShell 的活动进行快速分析并能确认已知的安全风险。
完整的脚本副本记录功能可以通过组策略启用,标头中会包含以下信息︰
Start time
User Name
RunAs User
Machine (Operating System)
Host Application
Process ID
参数:
IncludeInvocationHeader —— 包括每个运行的命令的开始时间。
OutputDirectory —— 把副本文件写到一个中心位置上,例如网络共享。
通过GPO启用PowerShell脚本块日志记录功能并记录脚本文件的调用信息:
Microsoft 提供了一个 PowerShell 脚本配置 中央副本共享 ACL 的示例︰
md c:\Transcripts ## Kill all inherited permissions $acl = Get-Acl c:\Transcripts $acl.SetAccessRuleProtection($true, $false) ## Grant Administrators full control $administrators = [System.Security.Principal.NTAccount] “Administrators” $permission = $administrators,”FullControl”,”ObjectInherit,ContainerInherit”,”None”,”Allow” $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission $acl.AddAccessRule($accessRule) ## Grant everyone else Write and ReadAttributes. This prevents users from listing ## transcripts from other machines on the domain. $everyone = [System.Security.Principal.NTAccount] “Everyone” $permission = $everyone,”Write,ReadAttributes”,”ObjectInherit,ContainerInherit”,”None”,”Allow” $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission $acl.AddAccessRule($accessRule) ## Deny “Creator Owner” everything. This prevents users from ## viewing the content of previously written files. $creatorOwner = [System.Security.Principal.NTAccount] “Creator Owner” $permission = $creatorOwner,”FullControl”,”ObjectInherit,ContainerInherit”,”InheritOnly”,”Deny” $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission $acl.AddAccessRule($accessRule) ## Set the ACL $acl | Set-Acl c:\Transcripts\ ## Create the SMB Share, granting Everyone the right to read and write files. Specific ## actions will actually be enforced by the ACL on the file folder. New-SmbShare -Name Transcripts -Path c:\Transcripts -ChangeAccess Everyone
通过组策略启用完整的脚本副本记录功能的操作步骤︰
Windows Components(Windows 组件) -> Administrative Templates (管理模板) -> Windows PowerShell -> Turn on PowerShell Transcription
该组策略配置对应的注册表路径为:
HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription
Invoke-Mimikatz 功能解析和检测
如要阅读更多关于Mimikatz和Invoke-Mimikatz的说明请参阅相关资料。
在PowerSploit中的 “Invoke-Mimikatz” PowerShell脚本提供了Mimikatz的大多数功能,该脚本利用Mimikatz 2.0和Invoke-ReflectivePEInjection通过反射将Mimikatz完全加载到内存中。通过这种手法你还可以做一些事情,比如凭据导出,而不必将Mimikatz二进制文件写入磁盘。“注意,PowerSploit框架现在托管在”PowerShellMafia“ 的GitHub仓库中。
是什么让Invoke-Mimikatz具有如此大的魔力?正是通过“反射”将Mimikatz DLL(嵌入在脚本中)加载到内存的能力。 Invoke-Mimikatz代码可以从互联网下载,并从内存中执行而无需写入任何文件到磁盘中。此外,如果以适当的权限运行Invoke-Mimikatz,并且目标计算机已经启用了PowerShell远程连接功能,则可以远程导出其他系统的凭据,以及远程执行标准的Mimikatz命令,而不会在远程系统上写入任何文件。
Invoke-Mimikatz已经不再更新但是Mimikatz依旧在不断更新。不过你可以手动进行更新,将编码过的DLL(32位和64位版本)用较新的文件替换就行了。手动更新Invoke-Mimikatz中的Mimikatz DLL的过程并不是十分复杂。 PowerShell Empire内置的Invoke-Mimikatz通常一直保持更新。
Invoke-Mimikatz –DumpCreds:使用mimikatz从LSASS中导出凭证
Invoke-Mimikatz –DumpCerts:使用mimikatz导出所有私有证书(即使它们被标记为不可导出)
Invoke-Mimikatz -Command“privilege :: debug exit”-ComputerName“computer1”: 提升在远程计算机上具有的权限(调试权限)
Invoke-Mimikatz 的“Command”参数允许Invoke-Mimikatz执行自定义的Mimikatz命令。
防御者应该期望Mimikatz中所包含的任何功能都能在Invoke-Mimikatz中使用。
如何检测Invoke-Mimikatz和其他的PowerShell攻击工具?
关于如何检测PowerShell攻击工具(如Invoke-Mimikatz)的大多数建议是跟踪与这些攻击工具相关的错误的“签名”的词或短语(这通常是AV的检测方法),以便能具有高的成功率或低误报率,然而这并不是一个好的方法。
这些“签名”关键字通常包括:
“mimikatz”
“gentilkiwi”
“Invoke-Mimikatz”
现在的问题是,这是PowerShell代码,所以在记事本中打开并修改这些签名关键字是很烦琐的。
那么该怎么做呢?
检测PowerShell攻击代码的最佳方法是查找代码关键指示符 —— PS攻击代码能正确运行所需的关键代码段。
Invoke-Mimikatz事件日志关键词:
“System.Reflection.AssemblyName”
“System.Reflection.Emit.AssemblyBuilderAccess”
“System.Runtime.InteropServices.MarshalAsAttribute”
“TOKEN_PRIVILEGES”
“SE_PRIVILEGE_ENABLED”
在Invoke-Mimikatz之类的PowerShell攻击工具运行后,在PowerShell操作日志中搜索“System.Reflection”就会返回大量的事件信息:
同样,在Invoke-Mimikatz之类的PowerShell攻击工具运行后,在PowerShell操作日志中搜索“TOKEN.PRIVILEGES”也会返回大量的事件信息:
PowerShell攻击工具检测
可以通过在PowerShell操作日志中来监视以下指标,就能检测到许多PowerShell攻击工具。 这些指标是PowerSploit工具特有的特征,许多其他的PowerShell攻击工具也可以相同的方法进行检测。
Invoke-TokenManipulation:
“TOKEN_IMPERSONATE”
“TOKEN_DUPLICATE”
“TOKEN_ADJUST_PRIVILEGES”
Invoke-CredentialInjection:
“TOKEN_PRIVILEGES”
“GetDelegateForFunctionPointer”
Invoke-DLLInjection
“System.Reflection.AssemblyName“
“System.Reflection.Emit.AssemblyBuilderAccess“
Invoke-Shellcode
“System.Reflection.AssemblyName“
“System.Reflection.Emit.AssemblyBuilderAccess”
“System.MulticastDelegate”
“System.Reflection.CallingConventions”
G
et-GPPPassword
“System.Security.Cryptography.AesCryptoServiceProvider”
“0x4e,0x99,0x06,0xe8,0xfc,0xb6,0x6c,0xc9,0xfa,0xf4”
“Groups.User.Properties.cpassword”
“ScheduledTasks.Task.Properties.cpassword”
Out-MiniDump
“System.Management.Automation.WindowsErrorReporting”
“MiniDumpWriteDump”