天天看點

SQL注入--寬位元組注入什麼是寬位元組使用寬位元組注入的前提什麼是寬位元組注入注入案例(來自pikachu的SQL寬位元組注入)防禦

什麼是寬位元組

當某字元的大小為一個位元組時,稱其字元為窄位元組

當某字元的大小為兩個位元組時,稱其字元為寬位元組

所有英文預設占一個位元組,漢字占兩個位元組

常見的寬位元組編碼:GB2312,GBK,GB18030,BIG5,Shift_JIS等等

使用寬位元組注入的前提

  1. 資料庫使用了gbk編碼
  2. 使用了過濾函數,将使用者輸入的單引号轉義(mysql_real_escape_string,addslashes)

    這樣被處理後的sql語句中,單引号不再具有‘作用’,僅僅是‘内容’而已,換句話說,這個單引号無法發揮和前後單引号閉合的作用,僅僅成為‘内容’,具體如下:

select * from users where id = ' 1 ' ;
 
 若注入語句為:1' order by 2#
 
 通過過濾函數拼接到sql語句中變為:1\' order by 2#
 即:select * from users where id = ' 1\' order by 2#;

 使'失效
           

什麼是寬位元組注入

繞過對于使用者輸入單引号等特殊符号的轉義處理,使轉義符号與輸入的字元結合形成一個新的字元,進而使單引号逃脫轉義處理,進行注入。

要繞過這個轉義處理,使單引号發揮作用,有兩個思路:

  1. 讓斜杠(\)失去作用:對斜杠(\)轉義,使其失去轉義單引号的作用,成為‘内容’
  2. 讓斜杠(\)消失:寬位元組注入
SQL注入--寬位元組注入什麼是寬位元組使用寬位元組注入的前提什麼是寬位元組注入注入案例(來自pikachu的SQL寬位元組注入)防禦

當使用寬位元組編碼,如:GBK時,兩個連在一起的字元會被認為是漢字,我們可以在單引号前加一個字元,使其和斜杠(\)組合被認為成漢字,從未達到讓斜杠消失的目的,進而使單引号發揮作用

注意:前一個字元的Ascii要大于128,兩個字元才能組合成漢字

例如:129=0x81,加%即可,即%81’

注入案例(來自pikachu的SQL寬位元組注入)

通過%df與\組成漢字來使單引号逃逸,擷取資料庫名字

SQL注入--寬位元組注入什麼是寬位元組使用寬位元組注入的前提什麼是寬位元組注入注入案例(來自pikachu的SQL寬位元組注入)防禦

擷取表名

SQL注入--寬位元組注入什麼是寬位元組使用寬位元組注入的前提什麼是寬位元組注入注入案例(來自pikachu的SQL寬位元組注入)防禦

擷取資料庫中第二張表的字段名

注意:本來這裡應該是table_name=‘users’,但因為對單引号進行了轉義處理,是以不能使用’user’

但是可以通過嵌套一個select來查詢到表名

SQL注入--寬位元組注入什麼是寬位元組使用寬位元組注入的前提什麼是寬位元組注入注入案例(來自pikachu的SQL寬位元組注入)防禦

擷取字段值

SQL注入--寬位元組注入什麼是寬位元組使用寬位元組注入的前提什麼是寬位元組注入注入案例(來自pikachu的SQL寬位元組注入)防禦

防禦

  1. 先調用mysql_set_charset函數設定連接配接所使用的字元集為gbk,再調用mysql_real_escape_string來過濾使用者輸入
  2. 将character_set_client設定為binary(二進制)

SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary

這幾個變量是什麼意思?

當我們的mysql接受到用戶端的資料後,會認為他的編碼是character_set_client,然後會将之将換成character_set_connection的編碼,然後進入具體表和字段後,再轉換成字段對應的編碼。然後,當查詢結果産生後,會從表和字段的編碼,轉換成character_set_results編碼,傳回給用戶端。

是以,我們将character_set_client設定成binary,就不存在寬位元組或多位元組的問題了,所有資料以二進制的形式傳遞,就能有效避免寬字元注入。

SQL注入--寬位元組注入什麼是寬位元組使用寬位元組注入的前提什麼是寬位元組注入注入案例(來自pikachu的SQL寬位元組注入)防禦

許多内容參考自此

繼續閱讀