当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] PowerShell 日志记录:记录和审核所有事情

作者:精品下载站 日期:2024-12-14 13:02:32 浏览:14 分类:玩电脑

PowerShell 日志记录:记录和审核所有事情


各种技能水平的 IT 专业人员每天都在使用 PowerShell 来执行各种任务。从系统和数据库管理自动化到帮助台故障排除、PowerShell 日志记录和审计,一切都可以发挥作用。所有这些活动都会给组织带来安全问题。您可能会发现自己会问:

  • 会话期间运行的命令是什么?
  • 是否从不安全的本地或网络源执行未经批准的脚本?
  • 使用哪些模块可能会造成潜在危害?

在本文中,您将了解可用于 PowerShell 日志记录和审核的选项。读完本文后,您将具备足够的知识来开始记录和审核网络上发生的所有 PowerShell 操作。如果您对此感兴趣,请继续阅读!

先决条件

本文将是一个实践教程。如果您想跟随,您将需要一些东西:

  • 基本熟悉 Powershell
  • 了解如何访问和编辑注册表项
  • 基本的组策略知识

本文不涉及非 Windows PowerShell 日志记录,但您可以在此处阅读有关该主题的信息。

所有示例均使用 PowerShell 5.1、Windows Server 2016 和 Windows Server 2019。

使用成绩单进行记录

互联网上有很多关于 PowerShell 不安全的说法。这与事实相差甚远。 PowerShell 提供了允许 SysOps 和 SecOps 等审核和记录 PowerShell 活动的机制。

最简单的 PowerShell 日志记录技术之一是脚本。脚本是保存当前主持人会话的好方法。此功能自 PowerShell 1.0 起就作为 Microsoft.PowerShell.Host 模块的一部分出现在 PowerShell 中。

通过脚本,您可以获得主机会话期间生成的所有命令和输出。关闭主机会话,转录将停止。

如何使用注册表打开成绩单

虽然记录可以通过组策略启用,但您也可以通过编辑 Windows 注册表来启用它们。例如,在 Windows Server 2016 上,注册表项位于 HKLM:\SOFTWARE\WOW6432Node\Policies\Microsoft\Windows\PowerShell\Transcription,并且可以包含如下所示的值:

[玩转系统] PowerShell 日志记录:记录和审核所有事情

如果您不想打开regedit并手动编辑注册表,下面您将找到一个 PowerShell 函数,它将为您完成所有艰苦的工作。此功能将为您设置所有适当的注册表值。

function Enable-PSTranscriptionLogging {
	param(
		[Parameter(Mandatory)]
		[string]$OutputDirectory
	)

     # Registry path
     $basePath = 'HKLM:\SOFTWARE\WOW6432Node\Policies\Microsoft\Windows\PowerShell\Transcription'

     # Create the key if it does not exist
     if(-not (Test-Path $basePath))
     {
         $null = New-Item $basePath -Force

         # Create the correct properties
         New-ItemProperty $basePath -Name "EnableInvocationHeader" -PropertyType Dword
         New-ItemProperty $basePath -Name "EnableTranscripting" -PropertyType Dword
         New-ItemProperty $basePath -Name "OutputDirectory" -PropertyType String
     }

     # These can be enabled (1) or disabled (0) by changing the value
     Set-ItemProperty $basePath -Name "EnableInvocationHeader" -Value "1"
     Set-ItemProperty $basePath -Name "EnableTranscripting" -Value "1"
     Set-ItemProperty $basePath -Name "OutputDirectory" -Value $OutputDirectory

}

启动和停止转录

开始使用转录的最简单方法是仅使用两个 cmdlet; Start-TranscriptStop-Transcript。这两个简单的命令是开始和停止记录 PowerShell 控制台活动的最简单方法。

要开始记录主机会话期间使用的命令的记录或日志,请在终端中键入以下代码,然后按 Enter

# Works with Windows PowerShell 1.0 to 5.1 and PowerShell 7
Start-Transcript

现在输入通用命令以在会话中生成一些详细输出。使用下面的代码获取当前日期时间:

Get-Date

您应该有类似的输出,如下面的屏幕截图所示:

[玩转系统] PowerShell 日志记录:记录和审核所有事情

此时,该命令的输出已保存到您在注册表中定义它的文本文件中。要结束转录,请关闭主机会话或使用 Stop-Transcript cmdlet。

