我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

admin 2025年4月28日10:02:38评论3 views字数 9109阅读30分21秒阅读模式

TL;DR — 

我构建了一个自动化功能,克隆和扫描了数以万计的公共 GitHub 存储库以查找泄露的机密信息。对于每个存储库,我恢复了已删除的文件,找到了悬空的 blob 和解压缩的 .pack 文件,以便在其中搜索公开的 API 密钥、令牌和凭据。最终报告了一堆泄漏,并从漏洞赏金🔥中获得了大约 64 美元。

大纲

  • 背景
  • Git 内部原理
  • 收集目标
  • 构建自动化
  • 调查结果和付款
  • 总结

背景

我叫 Sharon Brizinov,虽然我通常专注于 OT/IoT 设备中的低级漏洞和漏洞利用研究,但我偶尔也会深入研究漏洞赏金猎杀。

漏洞赏金计划领域的许多研究人员都会寻找泄露的机密,通常会扫描 GitHub 存储库以查找泄露的凭据。这种方法并不新鲜,但我想探索一个不同的角度 - 从据称已删除的文件中恢复秘密。开发人员经常忘记 Git 历史记录会保留所有内容,即使在文件从工作目录中删除后也是如此。

为了测试这一点,我扫描了来自数千家公司的数万个存储库,搜索隐藏在过去提交中的敏感信息。结果令人震惊 - 我发现了大量已删除的文件,其中包含 API 令牌、凭据,甚至是尚未撤销的活动会话令牌。报告这些发现为受影响的公司带来了显著的安全改进,最终,我总共获得了 64,350 美元的漏洞赏金奖励。

在这个博客中,我将尝试描述我从收集所有Github仓库,构建自动化,到发现和报告泄露的秘密的旅程。

Git 内部原理

首先,我强烈建议阅读 Octobot 的 git 内部工作原理。这是一个很棒的、易于阅读的资源,可以更好地理解 git。

Git 是一个分布式版本控制系统,可跟踪文件中的更改,并允许多个开发人员协作处理一个项目。它维护所有更改的完整历史记录,使用户能够恢复到以前的状态,分支进行功能开发,并有效地合并更改。Git 的核心是内容可寻址的文件系统,其中文件的每个版本都作为唯一对象存储在存储库中。

Git 跟踪的所有内容(文件、文件夹、提交等)都存储为对象,由其 SHA-1 或 SHA-256 哈希标识(取决于配置)。

Git 中有四种对象类型:

  • Blob
     → 文件内容

  • →目录结构
  • 提交
     →快照 + 元数据
  • Tag
     → 带注释的标签对象

Git Blob 和包

blob(二进制大对象)是 Git 存储文件内容的方式,没有任何文件名或路径信息。当 Git 第一次存储一个对象时,它会将其作为 “松散对象” 写入,如下所示:

.git/objects/ab/cdef1234567890...

其中 ab 是 SHA 的前 2 个十六进制字符,cdef1234567890... 是其余字符。存储在其中的二进制数据是对应于单个文件的 zlib 压缩数据。

为了优化存储和性能,Git 会定期(松散对象默认≥ 6700)将许多松散对象压缩到一个 pack 文件中:

.git/objects/pack/pack-<hash>.pack

.pack 文件是具有非常有趣的结构的复杂野兽。幸运的是,我们真的不需要完全理解它是如何构建的,因为我们可以使用 git-unpack-objects 来解压缩任何 .pack 文件。

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
如何识别 pack 和 blob 文件:50 41 43 4B — PACK |78 01 — zlib 压缩 blob 的开头(使用 HexShare 拍摄的图像)

有时,未引用的对象(又名悬空对象)会在我们的 git 仓库中创建。这些是有效但未引用的对象(提交、blob、树或标签),它们保留在目录中,但无法再从任何分支、标签、存储或 reflog 访问。它们通常是在重写历史记录时创建的(例如,通过执行 、 、 或 分支删除),留下旧对象。虽然不是活动历史记录的一部分,但 Git 会暂时保留它们(默认情况下为 2 周)以备不时之需。您可以使用.git/objects/git commit --amendrebaseresetgit fsck --dangling

Git 提交历史

