导语:随着这种演变以及将技术整合成一种单一的脚本语言,防御者能否发现一种方法来成功的阻止PowerShell的执行?
从目前的攻击发展趋势来看,攻击者已经比大多数防御者或系统管理员更喜欢使用PowerShell。像Powersploit,Veil Power *和Nishang这样的工具的一些常规功能已经被Red Team,Pentesters,恶意攻击者们所使用。随着这种演变以及将技术整合成一种单一的脚本语言,防御者能否发现一种方法来成功的阻止PowerShell的执行?当然,软件限制策略(SRP)或AppLocker确定能起到作用吗?不要肯定那么早哦…
经过实践评估后,我发现在我们拿到一个域用户,本地提权,窃取凭据,注入payloads,并继续在域中渗透时几乎每一步都在使用PowerShell。可是,我们总有恶梦的一天,会有人能够有效地限制PowerShell的执行并且那些老技巧肯定会失效。从我与防御者或信息安全爱好者的交流中,他们防御PowerShell的意识和技术正在上升,人们终于开始注意到PowerShell攻击工具的常规发布,以帮助发动攻击。这就是说,直到在不需要的系统上禁用PowerShell成为企业的常规做法之前,攻击者仍然可能会取得胜利。从这一点上来说,在防御者考虑将实现的防御方案所需的时间/成本最小化到一个点前,PowerShell的限制不太可能发生。
下面是一些之前关于使用 PowerShell 进行攻击的研究︰
1. FireEye在黑帽大会发布的白皮书 —— 包括与PowerShell攻击有关的事件响应和讨论。这份paper写的非常好!在与演讲者关于一些防御方案的谈话讨论中我获益匪浅。我希望以后能再参与这样的活动。 2. Crowdstrike 发布的关于DeepPanda的报告 —— 这是一份APT攻击者使用 PowerShell 进行攻击的报告。 3. PowerShell武器化 —— PowerShell武器化是 harmj0ys 发表的一篇很好的关于绕过执行限制的博文。 4. PowerShell 基础知识 —— Carlos Perez的PowerShell教基础程。绝对值得一读。 5. Powersploit' Github —— 攻击 PowerShell 用户的必需工具。
防御者的方法 — “使用Applocker限制PowerShell”
免责声明:本文不是AppLocker的使用指南。后面你会看到,这是一个指导你什么事情不可以做的文章! 此外,我不是微软认证系统工程师(MSCE)也不是什么微软专家。下文会有正确配置AppLocker以防止PowerShell运行的方法…但是如果有人已经公开过了,我就不会再做过多的说明了! 毕竟我Google的平均次数和其他网络防御者一样多。
AppLocker是Microsoft提供的用于“企业应用程序控制”的解决方案。它的目的是限制不必要的软件的运行,并提供了各种方法来实现这一点。它允许你通过指定路径,文件哈希或应用程序发布者来限制可执行文件,DLL,安装程序或脚本等策略以限制程序正常运行。生成的策略由组策略推送并进行集中管理。
显然,在可用性和安全性之间需要一直强调“平衡”,但是我发现在这里有必要提到一点,那就是使用AppLocker的最佳设置可能是利用白名单的方式。企业组织可以分析他们的标准构想方案和构建策略来匹配此构想方案。也就是说,CEO不可以安装他们想要的P2P软件,用户将无法运行魔兽世界,技术支持会增加3000%的电话求助量(这很严重,希望他们永远都不工作…但我肯定赞赏他们所做的工作!)。基于这个原因,企业组织仍然依靠基于黑名单的策略来防止使用net * .exe,cmd.exe和powershell.exe等程序的运行。
为了演示的目的,我打算模拟一个企业组织使用AppLocker的黑名单方式限制程序运行。我的目标是使用AppLocker来尽可能多的阻止PowerShell并测试适当的措施来绕过黑名单限制。
我用Windows 7系统进行测试。我将执行以下操作尝试设置和保护我的测试机:
1. 启动应用程序身份验证服务
2. 通过哈希拒绝以下可执行文件并添加相应的可执行文件规则:
C:\windows\system32\WindowsPowerShellv1.0\powershell.exe C:\windows\system32\WindowsPowerShellv1.0\powershell_ise.exe C:\windows\Syswow64\WindowsPowerShellv1.0\powershell.exe C:\windows\Syswow64\WindowsPowerShellv1.0\powershell_ise.exe
3. 添加通过路径拒绝:* .ps1 *的脚本规则
4. 在DLL规则中启用“强制”(AppLocker->属性)
5. 添加通过哈希拒绝以下DLL的DLL规则:
· C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShellv1.0\Microsoft.PowerShell.Commands.Management.dll · C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShellv1.0\Microsoft.PowerShell.Commands.Utility.dll · C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShellv1.0\Microsoft.PowerShell.ConsoleHost.dll · C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShellv1.0\Microsoft.PowerShell.Security.dll · C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShellv1.0\System.Management.Automation.dll
6. 测试并确保以上配置工作已经生效!
绕过AppLocker锁定应用程序的解决办法
我最近了解了PowerShell攻击的世界,所以只会在这一方面提示一些东西。 我之前听到有人讨论如何绕过关于PowerShell的AppLocker规则的方法。 就我个人而言,我感谢harmj0y给予的支持并提示给我正确的研究方向。 我也知道许多想法和一些来自“darkoperator”的初步的研究发现以及其他几个讨论PowerShell攻击的社区。 感谢那些分享相关技术的人,为我铺平了道路。 如果你有更好的方法我非乐意听到!
PowerShell可以通过.NET框架和Windows公共语言接口(CLI)提供后端访问功能。开发人员非常喜欢这种可扩展性,网上存在着许多如何使用这些功能来创建实用程序来做有趣的系统广告之类的事情的示例代码。不过,很少有人意识到,相同的代码可以用于将PowerShell打包并作为绕过AppLocker限制的解决方法。
阅读这篇文章,了解如何在C#中调用PS脚本。
首先,我必须配置我的项目并添加引用自动化程序集:
1. RC引用 – >添加引用
2. 浏览并选择下面的文件路径:
C:\Program Files\Reference Assemblies\Microsoft Windows PowerShellv1.0\System.Management.Automation.dll
为了从资源加载PowerShell代码,我必须首先创建一个资源:
1. 打开Resources.resx
2. 添加字符串资源
3. 将字符串命名为“Script”
4. 将值设置为“Get-Process”或任何你想要执行的脚本
创建完项目后,我实例化我的Runspace并创建了将用于执行命令的管道(Pipeline)。
//Init stuff Runspace runspace = RunspaceFactory.CreateRunspace(); runspace.Open(); RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace); Pipeline pipeline = runspace.CreatePipeline();
接下来,从资源区段提取PowerShell脚本,并将其添加到管道中。 你也可以改变为从互联网读取PowerShell脚本或者加密的字符串等。在目标环境中,重要的是混淆或加密脚本以防止AV或HIPS查杀原始的脚本。 在磁盘上的脚本每时每刻都会被Read Teamer捕获…
//Add commands string script = Properties.Resources.ResourceManager.GetString("Script"); pipeline.Commands.AddScript(script);
要检索脚本中的输出,我将“Out-String”命令添加到管道中并抓取了返回对象。 使用string对象对这些对象进行迭代遍历以返回最终输出的字符串。
//Prep PS for string output and invoke pipeline.Commands.Add("Out-String"); Collection results = pipeline.Invoke(); runspace.Close(); //Convert records to strings StringBuilder stringBuilder = new StringBuilder(); foreach (PSObject obj in results) { stringBuilder.AppendLine(obj.ToString()); } Console.Write(stringBuilder.ToString());
编译这个可执行文件并把它放到测试环境中,将会带来惊人的结果,它运行成功了。 尽管运行着针对限制PowerShell执行的所有预防措施,可是我们的可执行文件依旧能够访问API并运行我们选择的任何脚本。 我主要将它与Veil-PowerView进行了测试。 20行的C#代码展示了一个相当基本的POC。 不过这个绕过方式有一些明显的缺点…
1. 在磁盘上写入了攻击脚本(尽管脚本可以从互联网获取) 2. 托管代码,.NET代码很容易被反编译 3. 如果环境配置的是白名单方式这种绕过方式将会失效
阻止恶意程序执行的解决方法
这太简单了…对.NET的严重依赖使我有信心有一个简单的方法来阻止恶意程序运行。 在我的测试环境中,我在Process Explorer和Process Monitor中花了一些时间挖掘我的恶意应用程序。 我确认自定义可执行文件正在加载.NET程序集以完成PowerShell执行。 用Microsoft的话来说,“程序集是.NET Framework的构建的一部分”。 本质上,程序集是构成CLI的库的一部分。 在大多数情况下,程序集存储在C:\WindowsAssembly的全局程序集缓存(GAC)中。 事实上,.NET会在运行时加载程序集,而不是在初始化应用程序时执行。 当我执行代码时,就可以观察到加载程序集的时机。 下面是我观察到的文件句柄示例:
·C:WindowsassemblyGAC_MSILMicrosoft.PowerShell.Commands.Diagnostics1.0.0.0__31bf3856ad364e35Microsoft.PowerShell.Commands.Diagnostics.dll ·C:WindowsassemblyGAC_MSILSystem.Management.Automation1.0.0.0__31bf3856ad364e35System.Management.Automation.dll
快速切回到AppLocker,我将所有来自GAC的PowerShell特定的程序集添加到了拒绝策略列表中,然后通过验证文件哈希进行加载阻断。 为了获得在AppLocker中被阻止的程序集DLL文件并允许explorer进程访问后端程序集库,我需要禁用“缓存查看器”功能。 如果你想使用拖拽式安装程序集,记得一定要确保重新启用这个功能。 注册表命令如下:
reg add HKLMSoftwareMicrosoftFusion /v DisableCacheViewer /t REG_DWORD /d 1
由于某种原因,程序集拒绝策略仍然无法有效的阻断我的恶意应用程序的执行。 起初我想这可能是因为DLL被隐藏在程序集中所导致的,但是在测试之后,结果证明并不是这样。 我想可能是其他程序集DLL被阻止了。 有关更多信息,请参阅后续部分! 我可以找到的唯一一个可以成功阻止.NET程序内嵌PS代码执行的DLL,对应的AppLocker DLL规则是:
C:WindowsMicrosoft.NETassemblyGAC_32System.Transactionsv4.0_4.0.0.0__b77a5c561934e089System.Transactions.dll
这个规则阻止了我的恶意脚本的执行,但是被阻止的DLL是负责所有事务类(也就是提供创建资源管理器的功能)的库。 这是一个不合理的阻止方式,因为许多合法的.NET应用程序都需要资源。 最后的结论就是:重命名或移动 PowerShell 程序集。
mkdir c:windowsassemblydisabled move c:windowsassemblyGAC_MSILMicrosoft.PowerShell.Commands.Management1.0.0.0__31bf3856ad364e35Microsoft.PowerShell.Commands.Management.dll c:windowsassemblydisabled
显然,这起作用了,它阻止了我的恶意应用程序的执行。不过在我看来,这是一个有限的解决方案,因为它不够灵活,配置时需要安装/卸载程序集。理想的方案是具有可配置的策略以允许某些用户使用该程序集或在某些情况下阻止标准用户的使用。
*关注一下*(下面的内容是本文发表后才添加的)
本文发表之后,最初,几个人通过twitter参与了讨论。 在进一步深入之前,我必须声明,最好的方案是基于白名单的策略。黑名单往往考虑的不够周全,而且很可能会被专门研究绕过方法的攻击者绕过。 这篇文章只是为了演示。 也就是说,我很少发现有公司使用任何类型的AppLocker策略。
非常感谢Lee Holmes(@Lee_Holmes)和Carlos Perez(@Carlos_Perez)后续在Twitter上的讨论。Lee Holmes深挖了一下,为什么我在DLL黑名单模式下无法成功获得PowerShell程序集。他测试了我的黑名单策略并结合使用AppLocker审计模式和Windows事件日志来检测哪些DLL被加载和阻止了。这肯定有助于缩小你的阻止列表范围。在测试了这个方法后,我可以保证它的确很有用。
要将.NET程序集(特别是PowerShell程序)列入黑名单,必须阻止与该程序集相关的所有DLL。这包括GAC_MSIL和NativeImages中的DLL(如果它们都存在的话)。要发现与PowerShell程序集相关的的DLL,可以在PowerShell中运行如下命令:
[PSObject] .Assembly.Location
在.NET程序集中还有几种不同的PowerShell依赖,所以请自己检查一下。使用这种方法,我就能够阻止.NET导入的程序集DLL的执行。