得到题目输入1,返回一个数组
不由得让我想起春秋战役里面的堆叠注入
经过尝试(‘),(“)都被过滤了
简单试一试输入,发现有三种回显,分别位’nonono’,空以及返回array
在这里,很多都被返回了nonono,我想应该是被过滤了,但是太多我们都不可能一一尝试,所以跑一下字典
很明显,507的应该是被过滤的字符。由于和春秋战役太相似,春秋战役直接给我来了个正则很长。这咋办。
所以我们试试堆叠注入
果然返回来了,那无疑是堆叠注入了
但是。接下来有个头疼的地方了,flag这个被过滤了
怎么爆字段。发现有源码:
<?php
session_start();
include_once "config.php";
$post = array();
$get = array();
global $MysqlLink;
//GetPara();
$MysqlLink = mysqli_connect("localhost",$datauser,$datapass);
if(!$MysqlLink){
die("Mysql Connect Error!");
}
$selectDB = mysqli_select_db($MysqlLink,$dataName);
if(!$selectDB){
die("Choose Database Error!");
}
foreach ($_POST as $k=>$v){
if(!empty($v)&&is_string($v)){
$post[$k] = trim(addslashes($v));
}
}
foreach ($_GET as $k=>$v){
}
}
//die();
?>
<html>
<head>
</head>
<body>
<a> Give me your flag, I will tell you if the flag is right. </ a>
<form action="" method="post">
<input type="text" name="query">
<input type="submit">
</form>
</body>
</html>
<?php
if(isset($post['query'])){
$BlackList = "prepare|flag|unhex|xml|drop|create|insert|like|regexp|outfile|readfile|where|from|union|update|delete|if|sleep|extractvalue|updatexml|or|and|&|\"";
//var_dump(preg_match("/{$BlackList}/is",$post['query']));
if(preg_match("/{$BlackList}/is",$post['query'])){
//echo $post['query'];
die("Nonono.");
}
if(strlen($post['query'])>40){
die("Too long.");
}
$sql = "select ".$post['query']."||flag from Flag";
mysqli_multi_query($MysqlLink,$sql);
do{
if($res = mysqli_store_result($MysqlLink)){
while($row = mysqli_fetch_row($res)){
print_r($row);
}
}
}while(@mysqli_next_result($MysqlLink));
}
?>
看到mysql_multi_query(),可以堆叠注入
那确实,但是他妈的被过滤了咋整
我们发现,查询语句为
通过堆叠注入sql_mode的值为PIPES_AS_CONCAT
这里解释一下PIPES_AS_CONCAT
这句话sql语句的意思是开启mysql中支持管道符来进行字符串的拼接操作
简单准备的原始数据表:
没有开启这个模式的时候
开启了这个模式后
可以从上图看到,数据表中的数据被带出来了,下面这张图更清晰
从而将 || 视为字符串的连接操作符而非或运算符,所以构造出来
只输入数字进行查询是因为,执行数字时有回显,判断是执行成功的,查询字符串则会报错,一般来说php会设置默认不显示报错信息,因此使用数字查询开启这个模式来手动构造注入漏洞
这样在进行查询的时候将||运算符当成连接符成这样的语句
select 1,flag from Flag