1. 程式人生 > >windows下sqli-labs的搭建及學習(GET篇)

windows下sqli-labs的搭建及學習(GET篇)

環境搭建:

需要搭建以下環境:

  1. apache+mysql+php
  2. Tomcat+mysql+java(部分關卡需要)

        apache的環境在windows下可以直接安裝wamp、phpstudy、apmserv等,我安裝的是wamp,安裝過程中可能會遇到一些問題:像是之前安裝過mysql,防火牆,埠被佔用了之類的,導致啟用不了或者logo出現紅色和橙色,可能需要改一些配置檔案,這個百度一下很容易解決

      tomcat的環境比較容易搭建,百度照著做不會出錯

安裝sql-libs:

     將之前下載的原始碼解壓到web目錄下,windows下的wamp解壓在www目錄下。

     開啟sql-connections/db-creds.inc檔案

     將資料庫的username和password修改為你自己的mysql賬號和密碼

     然後再訪問127.0.0.1的頁面,點選連結Setup/reset Database for labs建立資料庫

 

     然後就可以開始玩遊戲了~


實驗測試:

Less-1:基於錯誤的_get_單引號_字元型注入


     輸一個id值,返回了name和password,接著測試是否能注入,url後加上?id=',發現報錯了,直接報的資料庫的錯,對web瀏覽器使用者透明,那麼可以從報錯中得到很多資訊,比如這是個MySQL的資料庫,還可以猜想到後臺的sql語句,應該是“SELECT * FROM table_name WHERE id='$_get['id']' LIMIT 0,1”這種,說明他沒有過濾單引號,並且id是char型的輸入,之所以報錯是因為用了單引號,導致後面的部分“'LIMT 0,1;”多餘出來了


     於是構造sql語句-1‘OR’1'='1'--+遮蔽掉後面的,也可以用#遮蔽,但這裡#沒有被url編碼,故需自己將他轉成url編碼%23


      注入成功~接著來猜欄位,有3個欄位存在,再試試4個

     沒有第4個欄位了,即沒有第4列

     接著用union 語句爆欄位,但始終只顯示一條記錄,看了下原始碼,發現他並沒有將結果迴圈輸出,而是隻返回符合查詢結果的第一條記錄


     於是利用聯合查詢的特點,使原查詢左邊為空,那麼我們定義的查詢結果便可以返回出來

     於是我們可以通過這裡使用資料庫的函式來爆出資料庫的資訊,構造如下語句

     這裡用到的資料庫函式有cancat_ws(),char(),user(),database(),cancat_ws()是連線函式,第一個引數是分隔符,同樣作用的函式還有cancat(),不同的是cancat()沒有連線符,char()函式是將十進位制引數轉換成對應的acsii碼,user()和database()都是內建的函式,分別返回使用者名稱和資料庫名,類似的函式還有version(),返回資料庫的版本資訊,但是沒有直接返回表名的函式,所以需要通過其他方式獲取表名

     這裡有一個很經典的方法,我們可以通過系統資料庫information_schema來獲取表名,information_schema資料庫中含有很重要的三張表:SCHEMATA,TABLES和COLUMNS

     SCHEMATA表中儲存了MySQL中所有資料庫的資訊,包括資料庫名,編碼型別路徑等,show databases的結果取之此表

     TABLES表中儲存了MySQL中所有資料庫的表的資訊(當然,索引是根據資料庫名的),包括這個表是基本表還是系統表,資料庫的引擎是什麼,表有多少行,建立時間,最後更新時間等,show tables from schemaname的結果取之此表

     COLUMNS表中儲存了MySQL中所有表的欄位資訊,show columns from schemaname.tablename的結果取之此表

     於是,我們可以構造?id=-1' union select 1,2,table_name from information_schema where table_schema='security'#

     這樣就爆出了第一張表名,但要獲取所有表名還需要用到'limit',limit是用來指定範圍,他有兩個引數(limit a,b)a是從第幾行開始取,b是取多少行,但需要注意的是實際取出來的開始行下標比a大1,即limit 5,10是表示取6到15行資料,接下來我們就可以用它取指定範圍的表了


     這裡取的是第4張表,如果超出能取的範圍,他會報錯

     於是通過修改limit的範圍我們獲取到了所有的表名,且與資料庫中的表名一致,其中users表用來儲存使用者資訊的可能性最大,於是,我們可以用同樣的方法爆他的欄位名

     獲取到的欄位名有三個id,username,password,於是我們就可以構造語句了


     同樣的,改變limit的範圍以獲取所有使用者資訊

     還有一種方法是通過group分組代替limit將所有資訊列出來,查詢表名可以構造如下payload:

     查詢欄位也是同樣的

     最後的payload可以合併不同的列,上下對應輸出


Less-2:基於錯誤的_get_整型注入

     嘗試單引號:


     這裡的報錯與less-1不同了,從報錯可以看出,此處的id是當做數值來處理的,因為sql語句對於數字型的資料可以不加單引號,而less-1是作為字串來處理的,猜想後臺sql語句應該是select * from table_name where id = $_get['id'] limit 0,1於是構造-1 or 1=1


可以注入,接著用和之前相同的方法先報資料庫名,然後是表名,接著是欄位,最後的payload如下


Less-3:基於報錯的_get_單引號_變形_字元型注入


     看報錯,所謂變形就是用)代替了空格,猜想後臺sql是select * from table_name where id =('$_get['id']')limit 0,1於是構造-1')or'1'='1'--+


     最後的payload:


Less-4:基於錯誤的_get_雙引號_字元型注入


     嘗試單引號正常無報錯資訊,因為在php中雙引號可以包含單引號,輸入單引號後臺就變成了id=("$_GET['id']'")


     於是嘗試雙引號,檢視報錯資訊,猜想後臺sql語句為select * from table_name where id =("$_get['id']")limit 0,1;構造如下sql注入:


payload:


less-5:雙注入_get_單引號_字元型注入

     這個題很有意思,一開始我還是放原來的payload,已經準備好爆表名了,結果他給我的反應是這個


     什麼都沒有,然後注意到提示是“雙注入”,於是百度了一下,總結如下:

     雙查詢注入顧名思義形式上是兩個巢狀的查詢,即select ...(select ...),裡面的那個select被稱為子查詢,他的執行順序也是先執行子查詢,然後再執行外面的select,雙注入主要涉及到了幾個sql函式:

     rand()隨機函式,返回0~1之間的某個值

     floor(a)取整函式,返回小於等於a,且值最接近a的一個整數

     count()聚合函式也稱作計數函式,返回查詢物件的總數

     group by cluase分組語句,按照cluase對查詢結果分組

     雙注入的原理總的來說就是,當一個聚合函式後面出現group分組語句時,會將查詢的一部分結果以報錯的形式返回,他有一個固定的公式,於是payload構造如下:


     獲取到資料庫名後再用同樣的方法獲取表名


     然後是使用者資訊,這裡只能查詢一行,所以不能用group_concat,可以修改limit的範圍來遍歷使用者資訊


Less-6:雙注入_get_雙引號_字元型注入

     換湯不換藥,按照Less-5的方法,只是把單引號改成了雙引號,直接上payload:


Less-7:匯出檔案_get_字元型注入


     嘗試之前的方法行不通了,他把報錯做了處理統一返回“You have an error in your SQL syntax”,明顯的,他也給出了提示use outfile,outfile的固定結構是:select A into outfile B,這裡的B通常是一個檔案路徑,A可以是文字內容(小馬),也可以是資料庫資訊,於是這裡就有兩種思路:

     第一種,構造select * from users into outfile "資料庫匯入匯出資料的目錄"


     這真是一件很悲傷的事情...我的語句構造沒問題,但是F盤下就是沒有test.txt文件出現,於是查了一波資料,有一種說法是許可權問題,需要root許可權才能進行資料庫的讀寫操作,可以用這個語句來判斷: and (select count(*) from mysql.user)>0 ,如果回顯正常,就是表示最高許可權


     我是最高許可權呀,難道是路徑轉義的問題,又試一下


     還是沒有...好吧,放Mysql裡面白盒測一下


     報了一個錯,查了下資料,報錯原因是:Mysql資料庫需要在指定的目錄下進行資料的匯出,secure_file_priv這個引數用來限制資料匯入和匯出操作的效果,例如執行LOAD DATA、SELECT ... INTO OUTFILE語句和LOAD_FILE()函式。這些操作需要使用者具有FILE許可權。
     如果這個引數為空,這個變數沒有效果;
     如果這個引數設為一個目錄名,MySQL服務只允許在這個目錄中執行檔案的匯入和匯出操作。這個目錄必須存在,MySQL服務不會建立它;
     如果這個引數為NULL,MySQL服務會禁止匯入和匯出操作。這個引數在MySQL 5.7.6版本引入。

     於是查看了下secure_file_priv,然後換成他指定的目錄,還是有問題...然後想到路徑的轉義,OK,成功了,路徑下面也出現了1.txt


     但是,我們這個是通過白盒測試拿到的資料,在正常情況下,我們是不知道資料庫名和表名的,不過,原理也類似,可以結合前面用到的經典方法


     然後是表名


     欄位


     注意,這裡我為方便重複使用的2.txt,但每次都要刪除後才可以生成新的

     最後的payload:


     這裡除了用以前的order by判斷欄位數,還有一個方法,像下面這樣直接試就好了,只有欄位數剛好正確才會生成2.txt,多了少了都不行


     第二種,將一句話木馬寫入到檔案,用菜刀拿下網站


     這裡檔案字尾要改成.php(我懶得換圖了),然後用菜刀連線,由於我這臺機沒裝菜刀,所以就不截圖了,大致意思就是這樣,下面來擴充套件一下匯入匯出資料還會涉及到哪些函式:

     @@datadir:資料庫儲存路徑

    @@basedir:MySQL安裝路徑

     dumpfile:匯出檔案,類似outfile,不同的是,dumpfile一次匯出一行,會和limit結合使用

     load_file():將檔案匯入mysql,用法 select load_file("檔案路徑");

