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

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

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

如何使用 PowerShell 跟踪重要的 Windows 安全事件


许多组织依靠 Microsoft 技术来完成工作。与此同时,威胁行为者可以利用 Windows 等操作系统。幸运的是,Windows 会记录操作系统安全事件来帮助您追踪此行为。

Windows 产生的安全事件是事件响应过程中的关键资源。 Microsoft 的 Windows 事件查看器等工具为您提供了查看捕获的事件所需的访问权限,但通过手动滚动拥挤的日志来检测异常是不现实的。

在本文中,您将了解如何通过了解审核策略、Windows 事件日志以及使用 PowerShell 分析安全事件来追踪 Windows 中潜在的安全漏洞。

先决条件

本文旨在传达教您如何使用 PowerShell 分析 Windows 安全事件的信息。如果您想跟随任何演示,您将需要:

  • Windows 10+ PC - 此 PC 将用于生成和跟踪事件日志中的潜在安全事件。本教程将使用 Windows PowerShell 5.1。
  • Windows PC 上的管理员权限
  • PowerShell 代码编辑器,例如 PowerShell ISE 或 Visual Studio (VS) Code。

Windows 存储安全事件的位置

当在 Windows 操作系统上执行某项操作时,Windows 会将该操作作为一个事件记录在一个或多个事件日志中。默认情况下,Windows 事件日志存储在文件系统的 %SystemRoot%\system32\winevt\logs 目录中。可以通过修改相应事件日志的 EventLog 注册表子项来更改此位置。

如果您想查看系统上最重要的事件日志的存储位置(应用程序、安全性和系统),请将以下代码复制并粘贴到 PowerShell 控制台中或将其另存为脚本。

要访问安全日志文件的存储位置,您需要以管理员身份运行代码。

#Present application, security, and system logs in an array.
 $arrLogs = @(
     "Application"
     "Security"
     "System"
 )
 #Use the ForEach-Object cmdlet to target each respective log with the Get-ItemProperty cmdlet.
 $arrLogs | ForEach-Object {
     #Use Get-ItemProperty cmdlet to list the configured file path for the application, security, and system log.
     Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\EventLog$_ -Name File | Select-Object PSChildName,File
 }

以下屏幕截图显示了代码的预期输出,显示了应用程序安全系统日志文件的日志名称和存储位置。

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

审核策略:定义要记录的事件

默认情况下,Windows 不会捕获检测或调查漏洞可能需要的所有安全事件。要控制 Windows 记录和不记录的内容,您必须定义并应用审核策略。审核策略是一组传递给 Windows 的指令,告诉它要记录哪些事件。

有几种不同的方法可以分配和使用审核策略,例如组策略。如果您必须在多台计算机上实施审核策略,则组策略效果很好。但在本文中,您将坚持使用单个设备,因此您将使用auditpol 工具。 Auditpol 工具随 Windows 一起安装,允许您在 Windows 系统上查找和设置审核策略。

查找审计政策

例如,要查找 Windows 系统上所有审核策略的状态,请使用 /get 参数,如下所示。使用 /category 参数后跟通配符告诉auditpol查找所有审核策略的状态;不仅仅是匹配特定类别或子类别的一个。

#Obtain the system's audit policy configuration.
auditpol /get /category:*

以下屏幕截图显示了代码预期输出的截断版本,其中显示了帐户管理审核策略类别、子类别和状态(设置)

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

配置为无审核设置意味着不会记录与该审核策略子类别关联的所有事件。

制定审核策略

auditpol 工具不仅可以查看审核策略设置。它还可以使用auditpol /set命令修改它们。要演示本教程中的后续部分,请以管理员身份打开 PowerShell 控制台并运行以下命令。此命令开始记录属于登录子类别的所有事件(成功和失败)。

配置登录子类别会强制您的系统记录事件:

  • 4624:账户登录成功
  • 4625:账户登录失败
  • 4626:用户/设备声明信息
  • 4648:尝试使用显式凭据登录
  • 4675:SID 已被过滤
