Git和Git文件导致源码泄露

参考文章

Git文件泄露漏洞:https://blog.csdn.net/qq_45521281/article/details/105767428

什么是Git

Git是目前世界上最先进的免费开源分布式版本控制系统,其诞生主要是为了高效管理像 Linux 内核这种规模的庞大项目

什么是版本控制系统

版本控制系统(Version Control System,VCS)是一种在软件开发过程中用于管理文件和项目版本的工具,可以记录文件内容的变化,让用户查看特定版本的文件内容,还能再不同版本之间进行切换,同时也方便团队成员协作开发

版本控制系统类型有:本地版本控制系统、集中式版本控制系统、分布式版本控制系统

本地版本控制系统

这种系统只在本地对文件的不同版本进行管理。它会在本地保存文件的多个版本,通过简单的数据库来记录文件的更新。例如 RCS(Revision Control System),它在本地磁盘上保存补丁集(文件修订前后的差异),通过应用这些补丁集来重现文件的各个版本。

集中式版本控制系统

该系统有一个集中管理的服务器,保存所有文件的修订版本,而协同工作的开发者们的客户端则从服务器获取最新的文件或者提交更新。SVN(Subversion)就是典型的集中式版本控制系统。其优点是方便管理员对版本库进行管理,缺点是依赖中央服务器,若服务器出现故障,团队成员就无法正常工作。

分布式版本控制系统

每个开发者的本地都有完整的版本库副本,包含所有的历史版本信息。Git 是分布式版本控制系统的代表。在分布式系统中,开发者可以在本地进行各种版本控制操作,如提交、创建分支等,不需要依赖网络连接到中央服务器。团队成员之间的协作可以通过推送和拉取操作在不同的本地仓库之间进行。

版本库、工作区和暂存区

版本库

版本库(Repository),也被称作仓库,是版本控制系统的核心组件,用于存储项目的所有文件及其历史版本信息,集中存储项目所有文件版本信息的地方,版本控制系统会对文件的每一次修改进行记录,包括修改的内容、时间、作者等,这些信息都被保存在版本库中。

版本库可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

本地版本库

存在于开发者本地计算机中的版本库。开发者可以在本地对版本库进行各种操作,如提交、查看历史记录等,无需依赖网络连接。例如使用 Git 时,在项目目录下执行git init命令就会在本地创建一个版本库。

远程版本库

存储在远程服务器上的版本库,通常用于团队协作开发。团队成员可以从远程版本库克隆项目到本地,进行开发后再将本地的修改推送到远程版本库,与其他成员共享。像 GitHub、GitLab 等平台提供的就是远程版本库服务。

工作区

工作区指的是你在本地计算机里实际操作的项目目录,就是你能够看到并进行文件编辑、创建、删除等操作的文件夹,简单的说就是电脑中看到的目录。

在工作区,你能自由修改文件内容,它独立于版本控制系统的其他部分。版本控制系统一开始并不会自动跟踪你在工作区的修改,只有当你执行特定操作时,这些修改才会被纳入版本控制流程。

假设你使用 Git 管理一个名为my_project的项目,在本地磁盘上的C:\Users\Username\my_project目录就是工作区。你可以在这个目录下使用文本编辑器打开文件进行修改,或者创建新文件。

暂存区

暂存区也被叫做索引(index),它是一个中间区域,用于准备要提交到本地仓库的文件修改。当你对工作区的文件进行修改后,可选择将部分或全部修改添加到暂存区。

暂存区再版本库里,版本库就是隐藏目录 .git

分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。

现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。

.git文件导致的源码泄露

原理

开发人员再开发时,常常会先把源码提交到远程托管网站(如:github),最后再从远程托管网站把源码pull到服务器的web目录下,如果忘记删除.git文件,就会导致源码泄露,攻击者就可能会将.git文件夹直接部署到线上环境,这就引起了git泄露漏洞

git的目录结构

在一个目录中初始化一个仓库以后,Git会在该目录下创建一个名为.git的隐藏目录(版本库),这个目录中包含了Git仓库的所有元数据和对象数据库(就是这个仓库的所有版本等一系列信息),如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.git/
├── branches/ # 旧的分支引用目录,现在基本不再使用
├── config # 仓库的配置文件,包含仓库级别的配置信息
├── description # 仓库的描述信息,主要供GitWeb等工具使用
├── HEAD # 指向当前所在分支的引用
├── hooks/ # 存放钩子脚本的目录,用于在特定的Git操作前后执行自定义脚本
├── info/ # 包含一些仓库的额外信息
│ └── exclude # 本地的忽略文件,作用类似于 .gitignore
├── objects/ # 存储所有对象数据的目录,如提交对象、树对象、Blob对象等
│ ├── info/
│ └── pack/
├── refs/ # 存储引用的目录,如分支、标签等
│ ├── heads/ # 存储本地分支的引用
│ ├── tags/ # 存储标签的引用
│ └── remotes/ # 存储远程分支的引用
└── index # 暂存区文件,记录了下一次提交时要包含的文件信息

