Commit Stomping:操纵Git历史以掩盖真相
Commit Stomping是一种受timestomping启发的技术,后者是攻击操作中常用的方法,通过操纵文件元数据来隐藏行动的真实时间。在Git中,Commit Stomping涉及修改提交时间戳,以误导观察者关于更改引入的时间。这不是Git中的错误或漏洞,而是一个功能,当被误用时,可用于伪装恶意或未经授权的更改,使在审计、调查或代码审查期间建立准确时间线变得更加困难。
我之前在编写RepoMan和伴随的博客文章时研究过这个主题,探讨了受AI影响的代码提交方式,但从未完全探索过作为独立技术的主题。如果您决定逐字复制本文,请将其归因于本文,而不是盲目复制和抓取。
为什么这种技术重要
Git提交历史通常被依赖作为真相来源在:
- 事件响应和取证时间线
- 代码审计和合规性审查
- 团队或开源环境中的归属
当提交时间戳被伪造时,确定更改的顺序和来源变得更加困难。这在软件供应链安全、内部威胁和长期审计跟踪的背景下具有重大影响。
Git如何跟踪时间
Git不仅存储更改的内容,还存储关于谁进行了更改以及何时进行的元数据。每个提交包括两个不同的时间戳:
GIT_AUTHOR_DATE:内容最初编写的日期和时间GIT_COMMITTER_DATE:提交最终确定到存储库的日期和时间
在大多数工作流中,这些值是相同的。然而,在变基、修改提交或由原始作者以外的人执行提交时,会出现差异。
变基和修改场景
使用git rebase或git commit --amend会重写提交。Git保留GIT_AUTHOR_DATE但更新GIT_COMMITTER_DATE以反映更改重写的时间。
|
|
这会调整提交元数据而不更改创作时间,除非明确覆盖。
多个提交者
在协作工作流中:
- 开发人员可能创建补丁并通过电子邮件发送
- 维护者或审查者可能随后提交它
在这些情况下,作者和提交者可能在身份和时区上不同。如果时间戳未标准化,这种差异可能会使取证分析复杂化。
手动时间戳控制
Git允许您通过环境变量控制两个时间戳:
|
|
这使得合法的元数据保存或误用以伪造历史成为可能。
支持的时间戳格式
Git支持这些环境变量和--date标志的各种格式:
-
Git内部格式
<unix timestamp> <time zone offset>示例:1GIT_AUTHOR_DATE="1700000000 +0100"这表示2024年11月14日06:13:20 CET。
-
ISO 8601
1 2GIT_AUTHOR_DATE="2024-11-14T06:13:20+01:00" GIT_AUTHOR_DATE="2024-11-14 06:13:20 +0100" -
RFC 2822
1GIT_AUTHOR_DATE="Tue, 14 Nov 2024 06:13:20 +0100" -
相对
1 2GIT_AUTHOR_DATE="2 weeks ago" GIT_COMMITTER_DATE="yesterday" -
Epoch
1GIT_AUTHOR_DATE="@1700000000"等同于"1700000000 +0000",除非指定。
使用自定义时间戳提交
Git允许您在创建时为提交分配任意时间戳。这意味着您可以伪造提交日期,使其看起来像是在完全不同的时间点完成的工作。这对于合法原因(如将历史代码移植到新存储库同时保留创作日期)可能有用,但也是Commit Stomping的基础,当被恶意使用时。
要使用回溯时间戳提交,您可以使用环境变量明确设置作者和提交者日期:
|
|
这将创建一个看起来像是在2025年初编写和提交的提交,无论实际制作日期如何。从时间线分析的角度来看,这与在该时间真正制作的提交无法区分,除非通过外部日志或镜像基础设施进行验证。
使用Commit Stomping重写历史
如果提交已经以当前或不想要的时间戳进行,您仍然可以返回并更改它。Git强大的历史重写工具使得事后伪造时间戳变得微不足道。这是Commit Stomping变得最有效的地方;重写现有提交以在伪造的历史上下文中植入或隐藏行动。
交互式变基
这种方法非常适合以受控方式更改一个或几个最近的提交:
|
|
这将打开一个编辑器,显示最后三个提交。将pick更改为edit以更改您想要修改的提交。然后:
|
|
这将用您选择的日期替换原始时间戳,同时保持提交内容和哈希更改(因为Git哈希包括元数据)。这是在清理或操纵活动期间进行外科手术式踩踏的理想选择。
使用git filter-branch
如果您在更广泛的提交集中重写时间戳,或者想要针对历史深处的特定哈希,git filter-branch允许进行脚本化、大规模重写。
|
|
这有选择地更改所有分支中提交abc123的时间戳。您可以扩展逻辑以匹配作者名称、消息或范围。虽然强大,但filter-branch也是资源密集型的,并且没有备份是不可逆的。
考虑改用git filter-repo。它更快、更灵活,并且对于大型存储库更安全。
自动化Commit Stomping
如果目标是隐藏更改的真实顺序或使存储库的时间线看起来嘈杂和随机,您可以在整个提交历史中自动化Commit Stomping。这会在时间线中引入熵,使得识别关键行动发生的时间变得更加困难。
这是一个使用filter-branch和随机Unix时间戳的简单示例:
|
|
此脚本随机设置作者和提交者日期为广泛epoch范围内的值。您可以调整随机性或针对特定范围,以将更改混合到特定时间框架中(例如,将后门放入旧发布周期中)。
这种方法嘈杂、不可逆,并且在无理由进行时是篡改的明显迹象,但在对抗模拟或攻击操作中,它可以完全破坏基于时间线的调查。
检测Commit Stomping
发现Commit Stomping并不总是直接的,特别是在快速移动的存储库或那些没有一致提交卫生的存储库中。然而,在取证审查、审计或一般源代码控制卫生检查期间,有明显的指标应该引起警惕。
寻找以下内容:
-
跨多个提交的相同或过于相似的时间戳 具有完全相同
GIT_AUTHOR_DATE和GIT_COMMITTER_DATE的提交,尤其是连续出现,表明自动化或手动回溯。当提交似乎反映逻辑上独立的工作时,这尤其可疑。 -
作者和提交者日期不匹配 如果作者日期显著早于提交者日期(例如,几个月或几年),可能表明重写或伪造的历史。虽然在变基或补丁应用期间有些差异是正常的,但大的差距应该被调查。
-
时间顺序不一致 出现顺序混乱的提交,其中较新的提交具有较早的时间戳,可能是历史操纵的迹象。虽然Git不强制执行严格的时间顺序,但此类提交的模式可以揭示篡改或恶意行动的迹象。
-
与外部日志的差异 将提交时间戳与您的CI/CD管道、webhook事件日志或镜像存储库进行比较。如果提交声称来自1月,但构建系统在4月首次看到它,那是一个危险信号。
-
不寻常的历史回溯集群 如果贡献者突然开始提交大量具有遥远过去时间戳的代码,可能是试图插入或埋葬更改而不引起注意。
在受监管或高信任环境中定期审计提交元数据是供应链完整性的宝贵部分。
防御Commit Stomping
Git是一个围绕灵活性和离线工作流设计的分布式系统。这种灵活性包括让用户为提交分配任意时间戳,这也意味着Git不验证提供的日期是否真实。如果您希望加固存储库以防止时间线操纵,以下措施将有所帮助:
-
要求并验证签名提交 GPG或SSH签名提交提供了一种验证提交者身份的方法。虽然这不直接防止时间戳篡改,但它增加了一层问责制,并有助于检测未经授权的重写尝试。将签名检查集成到您的CI管道中,并在受保护分支上拒绝未签名的提交。
-
在摄取时捕获元数据 在更改进入您的生态系统时记录提交事件——这可能是CI/CD管道中的时间戳记录、Git服务器中的审计跟踪或存储在日志聚合器中的webhook负载。这些摄取日志为更改实际发生的时间创建了一个外部参考点。
-
使用具有不可变存储的镜像存储库 将提交推送到安全位置托管的只读镜像。此镜像充当时间线的独立副本。如果有人在主存储库中重写历史,您可以与镜像进行比较以识别差异。
-
锁定历史重写 在主要或受保护分支上禁用强制推送。这不会阻止某人在分支或个人分支中重写历史,但它防止未经授权的时间线更改在未经通知的情况下进入您的关键分支。
-
监控异常模式 使用提交分析工具或基本脚本来监视时间戳异常,例如大的日期差距、提交历史中的向后跳跃或旧日期提交的突发。将其与在发布或合规周期期间的定期手动审查配对。
最终,防御Commit Stomping是关于在您的开发过程周围建立信任和验证层。Git给了您绳子——团队是用它安全地建造还是吊死自己,取决于这些控制是如何实施的。
最终想法
Commit Stomping不是传统意义上的漏洞——没有漏洞利用,没有CVE,也没有补丁即将到来。这是一个真正的案例,它不是错误,而是Git分布式和基于信任的设计的一个功能,可以被转变为欺骗技术。问题不是Git坏了,而是它隐含地信任用户。这种信任可能被滥用。
手动设置或重写提交时间戳的能力本身并不坏。它通常用于实际原因,如导入旧项目时保留日期、与外部系统对齐贡献或整理混乱的提交历史。但在错误的手中,它可能被滥用以重写过去,掩盖更改真正进行的时间,隐藏恶意编辑,或甩掉任何试图追踪发生了什么以及何时发生的人。
在一个源代码控制是安全边界一部分的世界中,假设Git日志的完整性不再足够。重要的是将版本历史视为可变的,除非证明 otherwise,并用提供外部验证的控制包围Git:CI/CD日志记录、签名提交、不可变镜像和行为监控。
如果您正在模拟高级对手、响应内部威胁、在事件期间审查代码历史或构建加固的开发管道,操纵时间戳的能力必须是您威胁模型的一部分,并且意识到各种攻击的影响是关键。如果您不寻找它,您就不会看到它——如果您不防御它,您就在取证跟踪中留下了一个安静的缺口。
归根结底,Git讲述了一个故事。Commit Stomping让您重写该故事的时间线,并沿途更改一些关键细节。
Git链接:https://github.com/ZephrFish/CommitStomping-Info