在微软,我们投入大量时间和精力管理世界级的云服务和难以置信的大型企业网络。安全性对所有这些都是至关重要的,所以让您吃惊的是,我们还投入了大量的时间和精力试图突破这些服务。这被称为“红色团队”(Red Teaming)——由高度专业化的安全专家组成,让他们扮演复杂对手的角色。
在Windows的最后几个版本中,我们一直在努力使这个平台对管理员、开发人员和高级用户都更加强大。唯一的问题是——红队正在迎头赶上。
本文假设
在本文档中,假设攻击者已经通过恶意仿冒电子邮件、自定义网站实现中的安全漏洞或类似攻击危害(破坏)了系统。
当这些安全缺陷出现在软件中时,就会被发现并修补。但我们总是假设攻击者会找到某种方法进入-即使只是通过用户被诱骗在其计算机上安装恶意应用程序。
与任何职业一样,攻击者的工作满意度(由受攻击公司出资或其他方式出资)在影响攻击者行为方面起着重要作用。毕竟,谁想用一个优雅和强大的脚本语言(如PuthS壳)来实现一个系统的折衷,使用易出错和难以编写的C++程序?
在本文档中,我们将讨论在Windows10中的脚本安全和保护方面取得的一些重要进展。
反恶意软件引擎的脚本透明性
反恶意软件引擎通常将大部分注意力集中在应用程序(或系统)打开的文件上。一个新的Windows 10功能,反恶意软件扫描接口(AMSI),让应用程序现在成为恶意软件防御的积极参与者。应用程序现在可以请求对任何内容进行反恶意软件评估,而不仅仅是磁盘上的文件。
鉴于power shell的shell和脚本语言令人难以置信的强大功能,我们在PowerShell的透明性方面取得了重大进展:可靠的誊写、深度脚本块日志记录、使用加密消息语法(CMS)标准的加密和解密cmdlet、面向开发人员的安全代码生成api,对于实现AppLocker策略的系统,“受约束的PowerShell”。
受保护的事件日志记录
当您增加机器上的日志记录时,一个问题是您记录的信息可能包含敏感数据。如果攻击者破坏了该计算机,则事件日志中的此敏感信息可能是凭据、机密系统等的金矿。为了帮助解决这个问题,我们添加了受保护的事件日志记录,它允许参与应用程序在将敏感数据写入事件日志时对其进行加密。一旦将这些日志移到更安全和集中的日志收集器中,就可以对它们进行解密和处理。
在Windows 10中,反恶意软件、安全和身份、PowerShell、VBScript和JScript团队协作,允许应用程序成为恶意软件防御的积极参与者。为此,我们引入了一种全新的方法来帮助保护客户免受基于动态脚本的恶意软件和非传统攻击途径的攻击。
这叫做AMSI——反恶意软件扫描接口。
反病毒引擎通常将大部分注意力集中在系统打开的文件上。当文件被打开时,他们会扫描其内容,并对其恶意意图做出决定。这个决定来自于对文件内容运行签名——试图识别恶意意图模式的签名。
在脚本语言方面,一个独特的挑战是它们支持动态脚本内容的求值和调用。虽然文件本身可能不是恶意的,但它可能会从internet上提取恶意代码。
这一挑战的另一个独特之处是对交互式内容的调用。具有足够强大的脚本语言的交互式shell可能会带来挑战,因为它们的输入根本不是基于文件的:
在Windows 10中,反恶意软件扫描界面有助于解决此问题。
反恶意软件扫描接口(AMSI)是一种通用接口标准,允许应用程序和服务与计算机上的任何反恶意软件产品集成。他们可以请求对任何可能是恶意的内容进行反恶意软件分析,并根据响应采取行动。
在Windows10中,内置脚本引擎(PowerShell、VBScript和JScript)现在请求对所有动态内容(包括在命令行手动键入的内容和从远程源下载的内容)进行反恶意软件分析。
有了这种支持,现在可以在模糊恶意软件中进行检测,而无需反恶意软件供应商编写易于出错的脚本语言模拟:
当你采取假设破坏的心态时,你必须假设攻击者已经在你的系统上。但接下来你会问:他们做了什么?它们连接到什么系统?是否调用了任何动态代码,它是什么?
PowerShell版本5(包括在Windows 10中,也可通过Windows管理框架用于早期的操作系统)在确保Blue团队拥有回答这些问题所需的信息方面取得了重大进展。
Windows 8.1上的PowerShell v4的KB 3000850还包括许多这些功能,如下所示。
PowerShell版本5构建在PowerShell版本4(及以下版本)提供的已经很强的基础架构上:转录、模块日志记录等。有关这些环境中的PowerShell安全最佳实践的更多信息,请参阅http://blogs.msdn.com/b/PowerShell/archive/2013/12/16/PowerShell-Security-Best-Practices.aspx。此外,FireEye还发布了一份关于调查PowerShell攻击的优秀文档:http://www.FireEye.com/resources/pdfs/FireEye-lazanciyan-investiging-PowerShell-Attacks.pdf。本文档详细介绍了主动和被动技术。
获取PowerShell会话中发生的事件摘要的最快方法之一是查看键入的人的肩膀。你看到他们的命令,这些命令的输出,一切都很好。或者不是,但至少你会知道。
PowerShell版本4及之前的版本包括通过Start Transcript命令支持肩上转录。然而,设置PowerShell会话的无处不在的转录是复杂且容易出错的。您需要在每个系统的系统启动配置文件中包含该命令,还需要向试图禁用转录的标记攻击者添加大量审核。
第二个问题是,只有在交互式PowerShell控制台中才支持转录。不支持远程处理会话的转录,也不支持在非控制台主机(如PowerShell ISE)中进行转录。
在PowerShell版本5和KB 3000850中,Start Transcript现在在启动一个脚本时会发出结构化对象(Path属性很有用),并在其头中添加了更多有用的信息:
文件名称由生成脚本誊写的计算机名称,防止脚本收集的“hash breaker”和生成时间组成。
虽然PowerShell v4及以下版本允许您控制输出路径,但随后您被迫自行适当地随机选择脚本文件名。 为了改善这种情况,我们已将–OutputDirectory参数添加到Start-Transcript中。
在标题内容中,“用户名”和“运行方式用户”通常是相同的。 如果您在受限的PowerShell远程处理端点(即:PowerShell有限管理)上启用了模拟,则“用户名”字段表示已连接的用户,而“运行方式用户”则表示要冒充的帐户。
在标题内容中,“用户名”和“运行方式用户”通常是相同的。如果您已在受约束的PowerShell远程处理端点上启用了模拟。,用户名”字段表示连接的用户,而“运行方式用户”字段表示要模拟的帐户。
当涉及到抄录内容时,PowerShell现在会誊写直接操作控制台缓冲区的控制台命令,并且现在可以在诸如PowerShell ISE之类的主机中启用。
如果要更直接地将命令与其输出相关联以进行后续的分析,请使用–IncludeInvocationHeader参数。 这会为每个调用的命令添加一个附加头:
开启自动誊写功能,需要在组策略中进行设置。
Windows Components -> Administrative Templates -> Windows PowerShell.
为了更好的实现自动化,设置会存储在下面的注册表中:HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription.
下面PowerShell函数是你能够开启或者关闭系统级脚本誊写功能。
在系统级别的脚本誊写功能启用后,没有接口的主机模拟脚本也会被誊写,例如以下示例C#程序。
当你运行上面脚本的时候,会得到如下记录:
当OutputDirectory选项被设置时,你能够将收集的脚本存储到一个路径下以供后续分析。如果你执行了这个策略,确保对用户访问权限进行限制,不要使每一个用户都能够访问收集脚本的文件。下面的PowerShell脚本创建了一个名称为“Transcripts”的SMB共享,这样做是最佳实践。
PowerShell脚本块是PowerShell执行的基本单元。脚本块可以是PowerShell交互窗口的一个命令行,也可以是PowerShell –Command<…>形式的命令行,也可以被包裹在一个函数、脚本和流程中。
作为over-the-shoulder style transcription的补充,PowerShell v5和KB 3000850引入了深度脚本块记录功能。当你开启脚本块记录功能的时候,PowerShell记录其产生的所以脚本块。如果一个脚本动态的生成指令(例如:$command = "'Hello World'"; Invoke-Expression $command)PowerShell将记录调用的脚本块。这提供了对系统上基于脚本活动的完整了解,这使我们能够监测包括利用动态代码生成来逃避检测的脚本或应用程序。
深度脚本块日志记录适用于承载PowerShell引擎的任何应用程序-命令行外壳,ISE或自定义主机。
通过组策略设置深度脚本块记录功能位置如下:
Windows Components -> Administrative Templates -> Windows PowerShell.
自动化执行这个策略需要设置注册表项:
HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging.
默认设置下,PowerShell仅在首次使用脚本块时记录日志。如果你选择”Log script block invocation start / stop events”, 每当脚本块被调用时,PowerShell也会记录启动和停止事件。 后一种设置会产生大量事件,因此应谨慎启用。
通过以下PowerShell功能,您可以启用和禁用系统范围的脚本块日志记录策略。
大多数公司仅在为时已晚之后才意识到需要启用脚本块日志记录。 为了在这种情况下提供一些帮助,当脚本块包含恶意脚本经常使用的内容时,PowerShell会自动记录它们。 此自动脚本块日志记录并非旨在替代防病毒或完整脚本块日志记录,仅用作最后的记录。
关闭脚本块记录功能,设置“Turn on Script Block Logging”为” Disabled”。或者设置EnableScriptBlockLogging注册表项为0。
当脚本块记录功能开启时,PowerShell事件将记录在Microsoft-Windows-PowerShell/Operational日志中:
此表见文件附件
消息中嵌入的文本是编译的脚本块的文本。 ScriptBlock ID是在脚本块有效期内保留的GUID。
注意:如果某些命令是通过PowerShell的动态关键字机制或重写函数生成的,则某些脚本块文本(例如:Get-ChildItem)可能无法真正代表其基础功能。 对于这两种情况,都将记录原始的动态关键字定义(或恶意功能定义)。
启用脚本块调用日志记录后,PowerShell还将写入开始和结束事件标记:
此表见文件附件
该ID是代表脚本块的GUID(可以与事件ID 4104相关联),而Runspace ID代表运行该脚本块的运行空间。
假定它代表系统上调用的所有PowerShell脚本的内容,则这些事件可能包含敏感数据。 要限制启用脚本块日志记录时的信息泄露风险,请参阅受保护事件日志记录。
调用消息中的百分号表示结构化的ETW属性, 在用消息文本中的实际值替换它们。一种更可靠的访问方法是使用Get-WinEvent cmdlet检索消息,然后使用消息的Properties数组。
这是此功能如何帮助解开恶意的加密和混淆脚本尝试的示例:
运行此命令将生成以下日志条目:
如果脚本块的长度超过了单个事件中ETW可以容纳的长度,则Windows PowerShell会将脚本分为多个部分。 这是从脚本的日志消息重新组合脚本的示例代码:
与所有保留缓冲区有限的日志系统(即ETW日志)一样,针对此基础架构的一种攻击是使用虚假事件来充斥日志以隐藏早期证据。 为了保护自己免受这种攻击,请确保您设置了某种形式的事件日志收集。
PowerShell版本5和KB 3000850引入了对使用加密消息语法(CMS)格式的内容保护的支持。 这些cmdlet支持使用IETF标准格式对内容进行加密和解密,以加密保护信息,如RFC5652所述。
CMS加密标准实现了公共密钥加密,其中用于加密内容的密钥(公共密钥)和用于解密内容的密钥(私有密钥)不同。
您的公钥可以广泛共享,并且不是敏感数据。 如果使用此公共密钥加密了任何内容,则只有您的私有密钥可以解密它。 有关公钥密码术的更多信息,请参见:http://en.wikipedia.org/wiki/Public-key_cryptography。
要在Windows PowerShell中被识别,加密证书需要一个唯一密钥标识符(EKU)才能将它们标识为数据加密证书(例如“代码签名”,“加密邮件”的标识符)。
这是创建适用于文档加密的证书的示例:
(将“主题”中的文本更改为您的姓名,电子邮件或其他标识符),然后放入文件中(即:DocumentEncryption.inf):
执行:
然后你会看到加密内容:
CMSMessageRecipient类型的任何参数都支持以下格式的标识符:
•实际证书(从证书提供者处检索)
•包含证书的文件的路径
•包含证书的目录的路径
•证书的指纹(用于在证书存储中查找)
•证书的主题名称(用于在证书存储中查找)
要在证书提供者中查看文档加密证书,可以将-DocumentEncryptionCert动态参数用于Get-ChildItem(dir):
58 [Cert:\currentuser\my]
>> dir -DocumentEncryptionCert
由于CMS格式是IETF标准,因此PowerShell支持对其他符合标准的工具生成的内容进行解密,并且它生成的内容可以由其他符合标准的工具解密。
支持CMS消息格式的较流行的实现之一是OpenSSL库和命令行工具链。 与OpenSSL库交换数据时的主要挑战来自OpenSSL假设,即内容以P7M格式包含在电子邮件正文中。 幸运的是,这些基于文本的标题相对容易添加和删除。
以下PowerShell命令演示了如何使用OpenSSL和PowerShell加密和解密其他应用程序生成的内容。
当你编写的代码的输入能够被攻击者控制的时候,代码注入漏洞是所有漏洞中危害最大的。一个很好的例子就是你在受约束的PowerShell运行空间中为使用者提供的函数。如果攻击能利用其中一个函数进行代码注入,那么他们可以像执行代码本身那样执行恶意代码,不受运行空间的限制。
几乎每种语言都可能受到代码注入漏洞的攻击。 在SQL中,这称为“ SQL注入”。 在网站中,这称为“跨站点脚本”。 在CGI应用程序中,shell脚本或调用系统命令的工具-称为“命令注入”。
在PowerShell中,代码注入漏洞的最常见来源来自在提交给Invoke-Expression命令的字符串中包括攻击者控制的输入。 例如:
如果$Path包含如下内容“; Write-Host Pwnd”,攻击者能够执行Write-Host cmdlet(或者更糟糕)。
几乎应该避免使用Invoke-Expression cmdlet,因为PowerShell(与其他语言一样)具有许多功能,可以更安全地代替它。
如果确实需要生成PowerShell脚本,则PowerShell版本5和KB 3000850引入了API以支持安全生成可能包含攻击者输入的脚本。
如果要将攻击者控制的输入放在字符串中(比如:用于命令参数),请确保将其放在单引号中。 然后,对内容本身使用EscapeSingleQuotedStringContentAPI函数。 这样可以确保攻击者输入中的单引号被正确地转义。
比如:
安全转义还包含在块注释,格式字符串或变量名称中的内容。
当系统敏感时,限制攻击可能造成的破坏的最有效方法之一就是降低攻击的能力。Windows的安全控制机制有多种形式,能够创建逐层的保护机制。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-12-27 18:35
被dodohit编辑
,原因: