我們在開發應用時,一般有個約定:不要信任任何來自不受自己控制的資料來源中的資料。例如以下這些外部源:
所有這些外部源都可能是攻擊媒介,可能會(有意或無意)把惡意資料注入php指令碼。編寫接收使用者輸入然後渲染輸出的php指令碼很容易,可是要安全實現的話,需要下一番功夫。我這裡以陳咬金的三板斧為引子,給大家介紹三招:過濾輸入、驗證資料,以及轉義輸出。
這篇文章很有用!
html
我們可以使用php提供的htmlentities函式過濾html,該函式會將所有html標籤字元(&、<、>等)轉化為對應的html實體,以便在應用儲存層取出後安全渲染。但是有時候我們是允許使用者輸入某些html元素的,尤其是輸入富文字的時候,比如、鏈結這些,但是htmlentities
不能驗證html,檢測不出輸入字串的字符集,故而無法實現這樣的功能。
<?php
$input = "
";echo htmlentities($input, ent_quotes, 'utf-8');
htmlentitie
s的第乙個引數表示要處理的html字串,第二個引數表示要轉義單引號,第三個引數表示輸入字串的字符集編碼。
與·htmlentities·相對的是·html_entity_decode·方法,該方法會將所有html實體轉化為對應的html標籤。
此外,php還提供了乙個類似的內建函式htmlspecialchars
,該函式也是用於將html標籤字元轉化為html實體,只是能夠轉化的字元有限(參考官方文件:如果要轉化所有字元還是使用htmlentities
方法,值得一提的是和htmlentities
一樣,htmlspecialchars
也有乙個與之相對的方法htmlspecialchars_decode
。
如果想要直接將輸入字串中的所有html標籤去掉,可以使用strip_tags
方法。
如果需要更加強大的過濾html功能,可以使用html purifier庫,這是乙個很強健且安全的php庫,專門用於使用指定規則過濾html輸入。在lar**el中我們可以使用相應的擴充套件包來實現過濾功能:
sql查詢
有時候應用必須根據輸入資料構建sql查詢,這些資料可能來自http請求的查詢字串,也可能來自http請求的uri片段,一不小心,就有可能被不懷好意的人利用進行sql注入攻擊(拼接sql語句對資料庫進行破壞或者獲取敏感資訊)。很多初級的程式設計師可能會這麼寫**:
$sql = sprintf(
'update users set password = "%s" where id = %s',
$_post['password'],
$_get['id']
);
這麼做風險很大,比如某個人通過如下方式對http傳送請求:
password=abc」;--這個http請求會把每個使用者的密碼都設定為abc
,因為很多sql資料庫把—視作注釋的開頭,所以會忽略後續文字。
在sql查詢中一定不能使用未過濾的輸入資料,如果要在sql查詢中使用輸入資料,一定要使用pdo預處理語句(pdo是php內建的資料庫抽象層,為不同的資料庫驅動提供統一介面),pdo預處理語句是pdo提供的乙個功能,可以用於過濾外部資料,然後把過濾後的資料嵌入sql語句,避免出現上述sql注入問題,此外預處理語句一次編譯多次執行,可以有效減少對系統資源的占用,獲取更高的執行效率。關於pdo後我們後續還會在資料庫部分重點討論。
值得注意的是,很多現代php框架都使用了mvc架構模式,將資料庫的操作封裝到了model層,框架底層已經做好了對sql注入的規避,只要我們使用模型類提供的方法執行對資料庫的操作,基本上可以避免sql注入風險。
我們以lar**el為例看看底層是如何規避sql注入的,改寫上面的update
語句,**會是這樣:
$id = $_get['id'];
$password = $_post['password'];
user::find($id)->update(['password'=>bcrypt($password)]);
由於模型類底層呼叫的是是查詢構建器的方法,所以最終會呼叫builder(illuminate\database\query\builder
)的update
方法:
public function update(array $values)
這段**傳入引數是要更新的值,然後通過$bindings
獲得繫結關係,這裡我們我們獲取到的應該是包含password和updated_at(預設更新時間戳)的陣列,然後再通過grammar(illuminate\database\query\grammars\grammar
)類的compileupdate
方法生成預處理sql語句,這裡對應的sql語句是:
update `users` set `password` = ?, `updated_at` = ? where `id` = ?
然後最終將預處理sql語句和對應繫結關係傳遞給資料庫去執行。關於sql注入我們還會在後續資料庫部分繼續討論。
使用者資料資訊
<?php
$email = '[email protected]';
$emailsafe = filter_var($email, filter_sanitize_email);
更多filter_var
的使用請參考php官方文件:相應的移除過濾器請參考:
當然,filter_var
函式還可以用於其它表單提交資料的過濾。
php常用的安全過濾函式
由於越來越多的專案開始使用框架,所以,很多的程式設計師也不在關心安全的問題!因為框架已經幫我們幾乎完美的處理了!但是,個人認為,我們還是需要了解一下常用的安全處理函式!原因簡單 很多小的功能和專案是用不到框架的,我們需要自己解決安全問題!mysql real escape string addsla...
php 的安全過濾(基礎篇)
php 5.2 以上提供了乙個非常簡單好用的自帶函式 filter var 下面是對這個函式使用的詳細介紹。驗證資料型別是否為boolean 舉例 php view plain copy value01 true if filter var value01 filter validate boole...
php常用的安全過濾函式
目錄結構 由於越來越多的專案開始使用框架,所以,很多的程式設計師也不在關心安全的問題!因為框架已經幫我們幾乎完美的處理了!但是,個人認為,我們還是需要了解一下常用的安全處理函式!原因簡單 很多小的功能和專案是用不到框架的,我們需要自己解決安全問題!mysql real escape string a...