Git 中的每个提交都表示存储库在给定时间点的快照。提交是不可变的,由 SHA-1/SHA-256 哈希标识。它们存储:

  • 对 tree 对象的引用,表示该提交时的文件结构。
  • 指向父提交的指针,形成存储库历史记录的有向无环图 (DAG)。
  • 元数据,包括作者、时间戳和提交消息。

Git 使用增量压缩有效地存储提交,这意味着它只记录更改,而不是文件的完整副本。

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

提交 — 树 — blob 关系(图片取自此处)

已删除的文件以及为什么可以恢复
当使用 git rm 删除文件或简单地从工作目录中删除并提交文件时,它会从最新快照中消失,但仍存在于存储库的历史记录中。发生这种情况是因为:
Git 提交历史记录是不可变的:一旦创建提交,其数据将存储在 .git/objects 中,即使它不再被任何分支或标签引用,也会保留在那里。未引用的(悬空)对象不会立即删除 — 它们通常会保留大约两周,然后才能进行垃圾回收。
引用 (refs) 使对象保持活动状态:Git 在 heads、tags 和 remotes 目录中维护引用,因此即使在以后的提交中删除了文件,较旧的提交 (=trees) 仍然包含该文件。

要从历史记录中完全删除文件,必须使用 git filter-branch、git-filter-repo 等工具重写历史记录,或者通过手动变基并运行垃圾收集器(使用 prune)来清除无法访问的对象——祝你好运。但是,如果存储库是公共的,则文件可能已经被复制或克隆到其他位置,因此查找和撤销泄漏的 API 密钥、令牌、密钥和会话非常重要。

为了更好地理解这些概念,我构建了一个小型平台来查看和分析 git 存储库中的文件目录更改,以可视化创建、更改和删除的对象。显然,这对这个项目来说有点矫枉过正,但是使用 vibe 编码,我花了 < 5 分钟,所以为什么不:)

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

我对一个小平台进行了 vibe 编码,以可视化整个 git 存储库快照中的变化

果汁 — 那么我们如何获取所有已删除的文件呢?

  • 通过区分父子提交来恢复已删除的文件。
  • 使用 git unpack-objects 解压缩所有 .pack 文件 < .git/objects/pack/pack-<SHA>.pack
  • 使用 git fsck 查找悬空对象 — full — 无法访问 — 悬空

为了收集所有已删除的文件,我遍历了所有提交,对于每个提交,我将文件列表与其父提交进行比较 (git diff)。如果存在差异并且一些文件被删除(用 D 标记),我会恢复文件 (git show) 并将它们转储到磁盘。显然,这不是最好的方法,也不是有效的使用方法,但它已经足够好了。下面是一个小型 PoC 脚本,它正是这样做的:

#!/bin/bash

# cd to cloned repo
mkdir -p "__ANALYSIS/del"
# Extract all commits and process each commit
git rev-list --all | whileread -r commit; do
echo"Processing commit: $commit"

# Get the parent commit
    parent_commit=$(git log --pretty=format:"%P" -n 1 "$commit")
if [ -z "$parent_commit" ]; then
continue
fi
    parent_commit=$(echo"$parent_commit" | awk '{print $1}')

# Get the diff for the commit
    git diff --name-status "$parent_commit""$commit" | whileread -r file_status file; do
# Replace / with _ for filenames in binary_files_dir
        safe_file_name=$(echo"$file" | sed 's///_/g')

# Handle deleted files
if [ "$file_status" = "D" ]; then
# Handle binary files
echo"Binary file deleted: $file" | tee -a "__ANALYSIS/del.log"
echo"Saving to __ANALYSIS/del/${commit}___${safe_file_name}"
                git show "$parent_commit:$file" > "__ANALYSIS/del/${safe_file_name}"
fi
done
done

收集目标

现在我有一个有效的 PoC 来恢复已删除的文件,下一步是收集尽可能多的相关 GitHub 存储库。什么才是相关的?当然,任何拥有有效漏洞赏金计划的公司。我从所有公开已知的漏洞赏金计划以及多年来我受邀参加的私人计划中编制了一份公司名称列表。对于公共 BB 程序,我主要使用了这些来源:
- https://hackerone.com/bug-bounty-programs
- https://www.bugcrowd.com/bug-bounty-list/
- https://github.com/Lissy93/bug-bounties
- https://github.com/trickest/inventory
- https://github.com/disclose/bug-bounty-platforms
- https://github.com/projectdiscovery/public-bugbounty-programs

