如何在php中防止sql注入?
高翔翻譯
q:如果把使用者輸入的沒有任何改動的放到sql的查詢語句中,很有可能會導致sql注入,比如說下面的例子:
$unsafe_variable = $_post['user_input'];
mysql_query("
insert
into
`table`
(`column`
) values
('$unsafe_variable'
)");··
3 為什麼會有注入漏洞呢?因為使用者可以輸入
value'); drop table table;--
然後查詢語句就變成了這樣
insert
into
`table`
(`column`
) values
('value'
);drop
table
table
;--')· 1
到底我們能做什麼去防止sql注入呢?
a:通過使用預編譯語句(prepared statements)和引數化查詢(parameterized queries)。這些sql語句從引數,分開的傳送到資料庫服務端,進行解析。這樣黑客不可能插入惡意sql**。
有兩種方式去完成這個:
1. 使用pdo物件(對於任何資料庫驅動都好用)
$stmt
= $pdo
->prepare(
'select * from employees where name = :name');
$stmt
->execute(
array
('name'
=>
$name
));
foreach
($stmt
as$row) ·
2. 使用mysqli ·
2 $stmt
=$dbconnection->prepare(
'select * from employees where name = ?'
);$stmt->bind_param(
's',
$name);
$stmt->execute();
$result
=$stmt->get_result();
while
($row
=$result->fetch_assoc())
如果你鏈結的資料庫不是mysql,你可以參考具體資料庫所提供的其他選項,例如(pg_prepare() and pg_execute() for postgresql)
pdo是乙個通用的選項。
注意:當使用pdo去連線mysql資料庫時,真正的預處理預設並沒有開啟。為了開去他,你應該關閉模擬的預處理語句,以下是乙個例子:
$dbconnection
=new
pdo(
'mysql:dbname=dbtest;host=127.0.0.1;charset=utf8'
, 'user'
, 'pass');
$dbconnection->setattribute(pdo
::attr_emulate_prepares
, false
);$dbconnection->setattribute(pdo
::attr_errmode
, pdo
::errmode_exception
);· 4
在上面的例子裡,錯誤模式嚴格意義上來說沒有必要,但推薦你加上去。這樣,指令碼在遇到致命錯誤(fatal error)的時候並不會停止執行。並且給開發者去捕獲(catch )那些pdoexception異常。
第乙個setattribute()是必須的。這告訴pdo去關閉模擬預處理,然後使用真正的預處理語句。這將保證語句和值在被交到mysql伺服器上沒有被解析(讓攻擊者沒有機會去進行sql注入。)
儘管你可以在建構函式裡設定字符集(charset ),但你也要注意舊版本的php(<5.3.6)會忽略在dsn中設定的字符集引數。
到底發生了什麼呢?你的sql語句交給prepare 之後被資料庫伺服器解析和編譯了。通過制定引數(不管是?還是命名佔位符:name),你都可以告訴資料庫引擎**你想過濾掉。然後當你執行execute方法時,預處理語句會把你所指定的引數值結合襲來。
這裡很重要的就是引數值和編譯過的語句繫結在了一起,而不是簡簡單單的sql字串、sql注入通過騙起指令碼加入一些惡意的字串,在建立sql傳送到資料庫的時候產生後果。所以,通過分離的從引數中傳送真正的sql語句,你控制了風險:在結尾的時候你不打算幹的一些事。(譯者注:請看開篇的例子)。當你使用預編譯的時候,任何引數都會被當作字串。在這個例子裡,如果$name變數包含了』sarah』; delete from employees 這個結果只會簡單的搜尋字串「『sarah』; delete from employees」,所以你不會得到一張空表。
另外乙個使用預編譯的好處就是,如果你在同乙個會話中執行乙個statement多次,只會被解析和編譯一次,對速度更友好。
哦,既然你問了增加語句的時候怎麼使用,下面給你個例子:
$preparedstatement
=$db->prepare(
'insert into table (column) values (:column)');
$preparedstatement->execute(
array
('column'
=>
$unsafevalue
));· 2·
3當你仍然使用預處理作為查詢的引數是,動態查詢的結構不能被引數化,自然查詢特徵不能被引數化,所以最好的就是設定乙個白名單過濾器去限制可能的值。
// value whitelist
// $dir
can only be
'desc'
or'asc'
$dir
= !empty(
$direction
) ?
'desc'
: 'asc';
如何在PHP中防止SQL注入?
如何在php中防止sql注入?q 如果把使用者輸入的沒有任何改動的放到sql的查詢語句中,很有可能會導致sql注入,比如說下面的例子 unsafe variable post user input mysql query insert into table column values unsafe ...
php中如何防止sql注入
1.什麼時候最易受到sql注入攻擊 當應用程式使用輸入內容來構造動態sql語句,以訪問資料庫時會發生sql注入攻擊 2.如何防止sql注入 a.永遠不要相信使用者的輸入,對使用者輸入進行校驗,可以通過正規表示式,或限制長度,對單引號和 進行轉換 不建議使用 user htmlspecialchars...
php如何防止SQL注入
說明 判斷傳遞的變數中是否含有非法字元 如 post get 功能 防注入 要過濾的非法字元 arrfiltrate array union add 出錯後要跳轉的url,不填則預設前一頁 是否存在陣列中的值 function funstringexist strfiltrate,arrfiltra...