#Set Logon Events to capture Success/Failure activity.
auditpol /set /subcategory:"Logon" /success:enable /failure:enable

有大量资源可帮助您进行最佳实践审核策略配置,包括互联网安全中心 (CIS) 基准、国防信息系统局 (DISA) 安全技术实施指南 (STIG) 以及由微软。

生成登录失败日志以供分析

本文将是一个教程,希望您能够遵循。如果您已将 Windows 配置为审核上述登录事件,那么现在让我们生成一些安全事件以供稍后分析。更具体地说,让我们生成 35 次失败的登录尝试,这些尝试将记录在系统的安全日志中以模拟暴力破解活动。

1. 打开您最喜欢的代码编辑器。

2. 复制以下代码并将其粘贴到代码编辑器中。此代码段尝试使用 Start-Process cmdlet 使用虚假用户名和密码打开 PowerShell.exe 进程。

#Define 5 usernames to record as logon failures.
 $arrUsers = @(
     "AtaBlogUser1"
     "AtaBlogUser2"
     "AtaBlogUser3"
     "AtaBlogUser4"
     "AtaBlogUser5"
 )
 #Loop through usernames using ForEach-Object to generate a logon failure for each one.
 $arrUsers | ForEach-Object {
     $securePassword = ConvertTo-SecureString "AtA810GRu13Z%%" -AsPlainText -Force 
     $storedCredential = New-Object System.Management.Automation.PSCredential($_, $securePassword)
     Start-Process -FilePath PowerShell -Credential $storedCredential
 }
 #Generate 30 logon failures for user AtaBlogUser.
 $i = 0
 Do {
     $securePassword = ConvertTo-SecureString "AtA810GRu13Z%%" -AsPlainText -Force 
     $storedCredential = New-Object System.Management.Automation.PSCredential("AtaBlogUser", $securePassword)
     Start-Process -FilePath PowerShell -Credential $storedCredential
     $i++
 } Until ($i -eq 30)

3. 将 PowerShell 脚本保存为 Invoke-BogusEvents.ps1 或您想要的任何名称,然后执行该脚本。

执行时,您会注意到预期错误重复了 35 次,指示用户名或密码不正确

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

如果您没有收到预期的输出,请确保辅助登录服务处于“正在运行”状态。

使用 PowerShell 访问 Windows 事件

现在您已经确定至少有 35 个 Windows 安全事件,让我们深入了解如何使用 PowerShell 的 Get-WinEvent cmdlet 查找它们。

您可能熟悉 PowerShell 的 Get-EventLog cmdlet,它也用于以编程方式访问事件日志。 Get-EventLog 使用 Win32 应用程序编程接口 (API),该接口已弃用,并且不会在本文中讨论。

以管理员身份打开 PowerShell 控制台,然后调用 Get-WinEvent cmdlet,向其传递 FilterHashtableMaxEvents 参数,如下所示。

以下命令在系统的安全日志 (LogName='Security') 中查询事件 ID 4625 (ID=4625),并返回前 10 个最新实例 (MaxEvents 10)。

#Filter the security log for the first 10 instances of Event ID 4625
Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 10

如果成功,您应该看到类似于以下内容的输出:

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

使用 Get-WinEvent 访问事件属性

在上一节中,您使用 Get-WinEvent 在较高级别上查看 Windows 安全事件,但 Windows 事件包含更多信息。每个 Windows 事件都有有价值的属性,您可以使用它们进行更深入的分析。

XML 形式的 Windows 事件

当 Windows 记录事件时,它以 XML 格式存储。如果是这样,那么为什么您的 Get-WinEvent 命令返回典型的 PowerShell 对象? Get-WinEvent cmdlet 读取本机 Windows API 并将事件转换为 PowerShell 对象以增强功能。

每个 Windows 事件都有遵循特定 XML 架构或结构的各种属性。

您将在下面看到每个事件都遵循具有三个属性的特定结构:

  • name - 属性的名称
  • inType - 输入类型定义或事件如何接受值
  • outputType - 输出类型定义或如何记录事件

使用 PowerShell 查找事件 XML 模板

如上所述,每个 Windows 安全事件都存储在 XML 中并具有特定的架构,但该架构是什么样的呢?让我们来看看吧。

在前面的一节中,您在安全事件日志中生成了一些 ID 为 4625 的事件。此类事件具有仅适用于它的特定属性。要查找这些属性以及模板的外观:

1. 如果尚未打开 PowerShell 控制台,请以管理员身份打开它。

2. 再次运行 Get-WinEvent,但这次使用 ListProvider 参数指定 Windows 用于将事件记录到安全事件日志的提供程序,并且仅返回 Events 属性。

Events 属性包含列表提供程序已记录的所有事件,并公开每个事件的 XML 模板。

(Get-WinEvent -ListProvider 'Microsoft-Windows-Security-Auditing').Events

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

3. 现在您已经有了查找所有事件类型模板的代码,通过仅返回与 ID 4625 关联的事件来缩小范围。

(Get-WinEvent -ListProvider 'Microsoft-Windows-Security-Auditing').Events | Where-Object -Property ID -eq 4625

4. 仅返回事件 ID 为 4625 的登录事件类型后,将其限制为仅显示 Template 属性,如下所示。

#Obtain event XML template for event properties of Event ID 4625.
 ((Get-WinEvent -ListProvider 'Microsoft-Windows-Security-Auditing').Events | Where-Object -Property ID -eq 4625).Template

以下屏幕截图显示了代码输出的截断版本,标识了事件属性名称、输入类型和输出类型。您可以看到事件 ID 4625 具有具有各种输入和输出定义的事件属性。

下面的屏幕截图突出显示了事件 ID 4625 的 SubjectUserSid 属性。此特定事件接受 win:SID 的输入类型 (inType) 并呈现输出 (outType) 作为字符串,这就是它在安全日志中的存储方式。

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

PowerShell 如何将 XML 转换为对象

现在您已经了解了 Windows 如何在 XML 中存储事件以及如何在 PowerShell 中查看这些模板,接下来让我们看看 PowerShell 如何将该 XML 转换为对象。

1. 再次运行 Get-WinEvent 命令以返回事件 ID 4625。到目前为止,这并不是什么新鲜事。请注意,PowerShell 仅显示四个属性:TimeCreatedIdLevelDisplayNameMessage

Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 1

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

默认情况下,Get-WinEvent cmdlet 不会将事件的 XML 数据源中的所有属性作为 PowerShell 对象返回。

2. 现在,将上述命令的输出通过管道传输到 Select-Object cmdlet,并指定传递值的 Property 参数以显示所有属性。

Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 1 | Select-Object -Property *

请注意,下面 PowerShell 隐藏了许多不同的属性。更具体地说,是一个名为 Properties 的属性。 Properties 属性包含您之前在 XML 模板中看到的每个事件属性的值。

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

3. 限制上面 Get-WinEvent 命令的输出以公开 Properties 属性。此属性将所有事件属性(而非 PowerShell 对象属性)存储在数组中。

#Output event properties array for the first instance of Event ID 4625
 $eventProperties = (Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 1).properties
 $eventProperties

下面屏幕截图的左侧是上述命令的输出。该数组包含屏幕截图右侧 XML 模板中每个 XML 属性的

屏幕截图中显示的代码输出表明,系统 Desktop-XXXXX (WorkstationName) 中的用户 AtaBlogUser (TargetUserName) 发生身份验证失败),使用 IP 地址 ::1 (IpAddress)。

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

也许您只想返回 TargetUserName 事件属性的值。由于您已将所有事件属性存储在名为 $eventProperties 的变量中,因此请引用第五个索引,该索引保存 TargetUserName 的值。

您必须引用单个事件属性对象上的 value 属性才能仅返回值 (AtaBlogUser)。 $eventProperties[5] .值

