在阅读了一些文章后,我受到启发,开始了一个专门针对事件日志操作技术的检测系列,我们的第一个主题是时间错位!
序
了解时间错位
在网络安全中,这个概念以文件为“时间踩踏”而闻名,但为了更清晰和有点异想天开,让我们将其称为时间错位!
相关视频教程
恶意软件开发(更新到了155节)
它涉及更改系统的时钟或调整文件的日期,从而影响事件日志中的时间戳完整性。这种技术可能会扰乱记录事件的顺序,使事件分析和取证复杂化。
攻击者可能会在执行恶意活动之前更改系统时间,使这些活动看起来比实际发生的时间更早或更晚。这可能会误导安全解决方案(SIEM、EDR 等) 依靠日志时间戳来拼凑事件序列并生成警报!
规避 SIEM 检测
将日志引入 SIEM Splunk 时,将创建以下字段:
_indextime:日志索引时间 - 由索引器生成。
Splunk 定义:从 Splunk 接收新数据到将数据写入 Splunk 索引的时间跨度。在此期间,将解析数据并提取实时时间戳。
_time:日志生成时间 - 从日志本身提取。
Splunk 定义:表示事件中时间信息的默认字段。如果事件不包含时间戳信息,Splunk 会尝试在索引时间 (_indextime) 为事件分配时间戳值
默认情况下,字段_time用于在Splunk中进行搜索,如果您在大多数计划搜索中未使用该字段_indextime,则缺少日志!延迟的可能原因包括:网络延迟、日志记录吞吐容量、日志记录间隔或时间延迟 有关为什么它对检测很重要的。
为了说明时间错位的利用:
_time字段将包含 2020/12/14(日志中的日期)
_indextime将包含 2024/01/13(日志摄取日期)
_time字段将包含 2026/12/31(日志中的日期)
_indextime将包含 2024/01/13(日志摄取日期)
除非使用“所有时间”设置搜索_time(这在实际场景中永远不可行),否则不会遇到在过去或将来设置了时间戳的事件。
下面是如何显示每个日志的_indextime的示例:
...
| eval indextime = _indextime
| eval diff = indextime - _time
| table indextime _time diff _raw
```human readable format for the example```
| eval indextime=strftime(indextime, "%Y-%m-%d %H:%M:%S")
以下是日志的样子:
您有两种选择:
1. 继续将日志时间 (_time) 用于搜索查询(默认行为),但有必要识别使用超出典型搜索时间范围的_time编制索引的日志。这使您能够使用可操作的自动化自动重新执行对错过的时间段的搜索,并调查潜在的事件,但需要付出很多努力。
2. 在搜索中使用_indextime,以确保全面检测所有索引事件。对于关联搜索查询,必须验证是否捕获了基于特定时间线准确检测方案所需的每个事件序列。有时它可能难以实现,并且可能需要仅根据_time进行一些搜索,尤其是在事件的精确时间和顺序对分析至关重要的情况下。
亚历克斯·特谢拉
在他的文章中分享了一些关于如何安排搜索的技巧 _index_earliest 和 _index_latest:
这是一个很好的方法,这是意料之中的,但是如果系统日期更改为提前或延迟一天以上的时间(将来),您将错过日志!
如前所述,涉及过去和未来系统日期的规避场景仍然有效,因为我们的_time窗口不够大。因此,无论您使用的是_time还是_indextime,_time窗口有限,都必须制定检测规则来识别_time异常并维护神圣的时间线!
在深入研究模拟这些漏洞并演示检测方法之前,让我们首先强调 EDR 中的相同缺陷,特别关注 CrowdStrike。
逃避 EDR Crowdstrike
在为本文进行测试时,我发现 CrowdStrike 依赖于而不是用于检测。使用 Splunk 作为其控制台,CrowdStrike 的默认仪表板和搜索也基于它,似乎编辑器决定保持这种方式!_time
_indextime
_time
我在我的机器上将系统日期更改为未来,安装了 crowdstrike 代理并执行了一堆恶意可执行文件,而有些被阻止了,表明代理的功能,我是隐形的!没有 Crowdstrike 的日志可见性和警报!
回到过去也很有效,但更有可能的是,SIEM 和 EDR 解决方案对历史数据进行回顾性搜索,而不是对未来日期(仅使用日志时间进行搜索时)执行。
有趣的是,crowdstrike 代理会在 15 分钟后检测并纠正不同步的系统时间,但这会留下 15 分钟的窗口来绕过检测!
这很好,但为了更改系统日期,您需要在 Windows 上拥有管理员权限!很高兴知道您可以通过这种方式向 EDR 隐藏您的活动。当更改日期的操作记录在系统上时,CrowdStrike 不会标记此行为或触发任何警报
观察到的最后一个 Crowdstrike 日志
即使没有管理员权限,也可以远程修改系统日期吗?
在 Windows 上,默认的 NTP 服务器是 time.windows.com,如果计算机位于域中,它将是 DC(详细信息在 HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesW32TimeParametersNtpServer 中)
为此目的使用 MITM NTP 欺骗的可行性如何?
使用这种技术在未来调整几台机器上的系统日期将有助于在接下来的 15 分钟内逃避 CrowdStrike 检测。
如果您有任何远程更改系统日期的替代方法,无论是否具有管理员访问权限,我都有兴趣听到它们!
在这篇文章发表之后,Hexacorn 与我分享了另一种操作系统时间的技术,它涉及使用 SetSystemTimeAdjustment API。
我想知道使用这种方法是否会触发 EDR 检测!
检测时间错位
我们将进行时间错位模拟,以更深入地了解它在 Windows 系统上创建的特定日志。
日期创建模式的一些示例:
Set-Date -Date [NewDate]
(Get-Date [*] | Set-Date
Set-Date [*]
Set-Date -Adjust[*]
(Get-Date).AddMonths([NumberOfMonths] | Set-Date
(Get-Date).AddYears([NumberOfyears] | Set-Date
(Get-Date).AddDays([NumberOfDays]) | Set-Date
Set-Date -Date $[*]
(New-Object System.DateTime [*])
os.system('date [*]')
cmd.exe*/c date [*]
cmd /C date [*]
exec('date [*]',[*]
system('date [*]')
"cmd", "/C", "date", "[*]"
date [*]
我们使用 PowerShell 中的 Set-Date 命令将日期设置为未来,特别是 2026–12–31 15:00:00
思维导图
更改系统日期后我观察到的所有相关 Windows 事件日志:
让我们来看看一些重要事件!
系统事件 ID 1(内核常规)
系统时间已更改
OldTime:在更改日期之前包含旧时间
NewTime:更改日期后包含新时间
TimeDeltaInMs:旧日期和新日期之间的增量(以毫秒为单位)(并不总是可用 - 似乎取决于操作系统版本)
进程名称: 显示负责更改的进程的完整路径。建议监视环境中不常见的进程名称或路径。
安全事件 ID 4616
系统时间已更改。这是我们用来检测时间错位的最可靠的事件 ID!
SubjectUserName:此字段标识对时间更改负责的用户。如果是 以外的用户,则表示修改不是由 Windows 时间服务完成的。在本例中,是修改用户。寻找不寻常的用户名。
LOCAL SERVICE
mthcht
ProcessName:显示负责更改的进程的完整路径。建议监视环境中不常见的进程名称或路径。
NewTime:更改日期后包含新时间
上一页时间:更改日期前包含旧时间
使用 Splunk 计算“NewTime”和“PreviousTime”之间的时间差,以过滤重大时间更改。
[Microsoft-Windows-PowerShell/操作] 事件 ID 4104
我们使用 powershell 来设置时间:
ScriptBlockText 捕获已执行的命令或脚本块的内容,我们的命令是可见的
Set-Date
[Microsoft-Windows-时间-服务]事件 ID 52
此事件对于监视重大系统时间更改非常重要
此提取的 EventID 52 对应于我所做的时间更改,其中我将日期从 2026 更改为 2024(还原)
TimeOffsetSeconds:此字段指定系统时钟跳跃的时间量(以秒为单位),指示时间变化的幅度。在这里,我们有 93754257 秒,将近 3 年的跳跃!
ProcessID 和 ThreadID:它们提供有关记录事件时处于活动状态的进程和线程的详细信息,可用于跟踪时间更改的来源。
[Microsoft-Windows-时间-服务]事件 ID 261
W32time 服务更改了时间
此提取的 EventID 261 对应于我所做的时间更改,其中我将日期从 2026 更改为 2024(还原)
NewTime:更改日期后包含新时间
OldTime:在更改日期之前包含旧时间
时间异常检测
前往未来往往会引起更多的怀疑,也更容易被发现。未来花费的短暂时间会导致与该未来日期一致的大量系统修改。这些变化总是会留下明显的异常痕迹,当你回到现在时,这些痕迹会变得很明显。
请务必不要将时间错位检测与主机缺失检测混淆。是的,一个小阈值可能会触发丢失的 Windows 主机的警报,但过去或将来恶意活动的持续时间非常短,通常只有几分钟,几乎不可能与正常行为区分开来。即使有内部代理日志的关联,观察到的延迟的众多潜在原因也意味着创建可靠的检测变得不切实际,并且您将被误报淹没。此外,如果我们在执行下一次计划搜索之前恢复到我在系统上的确切时间,则仅依赖于_time字段的检测不会标记任何丢失的主机。
[DFIR]NTFS 日志异常
通过使用 0gtweet 制作的工具 CheckUsnMonotonicity 分析 NTFS 不一致来检测时间操纵!
它将扫描 usn 日志并报告较新的条目是否具有较旧的时间戳,这可能意味着时钟纵了!
将来修改的文件和返回现在时识别的文件:
异常:PreviousCreationUtcTime 与新的创建时间 CreationUtcTime 相比,是将来的
SystemTime 和 UtcTime 增量
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'>
<System>
<Provider Name='Microsoft-Windows-Sysmon'
Guid='{5770385f-c22a-43e0-bf4c-06f5698ffbd9}'/>
<EventID>7</EventID>
<Version>3</Version>
<Level>4</Level>
<Task>7</Task>
<Opcode>0</Opcode>
<Keywords>0x8000000000000000</Keywords>
<TimeCreated SystemTime='2024-01-12T18:35:49.7963690Z'/>
<EventRecordID>1953928079</EventRecordID>
<Correlation/>
<Execution ProcessID='5540' ThreadID='7268'/>
<Channel>Microsoft-Windows-Sysmon/Operational</Channel>
<Computer>DESKTOP-GI9JDDB</Computer>
<Security UserID='S-1-5-18'/></System>
<EventData>
<Data Name='RuleName'>-</Data>
<Data Name='UtcTime'>2026-12-31 14:03:20.497</Data>
...
</EventData>
</Event>
异常:与 SystemTime 相比,UtcTime 是将来的
程序执行日期
文件创建、修改或访问时间的异常可以指示更改日期的时间。
将来,我运行了几个可执行文件,包括执行命令whoami /priv
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'>
<System><Provider Name='Microsoft-Windows-PowerShell'
Guid='{a0c1853b-5c40-4b15-8766-3cf1c58f985a}'/>
<EventID>4104</EventID>
...
<Security UserID='S-1-5-21-1027851627-835900396-3296330306-1001'/>
</System>
<EventData><Data Name='MessageNumber'>1</Data>
<Data Name='MessageTotal'>1</Data>
<Data Name='ScriptBlockText'>whoami /priv</Data>
<Data Name='ScriptBlockId'>d667a010-0568-4b8a-9778-aafd27139f91</Data>
<Data Name='Path'></Data>
</EventData>
</Event>
预回迁文件 WHOAMI.EXE-9D378AFE.pf 文件创建事件:
预回迁文件的实际内容:
日期采用 UTC 格式
异常:SourceCreated、SourceModified 和 LastRun 的日期已明确设置在未来...
将事件追溯到未来和过去(适用于所有类型的日志)
想象一下,我们计划在 -24 小时到 +24 小时_time窗口内进行搜索,正如本文最初建议的那样。为了有效地发现_time异常超出此区间的缺失日志,我们可以使用 Splunk 来发现。
以下搜索查询旨在检索跳过检测规则的日志:
每 2 小时安排一次
```this search can be very slow on a large dataset, reduce the scope as much as possible```
`my_logs`
_index_earliest="-2h" _index_latest="-1m"
| eval indextime = _indextime, diff = _indextime - _time
| where diff<-86400 OR diff>86400
| eval indextime=strftime(indextime, "%Y-%m-%d %H:%M:%S")
| table indextime _time diff index sourcetype source _raw
此 Splunk 搜索可以配置为触发警报,以便您的团队进行调查或启动自动化任务。自动化任务将精确识别哪些检测规则受到这些缺失日志的影响,并随后在相关_time段内重新执行它们。实施此过程非常复杂,需要付出大量努力来确保准确性和效率。
对于没有原始日志的缺失日志的仪表板视图,请按如下方式修改查询:
按指数划分的每小时平均延迟:
`mylogs`
| eval delay_minute = (_indextime - _time) / 60
| timechart span=1h avg(delay_minute) by index
您可以更改“by”条件,以同时筛选 sourcetype、source 或 host
主机的每小时最大延迟:
`mylogs`
| eval delay_minute = (_indextime - _time) / 60
| timechart span=1h max(delay_minute) by host
以下是时间表的表示形式:
一些主机在此处遇到了两个小时的延迟,但幸运的是,您的规则配置为在 -24 小时到 +24 小时_time窗口内搜索最近编制索引的日志 (_index_earliest...)。此设置可确保有效捕获这些事件:)
添加条件
| where delay_minute < -1440 OR delay_minute > 1440
在 timechart 命令之前查看丢失的日志!
将 max() 命令更改为 min() 命令以查看将来的日志(负值)
如前所述,具有未来时间戳的日志是可疑的,应该很少见。
若要检测将来的时间戳异常,请使用以下搜索查询:
... _index_earliest=-2h _index_latest=now
| where _time > relative_time(now(), "+10h")
确保所有事件都带有适当的时区的准确时间戳,尤其是当您的主机分布在全球时
使用 Windows 事件 ID 进行搜寻
用户使用 EID 4616 启动了系统日期更改:
`wineventlog`
signature_id=4616
vendor_product="Microsoft Windows"
```excluding changes made by the Windows Time Service```
src_user!="LOCAL SERVICE"
| stats values(previous_time)
values(new_time)
values(process_path)
values(process_id)
by src_user signature_id src_nt_host _time
检测巨大的时间跳跃
使用 EID 4616:
使用 Splunk 作为事件 4616 计算时间增量不会直接提供它
Set-Date -Date [NewDate]
(Get-Date [*] | Set-Date
Set-Date [*]
Set-Date -Adjust[*]
(Get-Date).AddMonths([NumberOfMonths] | Set-Date
(Get-Date).AddYears([NumberOfyears] | Set-Date
(Get-Date).AddDays([NumberOfDays]) | Set-Date
Set-Date -Date $[*]
(New-Object System.DateTime [*])
os.system('date [*]')
cmd.exe*/c date [*]
cmd /C date [*]
exec('date [*]',[*]
system('date [*]')
"cmd", "/C", "date", "[*]"
date [*]0
EID 261 可以应用相同的逻辑(包含旧时间和新时间):
Set-Date -Date [NewDate]
(Get-Date [*] | Set-Date
Set-Date [*]
Set-Date -Adjust[*]
(Get-Date).AddMonths([NumberOfMonths] | Set-Date
(Get-Date).AddYears([NumberOfyears] | Set-Date
(Get-Date).AddDays([NumberOfDays]) | Set-Date
Set-Date -Date $[*]
(New-Object System.DateTime [*])
os.system('date [*]')
cmd.exe*/c date [*]
cmd /C date [*]
exec('date [*]',[*]
system('date [*]')
"cmd", "/C", "date", "[*]"
date [*]1
计算增量很容易
使用系统事件 EID 1
Set-Date -Date [NewDate]
(Get-Date [*] | Set-Date
Set-Date [*]
Set-Date -Adjust[*]
(Get-Date).AddMonths([NumberOfMonths] | Set-Date
(Get-Date).AddYears([NumberOfyears] | Set-Date
(Get-Date).AddDays([NumberOfDays]) | Set-Date
Set-Date -Date $[*]
(New-Object System.DateTime [*])
os.system('date [*]')
cmd.exe*/c date [*]
cmd /C date [*]
exec('date [*]',[*]
system('date [*]')
"cmd", "/C", "date", "[*]"
date [*]2
如前所述,此事件包括新旧时间戳之间的时间增量(以毫秒为单位),应用与之前使用 delta 解析字段的搜索相同的逻辑
Set-Date -Date [NewDate]
(Get-Date [*] | Set-Date
Set-Date [*]
Set-Date -Adjust[*]
(Get-Date).AddMonths([NumberOfMonths] | Set-Date
(Get-Date).AddYears([NumberOfyears] | Set-Date
(Get-Date).AddDays([NumberOfDays]) | Set-Date
Set-Date -Date $[*]
(New-Object System.DateTime [*])
os.system('date [*]')
cmd.exe*/c date [*]
cmd /C date [*]
exec('date [*]',[*]
system('date [*]')
"cmd", "/C", "date", "[*]"
date [*]3
与 Microsoft-Windows-Time-Service EID 52 相同
Set-Date -Date [NewDate]
(Get-Date [*] | Set-Date
Set-Date [*]
Set-Date -Adjust[*]
(Get-Date).AddMonths([NumberOfMonths] | Set-Date
(Get-Date).AddYears([NumberOfyears] | Set-Date
(Get-Date).AddDays([NumberOfDays]) | Set-Date
Set-Date -Date $[*]
(New-Object System.DateTime [*])
os.system('date [*]')
cmd.exe*/c date [*]
cmd /C date [*]
exec('date [*]',[*]
system('date [*]')
"cmd", "/C", "date", "[*]"
date [*]4
增量在日志中可用(以秒为单位),可以应用相同的逻辑。
鉴于提供的上下文,事件 ID 4616 仍然是最佳选择。我们将优先使用此特定事件进行检测工作。
可疑过程路径更改的时间
时间更改不是由授权的进程进行的
Set-Date -Date [NewDate]
(Get-Date [*] | Set-Date
Set-Date [*]
Set-Date -Adjust[*]
(Get-Date).AddMonths([NumberOfMonths] | Set-Date
(Get-Date).AddYears([NumberOfyears] | Set-Date
(Get-Date).AddDays([NumberOfDays]) | Set-Date
Set-Date -Date $[*]
(New-Object System.DateTime [*])
os.system('date [*]')
cmd.exe*/c date [*]
cmd /C date [*]
exec('date [*]',[*]
system('date [*]')
"cmd", "/C", "date", "[*]"
date [*]5
时间更改是由来自可疑位置的进程进行的
Set-Date -Date [NewDate]
(Get-Date [*] | Set-Date
Set-Date [*]
Set-Date -Adjust[*]
(Get-Date).AddMonths([NumberOfMonths] | Set-Date
(Get-Date).AddYears([NumberOfyears] | Set-Date
(Get-Date).AddDays([NumberOfDays]) | Set-Date
Set-Date -Date $[*]
(New-Object System.DateTime [*])
os.system('date [*]')
cmd.exe*/c date [*]
cmd /C date [*]
exec('date [*]',[*]
system('date [*]')
"cmd", "/C", "date", "[*]"
date [*]6
命令执行
使用我之前在 splunk 查找中给出的创建检测模式,并使用命令行执行日志检测系统时间更改
Set-Date -Date [NewDate]
(Get-Date [*] | Set-Date
Set-Date [*]
Set-Date -Adjust[*]
(Get-Date).AddMonths([NumberOfMonths] | Set-Date
(Get-Date).AddYears([NumberOfyears] | Set-Date
(Get-Date).AddDays([NumberOfDays]) | Set-Date
Set-Date -Date $[*]
(New-Object System.DateTime [*])
os.system('date [*]')
cmd.exe*/c date [*]
cmd /C date [*]
exec('date [*]',[*]
system('date [*]')
"cmd", "/C", "date", "[*]"
date [*]7
检测到 NTP 服务器修改
涉及潜在的 NTP 服务器修改或篡夺
Set-Date -Date [NewDate]
(Get-Date [*] | Set-Date
Set-Date [*]
Set-Date -Adjust[*]
(Get-Date).AddMonths([NumberOfMonths] | Set-Date
(Get-Date).AddYears([NumberOfyears] | Set-Date
(Get-Date).AddDays([NumberOfDays]) | Set-Date
Set-Date -Date $[*]
(New-Object System.DateTime [*])
os.system('date [*]')
cmd.exe*/c date [*]
cmd /C date [*]
exec('date [*]',[*]
system('date [*]')
"cmd", "/C", "date", "[*]"
date [*]8
事件序列号异常
(事件序列号)是由某些 Windows 事件源发布的值。它用作事件日志提供程序记录的每个事件的标识符,该标识符按顺序递增,确保事件的精确顺序是明确的,而不管时间戳的精度如何!EventRecordID
通过选择具有高严重性和低日志量的日志提供程序,可以增强对时间异常的检测。必须从提供程序收集每个日志,而不仅仅是特定的 EventID,以准确跟踪整个数字序列。
例如,让我们使用 WinEventLog:Microsoft-Windows-Windows Defender/Operational 提供程序,并在 2026 年再次旅行,对我用于测试的机器进行一些修改
如果我们仅根据 _time(日志时间)进行搜索,我们将看不到 2026 年发生的活动。但是我们可以检测到序列号差距!
在我们的搜索中,EventRecordID 似乎从 237 变为 243 !
以下是使用 Splunk 检测序列号差距的方法:
Set-Date -Date [NewDate]
(Get-Date [*] | Set-Date
Set-Date [*]
Set-Date -Adjust[*]
(Get-Date).AddMonths([NumberOfMonths] | Set-Date
(Get-Date).AddYears([NumberOfyears] | Set-Date
(Get-Date).AddDays([NumberOfDays]) | Set-Date
Set-Date -Date $[*]
(New-Object System.DateTime [*])
os.system('date [*]')
cmd.exe*/c date [*]
cmd /C date [*]
exec('date [*]',[*]
system('date [*]')
"cmd", "/C", "date", "[*]"
date [*]9
您可以根据所使用的特定日志提供程序调整间隙阈值。但是,从所选提供程序收集所有事件 ID 以便有效检测至关重要。选择具有相关事件和可管理日志卷的提供商。
此外,请考虑使用一个自定义应用程序,该应用程序定期将简短事件记录到专用事件提供程序。这种方法使您可以完全控制生成的数据,从而能够高度自信地检测序列号中的任何异常。
请记住,清除日志提供程序中的事件日志将重置序列号计数,这将触发间隙警报。若要防止与标识日志清除的其他检测规则重叠,请确保将间隙检测与与日志清除关联的特定 EventID 相关联。
相关
为了提高时间操纵的检测准确性,请考虑关联所有建议的搜索。不要为每个警报生成事件,而是将结果记录到索引中。然后,使用单独的检测规则来聚合这些事件,从而为时间错位创建高置信度警报!
结论
在本文中,我们深入探讨了操纵日志以逃避检测的众多方法之一。还有大量的技术有待探索。我希望这篇最初的博文能帮助您意识到防御者保持对时间线的控制至关重要!
祝您狩猎愉快!
二进制漏洞课程(更新中)
windows网络安全防火墙与虚拟网卡(更新完成)
windows文件过滤(更新完成)
USB过滤(更新完成)
游戏安全(更新中)
ios逆向
windbg
还有很多免费教程(限学员)
更多详细内容添加作者微信
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...