当前位置: 移动技术网 > IT编程>脚本编程>Shell > 如何防范PowerShell代码注入漏洞绕过受限语言模式

如何防范PowerShell代码注入漏洞绕过受限语言模式

2018年05月29日  | 移动技术网IT编程  | 我要评论

导语:受限语言模式是缓解powershell攻击的一种方式,能够阻止执行任意未签名的代码。

介绍

受限语言模式是缓解powershell攻击的一种方式,能够阻止执行任意未签名的代码。当device guard或者applocker处于强制模式时,它是最实际有效的强制安全措施,因为未被策略允许的任何脚本或者模块都位于受限语言模式下,这严重限制了攻击者执行未签名的代码。通过限制语言模式限制了add-type的调用。限制add-type明显是考虑到了它能编译并加载任意的c#代码到你的运行空间中去。

但策略允许的powershell代码运行在“full language”模式下,允许执行add-type。这样,微软签名的powershell代码就能调用add-type。不相信吗?运行下面的命令你就会发现我是正确的。

利用

现在想象如果以下的powershell模块代码(暂且被称为“vulnmodule”)是由microsoft签名的。

ls c:* -recurse -include '*.ps1', '*.psm1' |
 select-string -pattern 'add-type' |
 sort path -unique |
 % { get-authenticodesignature -filepath $_.path } |
 ? { $_.signercertificate.subject -match 'microsoft' }

那么有什么可以影响来自受限语言模式的add-type的输入呢?

让我们一起思考下吧:

1. add-type作为类型定义传递给一个全局变量。因为它是全局的,它可以被任何人访问,包括我们和攻击者。
2. 问题是,签名的代码先于调用add-type就定义了全局变量,因此如果我们使用自定义的恶意c#代码,这将会被合法的代码覆盖。

3. 你知道能用set-variable cmdlet来设置变量只读吗?你知道我现在在想什么了吧?

武器化

好的,为了从受限语言模式注入代码到add-type,攻击者需要将它们的恶意代码定义为只读变量,从而设置全局“source”变量来拒绝签名的代码。这是一个武器化的概念证明:

  $global:source = @'
  public class test {
    public static string printstring(string inputstring) {
      return inputstring;
    }
  }'@
add-type -typedefinition $global:source

简要说明下add-type注入缺陷。受限语言模式的一个限制是你不能调用非白名单类的.net方法,但有两个例外:属性(getter方法)和tostring方法。在上面的poc中,我选择了实现一个静态的tostring方法,因为tostring允许传递参数(getter不行)。我的类也是静态的,因为.net类的白名单只在new-object实例化对象时适用。

那么上面的漏洞代码是否听起来不切实际呢?你可以这么认为,但是microsoft.powershell.odatautils 模块中的microsoft.powershell.odatautils也有这个漏洞。微软在 cve-2017-0215, cve-2017-0216, cve-2017-0219中修复了它。说实话,我不太记得了。matt nelson 和我都报告了这些注入bug。

缓解攻击

尽管微软在推动解决这个漏洞,我们有什么可以做的呢?

有个关于umci绕过二进制的有效的黑名单规则是文件名规则,其能基于pe文件中版本信息资源中的原始文件名来阻止程序执行。powershell很明显不是个pe文件,它是文本文件,因此文件名规则不适用。但是,你可以通过使用哈希规则强制阻止有漏洞的脚本。okay…要是相同脚本有不止一个漏洞呢?目前为止你只阻止一个哈希。你开始注意这个问题了吗?为了有效的阻止之前所有有漏洞的版本的脚本,你必须知道所有有漏洞的版本的哈希。微软意识到了问题并尽最大努力来扫描所有之前发布的有漏洞脚本,且收集哈希将他们整合到了黑名单中。

通过他们的哈希阻止所有版本的有漏洞的脚本有一定挑战性,但能一定程度上阻止攻击。这就是为什么一直迫切需要只允许powershell 5的执行并要开启scriptblock日志记录。lee holmes 有篇关于如何有效的阻止老版本的powershell的博文。

另一种方式是系统中大部分脚本和二进制都是catalog和authenticode签名的。catalog签名不是意味着脚本有内嵌的authenticode签名,而是它的哈希存储在微软签名的catalog文件中。因此当微软更新时,老版本的哈希将会过期,将不再是被签名的了。现在,一个攻击者也能将老的签名的catalog文件插入到catalog存储中。你不得不提权执行操作,关于这个,有很多方法可以绕过device guard umci。作为一个搜索有漏洞脚本的研究员,首先要寻找具有内嵌authenticode签名的有漏洞脚本(有字符串“sig # begin signature block”的提示)。matt nelson说这种bypass脚本存在。

报告

如果你找到了一种绕过,请将它上报给secure@microsoft.com ,你将得到一个cve。powershell团队积极解决注入缺陷,但是他们也主动解决用于影响代码执行的一些方式。

总结

尽管受限语言模式能有效的阻止未签名代码的执行,powershell和它的签名过的模块或脚本还是有很多攻击面。我鼓励每个人都来寻找更多的注入缺陷,上报他们,通过官方的msrc获得荣誉,并使得powershell生态变得更加安全。同时希望,powershell的代码作者要自我检视。

现在我解释了所有的内容,但是因为设计缺陷允许利用竞争条件,所以调用add-type还是有注入的漏洞。我希望能继续阐述这些问题,且希望微软将考虑解决这个基础问题。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网