SQL防注入

目標:編寫動態的SQL查詢

動態查詢便是指將變量放到語句中,將固定的字符串和變量拼接在一塊兒,組成一個完整的SQL查詢語句,因爲變量的值是動態變化的,所以查詢也是動態的。編寫這樣的可以執行的動態的查詢語句是十分天然的,也很是方便。可是,不經思考的加入也會帶來很大的安全隱患。例如這樣的一個查詢:php

SELECT × FROM Bugs WHERE bug_id = $bug_id";

若是這個時候$bug_id = "1234; DELETE FROM Bugs",Bugs表就跪了。所以SQL注入的危害至關大,不能將未經驗證的輸入做爲代碼執行。mysql

作法

沒有一種技術可以徹底的抵抗SQL注入,所以,須要將多種作法結合起來正則表達式

轉義

轉移能防止一些意外的狀況,例如這個查詢:sql

SELECT * FROM Projects WHERE project_name = '$project_name'

若是$project_name = O'Hare(這是很正常的一種狀況),因爲名字裏面有個引號,查詢就變成:數據庫

SELECT * FROM Projects WHERE project_name = 'O'Hare'

這個時候數據庫就會由於多了個引號而出錯,所以須要在名字裏面的'前加反斜槓。數組

參數化查詢

參數化查詢是指在編寫查詢語句的時候,在須要參數的位置上使用參數佔位符,而後查詢的時候提供這一參數。以php爲例:安全

<?php

$sql = "SELECT * FROM Projects WHERE project_name = ?";
$stmt = mysqli_prepare($con, $sql);
mysqli_stmt_bind_param($stmt, 's', $_POST['name']);
mysqli_stmt_execute($stmt);

簡單來講,數據庫接到一個指令,大體是這麼作的:函數

  1. 編譯SQL生成執行計劃優化

  2. 選擇執行計劃code

  3. 執行

SQL注入不少狀況是增長查詢語句,增長查詢語句就會形成查詢的語義發生變化(就是說編譯會生成不一樣的東西)。若是使用參數化查詢,在準備查詢語句的時候數據庫就去編譯,而後提供參數就會重用這個編譯結果,即便使用了注入變量,語義也不會發生變化(不會從新編譯),同時,傳參的時候,數據庫也會將變量進行過濾,以達到防止注入的效果。

參數化查詢也有作不到的東西:
1.多個值的列表不能做爲單一參數
若是編寫這麼一個查詢:

SELECT * FROM Bugs WHERE bug_id IN (?)

那麼你傳遞參數的時候不能是「1234,3456,5678」這樣的,這樣會被認爲是一個字符串
2.表名,列名,SQL關鍵字不能做爲參數

過濾輸入內容

應該將全部不合法的字符去掉,而不是找是否有些輸入包含了危險的內容。
好比說若是是須要一個整數,就應該只是用變量裏面的整數部分,(在Php裏面有filter擴展),能夠直接用類型轉換函數,也能夠用正則表達式匹配

給動態輸入的值加引號

通常都用參數化查詢,可是有時候,參數化查詢會致使數據庫採用錯誤的優化方案(多是採用錯誤的索引)。好比說表裏面有一列99%的都是TRUE,那麼用因此很快就能查詢到那1%的FALSE。這個時候將變量直接插進去是好的作法。但這個時候就要格外當心的引用字符串。在php裏面可使用PDO::quote()

用戶與代碼的隔離

好比說,你想要讓用戶選擇究竟是按什麼關鍵字排序,是升序排序,仍是按降序排序,這個時候你從客戶端接受兩個參數

<?php
$sort_standard = $_POST['order'];
$direction = $_POST['direction'];
$sql = "SELECT * FROM Bugs ORDER BY $sort_standard $direction";
mysqli_query($con, $sql);

可是這個並非一個安全的作法,由於用戶能夠傳遞任意值。可是參數化查詢又不能是關鍵字,採用這樣的作法:

先聲明$sort_standard和$direction數組,好比這樣

$sort_standard = array(
    "status" => "status",
    "date" => "date_report"
);
$direction = array(
    "up" => "ASC",
    "down" => "DESC"
);

當判斷到用戶的選擇不在數組中的時候就使用默認值,若是在數組中就用對應值,這樣作:

  1. 從不使用用戶的輸入進行查詢,減小了注入風險

  2. 讓語句動態化,而沒有語法上的限制

  3. 將數據庫查詢和用戶界面解藕

相關文章
相關標籤/搜索