$eventProperties[5].value

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

本节中描述的实践将在后续部分中用于追踪您在本文前面模拟的暴力尝试。

检测暴力攻击

现在,您已准备好使用 PowerShell 技能来追踪您在本文前面复制的暴力攻击!让我们通过模拟根据特定时间范围追踪暴力攻击的情况来测试您的技能。

假设您收到警报,发现您的组织认为有人试图使用管理帐户登录重要的 Windows Server。这项活动于昨天开始。您必须找到过去 24 小时内发生的事件 ID 4625:帐户无法登录的数量,并确定每个事件的登录类型。

1. 在 Windows 安全日志 (LogName="Security") 中查找过去 24 小时 (StartTime= ((Get-Date).AddDays(-1).Date),在当前时间 (Get-Date) 结束。

$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1));EndTime=(Get-Date)}

2. 现在,对变量中存储的所有事件进行计数,以确定失败登录事件是否比预期多。

$events.Count

您现在应该看到一个数值,指示过去 24 小时内在安全事件日志中找到事件 ID 4625 的次数。

3. 您已确定发生了暴力攻击,现在追踪有关这些 Windows 安全事件的更多信息。为此,只需返回您感兴趣的每个事件的属性。

如前所述,特定事件的每个值都存储在具有特定索引的数组中。该演示的有趣事件属性如下。

  • TargetUserName 索引:[5]
  • LogonType 索引:[10]
  • 工作站名称索引:[13]
  • IpAddress 索引:[19]

下面的代码示例读取 $events 变量中的每个对象,仅收集有趣的属性,并将它们连接到一行中。

#Extract TargetUserName, LogonType, WorkstationName, and IpAddress event properties from all instances of Event ID 4625 in the last 24 hours.
 $events | ForEach-Object {
     ## Reference the properties object property
     ## Only return the value of indexes 5,10,13 and 19 from the properties array
     ## Concatenate all values together by joining them with a comma
     $_.properties[5,10,13,19].value -join ", "
 }

以下屏幕截图显示了代码预期输出的截断版本,详细说明了以逗号分隔的 TargetUserNameLogonTypeWorkstationName 列表。 >IP地址。

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

4. 正如您之前从 XML 模板中看到的,事件 ID 4625 的模板具有 LogonType 属性。此属性指示帐户尝试进行身份验证的方法。通过进一步调查,您注意到 LogonType 有时会有所不同。

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

LogonType 值是 2-11 之间的数值,但这是什么意思呢?您进行一些研究并发现每个值的含义。

2 - 交互式 - 用户登录到该计算机。

3 - 网络 - 从网络登录到此计算机的用户或计算机。

4 - 批处理 - 批处理服务器使用批处理登录类型,其中进程可以代表用户执行,而无需用户直接干预。

5 - 服务 - 服务由服务控制管理器启动。

7 - 解锁 - 该工作站已解锁。

8 - NetworkCleartext - 用户从网络登录到此计算机。用户的密码以未散列的形式传递到身份验证包。内置身份验证会在通过网络发送所有哈希凭据之前对其进行打包。凭证不会以明文(也称为明文)形式穿越网络。

9 - 新凭证 - 调用者克隆其当前令牌并为出站连接指定新凭证。新的登录会话具有相同的本地身份,但对其他网络连接使用不同的凭据。

10 - RemoteInteractive - 调用者克隆其当前令牌并为出站连接指定新凭据。新的登录会话具有相同的本地身份,但对其他网络连接使用不同的凭据。

11 - CachedInteractive - 用户使用计算机本地存储的网络凭据登录到该计算机。未联系域控制器来验证凭据。

现在您已经很好地理解了每个 LogonType,您需要一个更具描述性的字符串,而不是在输出中看到数字值。要在 PowerShell 中创建“映射”,请使用哈希表。