使用 Stop-Transcript cmdlet 显示意图。您还可以通过简单地关闭 PowerShell 控制台来“停止”转录。

Get-Date cmdlet 和输出在后台记录到纯文本文件中,包括 Stop-Transcript cmdlet。

默认情况下,记录保存在 %userprofile%\Documents 文件夹中,并命名为 PowerShell_transcript.[hostname].[random_characters].[timestamp].txt 。当集中存储记录时,此命名约定非常有用,因为它可以防止意外覆盖并使搜索 PowerShell 日志变得更加容易。

PowerShell 脚本剖析

每个成绩单都有一定的“模式”或结构方式。查看使用默认参数保存的 PowerShell 转录文件。您可以从成绩单中看到所有常见的属性。

使用默认参数创建的每个记录将包括主机会话信息、开始时间、用户名、PowerShell 和操作系统版本以及计算机名称。根据这些有用的信息,您可以看到运行的命令、生成的输出以及最终命令 Stop-Transcript,该命令结束转录并将最终时间戳写入转录文件。

[玩转系统] PowerShell 日志记录:记录和审核所有事情

使用 Start-Transcript cmdlet 时,不存在仅使用默认命名约定或路径的硬性限制。可以使用任何名称将记录保存到任何可写位置。

现在就试试。使用 -Path 参数,如下例所示。此代码片段将在 C:\My_PowerShell_Transcripts 处创建一个文件夹,并立即开始在 Get-Date-Transcript.txt 文件中记录记录。

$null = New-Item -Path C:\My_PowerShell_Transcripts -ItemType Directory -ErrorAction Ignore
Start-Transcript -Path 'C:\My_PowerShell_Transcripts\Get-Date-Transcript.txt'

运行一些命令后,再次停止转录 (Stop-Transcript),然后导航到上例中指定的目录。您现在应该看到您的成绩单,如下所示:

[玩转系统] PowerShell 日志记录:记录和审核所有事情

将参数添加到Start-Transcript

之前,您了解了如何使用不带参数的 Start-Transcript,但此 cmdlet 还具有一些其他方便的参数来自定义行为,例如:

  • NoClobber - 防止意外覆盖
  • Append - 允许 PowerShell 写入现有的转录文件
  • InclusionInvocationHeader - 添加每个命令运行的精确时间戳。
  • UseMinimalHeader - v6.2 参数,用于删除默认包含的主机会话详细信息。

您可以在此处阅读文档以获取可选参数的完整列表。

成绩单的局限性

脚本很方便,但有时您无法看到脚本中正在发生的端到端活动。让我们看一下名为 Get-Date.ps1 的示例脚本。

Get-Date.ps1:

  • 使用 Get-Date cmdlet 返回当前日期/时间
  • 使用 Test-NetConnection cmdlet 将网络连接测试结果打印到控制台
  • 定义一个数字数组
  • 循环遍历数组中的每个数字,启动一个不产生任何输出的命令并打开一个新的 PowerShell 进程。
# Run Get-Date as a script

# Produce date to host session
Get-Date

# Test network with some output to host session
Test-NetConnection localhost

#uh-oh
$numbers = 1..10

# What's this?
Foreach ($number in $numbers) {

    # Doing something that doesn't produce console output
    [System.Console]::Beep(6000,500)

    Start-Process pwsh.exe

    # host session runs this but it produces no output
    # and is not logged in the transcript!
}

查看刚刚创建的脚本,除了 Get-DateTest-NetConnection 之外,Get-Date.ps1 脚本并没有明显执行额外的操作。 :

[玩转系统] PowerShell 日志记录:记录和审核所有事情

这种 PowerShell 日志记录方法的缺点是它仅适用于当前用户的主机会话。如果执行的脚本没有向主机会话产生任何输出,则不会记录该脚本所执行的操作。脚本虽然提供了一些 PowerShell 日志记录功能,但绝不意味着封装所有 PowerShell 脚本活动。

PowerShell 脚本块日志记录可以解决此问题,也是下一节的主题。

脚本块日志记录

启用后,脚本块日志记录将记录 PowerShell 所做的一切。脚本块日志记录是使用组策略或直接编辑 Windows 注册表来实现的。 Windows 10 添加了名为“受保护事件日志记录”的新功能,使您能够不记录个人身份信息 (PII) 等敏感信息或凭据等其他敏感数据。受保护的事件日志记录超出了本文的范围,但您可以在此处阅读有关它的更多信息。

