如何在PHP中防止SQL注入?

2021-08-13 22:28:44 字數 3101 閱讀 6147

如何在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...