此外,我认为获取所有至少有一个 Github 存储库和超过 5000 个 star 的 Github 帐户(主要是组织)可能会很有趣。我最后得到了这句话:

for page in {1..100}; do gh api "search/repositories?q=stars:>5000&sort=stars&order=desc&per_page=50&page=$page" --jq '.items[].full_name'done | cut -d '/' -f 1

组织帐户

我列出了所有公司名称的一大份清单,并将其保存为 companies.txt。接下来我需要找到他们的公共 Github 帐户。我想过不同的方式来实现这个目标,但最终选择了最懒惰和愚蠢的方式——“AI”。我刚刚将批量的公司名称发送到 grok、perplexity 和 OpenAI 上,并友好地要求他们“在线搜索并找到与以下组织关联的 github 帐户”。它并不完美,我不得不修复他们编造的一些账户,但总的来说它运行得相当不错。

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

我使用 AI 将公司/组织名称转换为他们的 Github 帐户

我很早就观察到的一个重要问题是,许多公司都维护着多个 GitHub 帐户。例如,他们可能为其主要工程团队、研究、QA/测试、社区等拥有单独的帐户。每个账户都可以保存有价值的信息,整个组织的开发人员可能会无意中泄露这些账户中的任何一个的敏感数据。因此,我确保专门寻找名称为“lab”、“research”、“test”、“qa”、“samples”、“hq”和“community”的帐户。

这是我使用的确切提示:

I have a task for you. I will provide a list of companies, and your job will be to search the internet for all GitHub accounts associated with those companies. This includes official, affiliated, open-source, and community-related repositories. Please provide only the GitHub URLs in a clean, bullet-point list. Is that clear?

请多点

此外,我还审查了我收集的所有 GitHub 帐户和存储库,以确定哪些是其他项目的分支。对于每个分叉的存储库,我将其追溯到原始来源,并将关联的 GitHub 帐户添加到我的监控列表中。我的理由是,如果供应商 A 创建的项目被其他公司(在我的列表中)分叉,则供应商 A 可能还有其他存储库(可能包含泄露的机密),这可能会影响分叉其他项目的公司。

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

我在分析所有存储库及其连接时使用的图表之一

我总共有数千个 Github 组织帐户,是时候构建自动化了。

构建自动化

自动化非常简单,它需要克隆所有组织的所有项目,恢复所有已删除的文件并搜索仍然有效的机密。下面是一个伪代码:

- foreach company in companies:
    - foreach repo in comapny.repos:
        - restore all deleted files
        - foreach file in files:
            - collect secrets
            - foreach secret in secrets:
                - is secret active?
                    - notify via Telegram bot

总的来说,我需要实施六个步骤,包括准备机器、克隆所有存储库、恢复所有已删除的文件、搜索热机密、通知已验证的机密、删除存储库并继续。以下是所有组件如何协同工作的细分。

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

设计自动化

1 — 准备机器

在这个项目的整个处理过程中,我使用了 10 台服务器,一些是私有云计算(例如 EC2),一些是 VPS,一些是物理计算机和 Raspberry PI。我确保每个计算单元至少有 120GB 的可用硬盘空间。然后,我将 Github 组织列表拆分为 10 个,并将每个部分加载到不同的服务器上。

2 – 克隆所有存储库

为了获取组织的整个 Github 存储库列表,我使用了 gh cli,如下所示:

for REPO_NAME in $(gh repo list $ORG_NAME -L 1000 --json name --jq '.[].name');
do
    FULL_REPO_URL="https://github.com/$ORG_NAME/$REPO_NAME.git"
    git clone"$FULL_REPO_URL""$REPO_NAME"
done;

3 – 恢复所有已删除的文件

对于每个克隆的项目,我使用三种技术恢复了所有已删除的文件:

  • 通过比较父子提交来恢复已删除的文件(请参阅上面的 bash 脚本)。
  • 使用 git unpack-objects 解压缩所有 .pack 文件 < .git/objects/pack/pack-<SHA>.pack
  • 使用 git fsck 查找悬空对象 — full — 无法访问 — 悬空