一般来说一个git仓库会存在以下俩文件

  1. README.md (项目介绍)
  2. .gitignore (配置在git进行文件跟踪的时候忽略掉哪些文件 , 从这个文件一般也可以得到一部分网站的目录结构 , 或者一些日志/配置文件等敏感文件)

一般情况下的开发流程

  1. 初始化仓库 , 并将仓库托管在Coding或者Github上 , 便于远程协作/备份/部署
  2. 在本地进行网站开发 , 并定时提交commit , push到远程托管网站
  3. 当一个阶段的开发差不多的时候 , 需要远程登陆服务器 , 通过托管网站再将发行版网站pullWeb目录下
  4. 网站正常运行

这里当网站维护开发人员在从托管网站pull代码的时候,也会将这个存储了所有版本信息的.git文件夹下载到服务器的Web目录下,因此攻击者就可以利用这个目录去下载git文件夹,可以利用其中存储的版本控制信息,完全恢复网站后台的代码和目录结构

如何利用漏洞

利用爬虫

爬虫爬取整个git目录 (这个方法比较原始 , 需要具有一定的Git经验 , 和使用Githack这个工具相比 , 有一个比较好的地方就是 , 可以完全模拟服务器上的代码环境 , 可以跟踪到git的每一次提交 , 但是Githack好像只可以将源码恢复到最近的一次提交,这里的好处还有可以去查看git的提交日志 , 这个日志信息中会有开发人员对每一次commit的描述 , 比如某个BUG的修复等等 , 对于这些和BUG相关的地方 , 可以有针对性地进行白盒审计 , 有可能这个BUG修复了还不如没修复 , 可能会造成更大的漏洞)

具体思路

  1. 利用爬虫递归下载.git目录的所有文件
  2. 利用git命令对网站的commit历史进行查看
  3. 利用git命令对网站的源码进行恢复

具体操作

演示网站 : http://www.xxx.com/.git/

  1. 在虚拟机中利用wget对该目录进行递归下载(-r)
1
2
3
4
5
wget -r -p -np -k http://www.xxx.com/.git/
--recursive(递归)
-k, --convert-links(转换链接)
-p, --page-requisites(页面必需元素)
-np, --no-parent(不追溯至父级)
  1. 下载完成后 , 进入下载的网站目录
  2. 利用命令 : git log 查看网站的提交记录
  3. 利用命令 : git reset --hard [log hash] 恢复到指定版本号 (一般如果只需要得到源码的话就恢复到最近的一次提交)

如何防御

  1. 对.git目录的访问权限进行控制
  2. 在每次pull到web目录下之后删除.git文件夹

利用GitHack脚本

GitHack是一个.git泄露利用脚本,通过泄露的.git文件夹下的文件,还原重建工程源代码。

GitHack脚本下载地址:https://github.com/lijiejie/GitHack

GitHack脚本的工作原理

  1. 解析.git/index文件,找到工程中所有的: ( 文件名,文件sha1 )
  2. .git/objects/文件夹下下载对应的文件
  3. 使用zlib解压文件,按原始的目录结构写入源代码

使用方法

1
python GitHack.py http://www.example.com/.git/     #别忘了最后的.git

还原后的文件在 dist/ 目录下

工作流程

  1. 尝试获取 packs克隆
  2. 尝试目录遍历克隆
  3. 尝试从缓存文件(index)、commit记录中恢复

CTF做题实战

题目一

题目来源

ctfshow 萌新赛 给她

image-20250330214346166

看着是要SQL注入,但实际上是要进行.git泄露,这里用GitHack脚本进行泄露

1
python GitHack.py https://6d6e5822-a557-4a9a-96c9-4a46aacb1c63.challenge.ctf.show/.git/

image-20250330214644843

image-20250330214714870

可以看到源码下载到了这个hint.php文件中了,源码如下

1
2
3
4
<?php
$pass=sprintf("and pass='%s'",addslashes($_GET['pass']));
$sql=sprintf("select * from user where name='%s' $pass",addslashes($_GET['name']));
?>

这里考查sprintf漏洞,之后的见另一个笔记sprintf漏洞

题目二

题目来源

NSSCTF–git泄露

image-20250331132139456

利用GitHack脚本下载得到源码

1
python GitHack.py http://node4.anna.nssctf.cn:28510/.git/

源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
if ($_GET['wher3'] === 'nssc7f') {
echo getenv('FLAG');
}
?>
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>NSSCTF | .git泄露</title>

</html>

<body>flag在哪里?</body>

image-20250331132315777


Git和Git文件导致源码泄露
https://yschen20.github.io/2025/04/25/Git和Git文件导致源码泄露/
作者
Suzen
发布于
2025年4月25日
更新于
2025年4月29日
许可协议