直接编辑注册表对于独立系统或工作组设置来说是一个很好的解决方案。如果您可以使用组策略,请在其中配置脚本块日志记录和受保护的事件日志记录。

使用 Windows 注册表启用脚本块日志记录

要使用 Windows 注册表启用脚本块日志记录,请将以下函数复制到 PowerShell 会话中,然后按 Enter

function Enable-PSScriptBlockLogging
 {
 # Registry key $basePath = 'HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging' 

# Create the key if it does not exist if(-not (Test-Path $basePath)) 

{     

$null = New-Item $basePath -Force     

# Create the correct properties      New-ItemProperty $basePath -Name "EnableScriptBlockLogging" -PropertyType Dword 

} 

# These can be enabled (1) or disabled (0) by changing the value Set-ItemProperty $basePath -Name "EnableScriptBlockLogging" -Value "1"
 }

现在像运行普通 cmdlet 一样运行该函数,输入函数名称并按 Enter

Enable-PSScriptBlockLogging

脚本块日志记录已启用。现在我们来测试一下。尝试运行一些 cmdlet 或一些脚本。完成此操作后,使用以下代码检查脚本块日志记录事件:

# Viewing just the message which shows scripts, cmdlets run
Get-WinEvent Microsoft-Windows-PowerShell/Operational -MaxEvents 4 |
	Where-Object Id -eq 4104 | Select-Object -ExpandProperty Message

下面是您的输出的示例。根据您运行的命令或脚本,您可能会看到更多信息。在此屏幕截图中,您可以看到我运行的脚本以及用于查看日志条目的上述命令:

[玩转系统] PowerShell 日志记录:记录和审核所有事情

您仍然可以使用传统的 Windows 事件查看器并导航到应用程序和服务日志 > Microsoft > PowerShell > 操作来查看和审核此信息。以下是日志如何显示在 Windows 事件查看器中的示例:

[玩转系统] PowerShell 日志记录:记录和审核所有事情

上面的示例来自于系统更改,该更改创建了一组错误的注册表项,从而导致意外结果。幸运的是 ScriptBlock 日志记录已提前打开。该问题可追溯到某些运行的代码中的命名问题。

如果此信息将用于审计目的,那么最好有一个集中的日志收集点或 SIEM。

现在您已经了解了 PowerShell 在系统上处理的内容,是时候在下一节中审核和记录 PowerShell 在处理命令和脚本期间使用的模块了。

模块日志记录

当您需要审核主机上使用的特定 PowerShell 模块时,模块日志记录就是答案。启用模块日志记录的方式与允许脚本块日志记录的方式大致相同。

模块日志记录将生成比 ScriptBlock 日志记录多得多的事件。您需要考虑其影响并制定使用策略。

使用 Windows 注册表启用模块日志记录

并非每个环境都有可用的组策略。那么,如果您需要审核和记录 PowerShell 模块的使用情况,在这些环境中该怎么办?您使用 Windows 注册表!

要使用 Windows 注册表启用模块日志记录,请使用以下 PowerShell 函数:

# This function checks for the correct registry path and creates it
# if it does not exist, then enables it.
function Enable-PSModuleLogging
{

    # Registry path
    $basePath = 'HKLM:\SOFTWARE\WOW6432Node\Policies\Microsoft\Windows\PowerShell\ModuleLogging'
    
    # Create the key if it does not exist
    if(-not (Test-Path $basePath))
    {

        $null = New-Item $basePath -Force
        # Create the correct properties
        New-ItemProperty $basePath -Name "EnableModuleLogging" -PropertyType Dword

    }

    # These can be enabled (1) or disabled (0) by changing the value
    Set-ItemProperty $basePath -Name "EnableModuleLogging" -Value "1"

}

接下来,运行 PowerShell 函数:

Enable-PSModuleLogging

启用模块日志记录后,不会自动监视模块。您必须指定要记录哪些模块。有几种方法可以做到这一点。临时方法是使用管道执行详细信息属性和 Windows 注册表或组策略来实现更永久的方案。

您可以对特定模块或所有模块执行此操作。不建议只监控特定模块。