$logonTypes = @{
     [uint32]2 = "Interactive"
     [uint32]3 = "Network"
     [uint32]4 = "Batch"
     [uint32]5 = "Service"
     [uint32]7 = "Unlock"
     [uint32]8 = "NetworkCleartext"
     [uint32]9 = "NewCredentials"
     [uint32]10 = "RemoteInteractive"
     [uint32]11 = "CachedInteractive"
 }

5. 将 Get-WinEventLogonType 哈希表与 ForEach-Object 结合起来,创建一个仅返回您想要的属性的脚本带有用户友好的 LogonType 值,如下所示。 Format-Table cmdlet 通过将 PowerShell 的响应格式化为表格来添加用户友好的输出。

#UseGet-WinEventtoaccessthepropertiesofeachloggedinstanceofEventID4625
$events=Get-WinEvent-FilterHashTable@{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1).Date);EndTime=(Get-Date)}
##Createthenumericalvaluetostring"map"
$logonTypes=@{
[uint32]2="Interactive"
[uint32]3="Network"
[uint32]4="Batch"
[uint32]5="Service"
[uint32]7="Unlock"
[uint32]8="NetworkCleartext"
[uint32]9="NewCredentials"
[uint32]10="RemoteInteractive"
[uint32]11="CachedInteractive"
}
##Beginprocessingeachobjectinthe$eventsarray
$events|ForEach-Object{
##Lookupthenumericalvalueinthehashtable
$logonType=$logonTypes[$_.properties[10].value]
#CreatecustomPowerShellobjecttooutputrelevanteventproperties
[PSCustomObject]@{
TimeCreated=$_.TimeCreated
TargetUserName=$_.properties[5].value
LogonType=$logonType
WorkstationName=$_.properties[13].value
IpAddress=$_.properties[19].value
}
}|Format-Table-Wrap

此时,您现在拥有一个返回 PSCustomObject 类型对象的脚本,允许您执行许多不同类型的分析!要完成本教程的分析,请按 TargetUserName 确定身份验证失败尝试的优先级。要通过 TargetUserName 属性对失败进行优先级排序,请将上述代码与 Group-Objectcmdlet 结合起来。使用Sort-Object 及其降序 开关来识别最严重的违规用户。

#UseGet-WinEventtoaccessthepropertiesofeachloggedinstanceofEventID4625
$events=Get-WinEvent-FilterHashTable@{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1).Date);EndTime=(Get-Date)}
##Createthenumericalvaluetostring"map"
$logonTypes=@{
[uint32]2="Interactive"
[uint32]3="Network"
[uint32]4="Batch"
[uint32]5="Service"
[uint32]7="Unlock"
[uint32]8="NetworkCleartext"
[uint32]9="NewCredentials"
[uint32]10="RemoteInteractive"
[uint32]11="CachedInteractive"
}
##Beginprocessingeachobjectinthe$eventsarray
$events|ForEach-Object{
##Lookupthenumericalvalueinthehashtable
$logonType=$logonTypes[$_.properties[10].value]
#CreatecustomPowerShellobjecttooutputrelevanteventproperties
[PSCustomObject]@{
TimeCreated=$_.TimeCreated
TargetUserName=$_.properties[5].value
LogonType=$logonType
WorkstationName=$_.properties[13].value
IpAddress=$_.properties[19].value
}
} | Group-Object -Property TargetUserName | Sort-Object -Property Count -Descending

做得好!您刚刚使用 PowerShell 检测了本文前面模拟的暴力尝试。根据输出,AtaBlogUser 在过去 24 小时内未能通过身份验证 30 次!

[玩转系统] 如何使用 PowerShell 跟踪重要的 Windows 安全事件

下一步

在本教程中,您了解了 Windows 如何记录事件、如何为某些事件类型启用事件日志记录以及如何构建 PowerShell 工具来查询这些事件。

使用您现在拥有的 PowerShell 脚本,如何使其变得更好?您将如何利用今天学到的代码来构建更好的工具?

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

取消回复欢迎 发表评论:

关灯