4 – 搜索活动密钥

恢复所有文件后,我运行 TruffleHog,这是一个很棒的秘密扫描工具,可以深入挖掘代码存储库并查找秘密、密码和敏感密钥。它支持检测和验证 800 多种不同密钥类型的密钥,并且总体运行速度非常快。它还可以检测 base64 编码和一些压缩数据格式的秘密,这对我们来说非常有用。

我使用带有 — only-verified 标志的 Trufflehog 来搜索 *working and verified* 秘密。我还使用了 filesystem 参数来强制它搜索磁盘上的文件 — 磁盘也包括已恢复的已删除文件。

trufflehog filesystem --only-verified --print-avg-detector-time --include-detectors="all" ./ > secrets.txt

在本地克隆上运行 Trufflehog 的另一个好处是,它还扫描了 .git 目录,并且由于它还可以解压缩和扫描 zlib 压缩的流,因此大多数松散对象都是“免费”扫描的。它还扫描了关闭的 .pack 文件,有时也会以不错的结果让我感到惊讶。

一个问题出现了 — 如果 Trufflehog 可以解压缩和扫描 git 对象,为什么还要费心恢复已删除的文件呢?因为这样做可以显著提高查找密钥的成功率。有时,压缩的流和 .pack 文件太大而无法处理,有时它们严重混合在多个压缩和包装器中,并且这些工具在以原始格式扫描时无法产生结果。通过尽可能多地提取文件,我通过查找泄漏的机密获得了更高的成功率。

5 — 通知已验证的密钥

一旦 Trufflehog 发现 repo 中泄露了机密,就该通过 Telegram 通知我了:

curl -F chat_id="XXXXXXXXXXXXX"
     -F document=@"$ORG_NAME.$REPO_NAME.secrets.txt"
     -F caption="New secerts - $ORG_NAME - $REPO_NAME"
'https://api.telegram.org/botXXXXXXXXXXXXX:XXXXXXXXXXXXX/sendDocument'

为什么选择 Telegram?IDK,这就是我的 Automation-Notify 首选工具。使用小型数据库构建小型后端会好得多,但谁在乎:)

6 – 删除存储库并继续
最后,自动化将删除存储库以节省空间,并移动到下一个存储库。

调查结果和付款

那么我发现了什么呢?数百个活动密钥泄露 — 除了真实的生产令牌外,我还遇到了公司精心植入的测试账户甚至金丝雀,以便在有人试图使用它们时收到通知。让我们分解一下我找到的所有内容:

最有趣的秘密

以下是我找到的最有趣的秘密和代币,以及我为它们获得的相关赏金的范围。赏金根据多种因素(如影响、代币范围以及受影响公司的漏洞赏金政策和支付表)而发生重大变化。

  • GCP 项目/AWS 生产代币
     — 5 美元 – 15 🔥🔥🔥 美元
  • Slack 代币
     — $3k-$10k 🔥🔥
  • Github 代币
     — $5k-$10k 🔥🔥
  • OpenAPI 令牌
     — 500 美元至 2000 🔥 美元
  • HuggingFace 代币
     — 500 美元至 2000 🔥 美元
  • Algolia 管理员令牌
     — 300 美元至 1000 🔥 美元
  • 电子邮件 SMTP 凭证
     — 500 USD – 1000 🔥 USD
  • 特定于平台的开发人员令牌和会话
     — 500 USD – 2000 🔥 USD

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

使用泄露的秘密,我能够访问超级敏感的数据

无趣的秘密

虽然我确实发现了许多有趣的代币,但一些活跃的代币与测试账户甚至金丝雀有关。事实证明,有一个非常好的网站叫做 CanaryTokens,它使您能够生成金丝雀代币并在有人尝试使用它们时收到通知。非常酷的主意。

其他一些不有趣和重复的令牌是丢弃帐户、用于测试的虚拟用户以及完全没有权限的 API 令牌,这些令牌被故意用于前端。每当我遇到这些时,我都会忽略它们,因为它们根本没有影响。

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

丢弃帐户和测试私钥并不有趣