要使用 PowerShell 在单个会话中记录模块使用情况,您必须首先导入要审核的模块。然后,使用成员属性 LogPipelineExecutionDetails,将值设置为 $True。默认情况下,所有模块的此属性均为 $False

例如,假设您要记录模块 VMware.PowerCLI。您可以通过输入以下代码并按 Enter 来完成此操作:

# Assuming you have already imported a module
(Get-Module -Name VMware.PowerCLI).LogPipelineExecutionDetails = $true

运行上述命令后,每次在 PowerShell 中调用 VMware.PowerCLI 模块时,都会创建一个日志条目。但该方法仅对当前会话有效。关闭 PowerShell 后,日志记录将停止,直到您再次启动为止。

管道执行详细信息可以在 Windows PowerShell 事件日志中找到,事件 ID 800

使用 Windows 事件查看器查看日志时,日志如下所示:

[玩转系统] PowerShell 日志记录:记录和审核所有事情

要使用 PowerShell 查看这些日志条目,您可以运行以下代码:

Get-EventLog 'Windows PowerShell' -EntryType Information -InstanceId 800

如果您正在记录所有 PowerShell 模块,您将看到很多条目。您可以根据自己的喜好过滤它们。但是,这超出了本文的范围。

如果您希望始终为所有用户记录所有模块,那么您需要再次编辑 Windows 注册表,以将新的键值添加到您在本节前面创建的模块日志记录键中。

要为 ModuleNames 添加新的注册表项值,请使用下面的 PowerShell 函数:

# This function creates another key value to enable logging
# for all modules
Function Enable-AllModuleLogging
{
    # Registry Path     $basePath = 'HKLM:\SOFTWARE\WOW6432Node\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames' 
    
    # Create the key if it does not exist
    if(-not (Test-Path $basePath))
    {
	$null = New-Item $basePath -Force
    }
    # Set the key value to log all modules
    Set-ItemProperty $basePath -Name "*" -Value "*"
}

Enter 后,您将运行该函数,就像本节前面所做的那样:

Enable-AllModuleLogging

再次按 Enter,现在每次使用时都会记录所有 PowerShell 模块。

使用组策略启用日志记录和脚本

如果您选择不编辑 Windows 注册表,则不必编辑。如果您有可以使用组策略的环境,则使用以下策略对象来实现日志记录和审核可能会更容易。

首先打开组策略管理控制台并创建一个新的组策略对象 (GPO)。然后按如下方式编辑策略:

  1. 导航到计算机配置 > 管理模板 > Windows 组件 > Windows PowerShell。您应该看到与以下示例所示相同的设置:

[玩转系统] PowerShell 日志记录:记录和审核所有事情

2. 通过更改以下设置的状态来启用您的选择:

[玩转系统] PowerShell 日志记录:记录和审核所有事情

  • 打开模块日志记录

请务必使用星号 (*) 作为值来启用所有模块的日志记录。或者,您也可以按名称列出特定模块。

[玩转系统] PowerShell 日志记录:记录和审核所有事情

  • 打开成绩单

[玩转系统] PowerShell 日志记录:记录和审核所有事情

3. 将新 GPO 链接到包含要监视或审核的计算机帐户的组织单位 (OU)。

请记住重新启动计算机,此策略也适用。

这就是开始使用组策略审核和记录 PowerShell 环境所需要做的全部工作。

结论

有了这些新知识,您就可以通过 PowerShell 管理提高安全性。 PowerShell 日志记录和审核功能使得使用 PowerShell 对于试图做坏事的坏人来说是一个非常糟糕的选择。本文讨论的方法使您能够掌握 PowerShell 日志记录和审核的艺术,使您成为更好的 SecOps 或 SysOps 专业人士。您已经学习了如何使用 Windows 注册表、组策略以及通过 PowerShell 本身创建脚本、记录脚本块执行和模块详细信息。我们鼓励您浏览下面的其他资源链接,以进一步了解您的 PowerShell 日志记录和审核知识。现在继续,通过记录和记录所有 PowerShell 内容来强化您的 PowerShell 环境!

其他资源

开始-成绩单

停止转录

启用脚本块日志记录

about_Logging-Windows

about_EventLogs

新物品

新项目属性

设置项目属性

about_Group_Policy_Settings-PowerShell

创建组策略对象

组策略到注册表参考

威胁研究 - 通过 PowerShell 日志记录提高可见性 (FireEye)

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