一、什麼是SQL注入
- 服務器沒有嚴格的校驗客戶端發送的數據,導致將用戶精心構造的數據作爲 SQL 語句執行,從而導致數據庫的內容被修改或泄露。
二、如何探測sql注入點
- 用戶的輸入能是否改變顯示的內容,如果能夠改變說明後臺對輸入有處理
- 例如,傳回的數據有沒有改變、是否存在顯示的內容、以及其它一些不可見的信息
- 構建一條絕對出錯的輸入('")(),查看當前頁面的返回內容
- 如果報錯了,就說明用戶輸入的內容會被作爲sql指令的一部分
- 嘗試對SQL指令進行閉合,並且構建出相關的語法,查詢自己需要的內容
- 閉合實際就是猜測後臺使用的SQL指令
三、如何獲取信息
- 通過聯合查詢注入的方式,獲取到想要得到的信息(返回了查詢到的信息)
- 在進行聯合查詢的時候,兩條查詢語句的列數必須是相同的
- SELECT * FROM xxx UNION SELECT 1,2,3,...; 直到不報錯
- SELECT * FROM xxx ORDER BY N; 直到報錯爲止
- 有時,網頁上只會顯示查詢到的第一條內容,此時在使用聯合查詢的時候,我們是看不到自己構建的查詢語句查詢到的內容的,可以通過將默認的查詢條件設置爲查不到來顯示自己的內容。
- SELECT * FROM USER WHERE id=-1 UNION SELECT 1,2,3;
- 並不是所有查詢到的內容都會被顯示出來,我們需要結合頁面利用聯合查詢中的字段
- SELECT * FROM USER WHERE id=-1 union SELECT 1,version(),database()
- 在進行聯合查詢的時候,兩條查詢語句的列數必須是相同的
- 報錯注入方式(必須有報錯信息)
- updatexml(str, xpath, str): 函數的作用是解析 xpath 語法進行內容的替換
- xpath 中 ~是絕對報錯的,後續可以拼接自己想要查詢的語句,注意需要加()
SELECT UPDATEXML(0, concat('~',(SELECT GROUP_CONCAT(COLUMN_NAME) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='security' AND TABLE_NAME='users')), 0)
- 缺點,只能獲取到最多32字符的數據
SELECT UPDATEXML(0, concat('~',(SELECT SUBSTR((SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.TABLES), 32, 32))), 0)
- extractvalue:使用方式和 UPDATEXML 完全一致,但是少了第三個參數
- 雙注入(8.0不支持):
SELECT COUNT(*) FROM TABLE GROUP BY FLOOR(RAND(0)*2);
- rand()函數的參數一定要寫成0,否則概率性失效
- floor(rand(0) * 2) 得到的結果必然是 0 或者 1
- count(*) 配合 group by 會產生虛擬表,就是虛擬表部分出現了問題導致了錯誤
- 0 是否存在 FLOOR(RAND(0) * 2),不存在
- 1 創建 FLOOR(RAND(0)*2),1
- 1 是否存在 FLOOR(RAND(0)*2),存在
- 0 是否存在 FLOOR(RAND(0)*2),不存在
- 1 創建 FLOOR(RAND(0)*2),鍵是唯一的,所以報錯(報錯的是鍵名)
- updatexml(str, xpath, str): 函數的作用是解析 xpath 語法進行內容的替換
四、我們能夠獲取到什麼信息
- 最基本的信息,例如 version() database() user() 等
- 通過 information_schema 獲取數據庫中的所有 數據庫名、表名、字段名
- SCHEMATA: 保存了所有數據庫的信息
SELECT * FROM information_schema.SCHEMATA
- TABLES:保存了數據庫和表的對應關係
SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE()
- COLUMNS: 保存了指定數據庫的表和字段的對應關係
SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='USER';
五、一些問題
- 爲什麼不使用 # 進行注入?
- 並不是通用的註釋,它只能被用於 mysql 數據庫
- 直接寫在 URL 中時,表示的是錨點跳轉,使用需要轉義 %23
六、涉及的函數
- version(): 當前的數據庫版本
- database(): 當前所使用的數據庫
- user(): 當前的用戶名和主機名
- group_concat(): 拼接查詢到的所有結果爲一個字符串
- concat: 拼接任意個數的字符串
- substr: 截取指定字符串中的一部分
- count:用於分組查詢,計算每一組查詢到了多少條內容
- floor:向下取整函數
- rand:隨機數函數,返回的是一個0~1的隨機小數