让我们看几个例子:

  • Github 虚拟用户私钥
    :许多项目都在使用涉及虚拟 Github 用户的测试私钥。我遇到过几个在数百个存储库中重复出现的问题,例如 aaron1234567890123。
  • 丢弃账户
    :用作只读或绕过速率限制的账户。
  • Web3 API 开放代币
    :我见过数百个 web3 项目使用开放 API 密钥来查询不同区块链的交易或加密价格。最受欢迎的 API 代币是:Infura 和 Alchemy。
  • 前端 API 密钥:
    某些服务(如 Algolia)希望您在前端使用特定的 API 令牌。通常 Token 具有只读权限,无法修改或影响应用程序。当开发人员意外使用的角色和权限比预期多的令牌时,问题就开始了。例如,使用 Algolia 管理员令牌,而不是 Algolia 搜索令牌。
  • 金丝雀令牌
    :一些公司使用 Canary 令牌在使用它们时获取通知。有几个服务可以帮助解决这个问题,例如 CanaryTokens。

为什么秘密一开始就被泄露了?!

在分析了数十个实际影响案例后,我可以将这个问题归纳为三种解释——缺乏对 git 工作原理的了解,没有完全意识到由于二进制文件或隐藏文件而提交了什么,以及盲目信任 git rewrite-history 工具。

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

秘密泄漏的主要原因是二进制文件的删除
  • 缺乏对 git 工作原理的了解
    :有时开发人员不了解 git 如何存储信息 — 例如,开发人员提交了纯文本凭据/令牌/密钥。后来他们发现他们搞砸了,只是删除了 secret 或删除了文件,而没有撤销 secret。但是 git 会记住所有内容,因此通过重建所有已删除的文件,任何人都可以找到秘密。
  • 没有意识到里面有什么
    :我看到很多情况下,开发人员没有使用 .gitignore 并且不小心提交了二进制文件,例如包含机密的 .pyc(符合 python)文件。后来,他们删除了这些文件,而没有意识到这些文件包含混合了热密钥的二进制数据。在其他情况下,我看到隐藏文件(在以点开头的 linux 文件名中,如 .env)被提交或压缩到稍后提交的存档中。即使稍后删除了这些文件,信息仍然可以恢复,因此,密钥会泄漏。
  • 信任 git rewrite-history 工具
    :我还注意到一种情况,开发人员不小心将机密提交到他们的存储库中。后来他们明白了这个错误,删除了它们,并试图使用重写 git 历史工具来让这一切消失。但是,.pack 文件中仍有引用,我能够恢复密钥。幸运的是,我负责任地报告了这个问题,他们能够修复它而没有任何伤害。

大多数泄露的密钥是在已提交到存储库并后来删除的二进制文件中发现的。这些文件通常由编译器或自动化进程生成。一个常见的示例是文件,它是在某些 Python 解释器编译源代码时创建的 Python 字节码文件。这些往往是无意中犯下的。其他示例包括编译器生成的调试文件,例如文件,这些文件有时也会被错误提交。.pyc.pdb

总结

总的来说,这是一个非常有趣的项目!

我相信在本地克隆大量 GitHub 存储库并提取/恢复已删除的文件被证明是扫描和发现泄露机密的有效策略。

此外,我对 Git 内部结构有了更深入的了解,甚至在此过程中构建了几个自定义工具——其中 HexShare 是公开可用的。在此过程中,我还向多家财富 500 强公司报告了泄露的机密,并获得了大约 64 美元的奖励。

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

rust语言全栈开发视频教程-第一季(2025最新)

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

详细目录

mac/ios安全视频

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

QT开发底层原理与安全逆向视频教程

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

linux文件系统存储与文件过滤安全开发视频教程(2024最新)

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

linux高级usb安全开发与源码分析视频教程

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

linux程序设计与安全开发

我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
  • 我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
  • windows

  • 我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
  • windows()

  • 我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
  • USB()

  • 我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
  • ()

  • 我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
  • ios

  • 我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
  • windbg

  • 我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
  • ()

  • 我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

  • 我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

  • windows恶意软件开发与对抗视频教程

  • 我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
  • 我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事
  • 我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

原文始发于微信公众号(安全狗的自我修养):我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年4月28日10:02:38
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   我如何从已删除的文件中赚取 64 美元 — 一个漏洞赏金故事https://cn-sec.com/archives/4009190.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息