如何在PHP中防止SQL注入?

2021-07-16 19:54:53 字數 2931 閱讀 3915

如何在php中防止sql注入?

q:如果把使用者輸入的沒有任何改動的放到sql的查詢語句中,很有可能會導致sql注入,比如說下面的例子:

$unsafe_variable = $_post['user_input']; 

mysql_query("insert

into

`table` (`column`) values ('$unsafe_variable')");

為什麼會有注入漏洞呢?因為使用者可以輸入value'); drop table table;--然後查詢語句就變成了這樣

insert

into

`table` (`column`) values('value');

drop

table

table;

--')

到底我們能做什麼去防止sql注入呢?

a:通過使用預編譯語句(prepared statements)和引數化查詢(parameterized queries)。這些sql語句從引數,分開的傳送到資料庫服務端,進行解析。這樣黑客不可能插入惡意sql**。

有兩種方式去完成這個:

使用pdo物件(對於任何資料庫驅動都好用)

$stmt = $pdo->prepare('select * from employees where name = :name');

$stmt->execute(array('name' => $name));

foreach ($stmt

as$row)

2. 使用mysqli
$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);

在上面的例子裡,錯誤模式嚴格意義上來說沒有必要,但推薦你加上去。這樣,指令碼在遇到致命錯誤(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));

當你仍然使用預處理作為查詢的引數是,動態查詢的結構不能被引數化,自然查詢特徵不能被引數化,所以最好的就是設定乙個白名單過濾器去限制可能的值。

// 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 un...

php中如何防止sql注入

1.什麼時候最易受到sql注入攻擊 當應用程式使用輸入內容來構造動態sql語句,以訪問資料庫時會發生sql注入攻擊 2.如何防止sql注入 a.永遠不要相信使用者的輸入,對使用者輸入進行校驗,可以通過正規表示式,或限制長度,對單引號和 進行轉換 不建議使用 user htmlspecialchars...

php如何防止SQL注入

說明 判斷傳遞的變數中是否含有非法字元 如 post get 功能 防注入 要過濾的非法字元 arrfiltrate array union add 出錯後要跳轉的url,不填則預設前一頁 是否存在陣列中的值 function funstringexist strfiltrate,arrfiltra...