Less-8:bool型_單引號_盲注

     首先嚐試less-7的方法,沒問題


     接著探索新姿勢,正常輸入返回“You are in......”,嘗試單引號卻什麼都沒返回,看了下原始碼就是這樣處理的,點題盲注

     盲注主要分為bool型和時間性,通常涉及到這幾個函式:

     length(str):返回字串str的長度

     substr(str,pos,len):將str從pos位置開始擷取len長度的字元返回,需要注意的是這裡pos的是從1開始的

     mid(str,pos,len):和substr()類似

     ascii(str):返回字串str最左邊的acsii碼(即首字母的acsii碼)

     ord():同上,返回acsii碼

     left(str,len):對字串str左擷取len長度

     right(str,len):對字串str右擷取len長度

     if(a,b,c):條件判斷,如果a為true,返回b,否則返回c

     盲注有個固定式:and ascii(substr(A,1,1))>B,或者and if(ascii(substr(A,1,1))>B,1,0),這裡的A通常是一個select語句,B則是字元或數字的ascii碼,他們的中心思想都是通過substr等擷取函式以二分法的形式查詢逐個匹配想要的資訊,這個過程通常都很耗時,所以建議直接寫個盲註腳本來跑

     下面是盲注匹配的一個例子,我們來匹配資料庫名,在之前的實驗中已知資料庫名是security,下面的sql語句是用來匹配資料庫名的第一個字母


     字母s的ascii碼是115,所以他大於114,結果為true,頁面顯示正常


     這裡大於了115,結果為false,頁面顯示異常,好,接下來直接寫個盲註腳本,跑出來結果如下:


Less-9:時間型_單引號_盲注

     時間型盲注和bool型盲注應用場景不同之處在報錯的返回上,從less-8我們知道,輸入合法時他會返回正常頁面“You are in......”,而非法輸入時他沒有返回任何東西,於是,我們可以根據這個特點跑盲注,通過他不同的返回頁面來判斷我們匹配的字元是否正確,而在less-9中合法輸入他返回如下


     非法輸入也是返回該頁面


     這樣,我們就不能根據他頁面的返回內容來判斷匹配結果了,因此我們需要用延時函式sleep()對兩種輸入進行區分,可以構造如下語句:

     ?id=1andif(ascii(substr(database(),1,1))>1150, sleep(5))%23

     這裡的意思是,如果資料庫名首字母的ascii碼大於115,那麼執行sleep(5),延時5秒,此時標籤欄會變成緩衝,於是,我們就可以判斷匹配的結果了,盲註腳本與less-8類似,只需要加入sleep函式即可

Less-10:時間型_雙引號_盲注

     把上面payload中的單引號改成雙引號就可以了,如:

     ?id=1" andif(ascii(substr(database(),1,1))>1150, sleep(5))%23

參考文獻:

http://www.freebuf.com/articles/web/34619.html

http://blog.csdn.net/u012763794/article/details/51207833

http://blog.itpub.net/26506993/viewspace-2121850/