PHP安全-輸出轉義
另外一個Web應用安全的基礎是對輸出進行轉義或對特殊字符進行編碼,以保證原意不變。例如,O’Reilly在傳送給MySQL數(shù)據(jù)庫前需要轉義成O’Reilly。單引號前的反斜杠代表單引號是數(shù)據(jù)本身的一部分,而不是并不是它的本義。
我所指的輸出轉義具體分為三步:
l識別輸出
l輸出轉義
l區(qū)分已轉義與未轉義數(shù)據(jù)
只對已過濾數(shù)據(jù)進行轉義是很有必要的。盡管轉義能防止很多常見安全漏洞,但它不能替代輸入過濾。被污染數(shù)據(jù)必須首先過濾然后轉義。
在對輸出進行轉義時,你必須先識別輸出。通常,這要比識別輸入簡單得多,因為它依賴于你所進行的動作。例如,識別到客戶端的輸出時,你可以在代碼中查找下列語句:
echo
printf
<?=
作為一項應用的開發(fā)者,你必須知道每一個向外部系統(tǒng)輸出的地方。它們構成了輸出。
象過濾一樣,轉義過程在依情形的不同而不同。過濾對于不同類型的數(shù)據(jù)處理方法也是不同的,轉義也是根據(jù)你傳輸信息到不同的系統(tǒng)而采用不同的方法。
對于一些常見的輸出目標(包括客戶端、數(shù)據(jù)庫和URL)的轉義,PHP中有內置函數(shù)可用。如果你要寫一個自己算法,做到萬無一失很重要。需要找到在外系統(tǒng)中特殊字符的可靠和完整的列表,以及它們的表示方式,這樣數(shù)據(jù)是被保留下來而不是轉譯了。
最常見的輸出目標是客戶機,使用htmlentities( )在數(shù)據(jù)發(fā)出前進行轉義是最好的方法。與其它字符串函數(shù)一樣,它輸入是一個字符串,對其進行加工后進行輸出。但是使用htmlentities( )函數(shù)的最佳方式是指定它的兩個可選參數(shù):引號的轉義方式(第二參數(shù))及字符集(第三參數(shù))。引號的轉義方式應該指定為ENT_QUOTES,它的目的是同時轉義單引號和雙引號,這樣做是最徹底的,字符集參數(shù)必須與該頁面所使用的字符集相必配。
為了區(qū)分數(shù)據(jù)是否已轉義,我還是建議定義一個命名機制。對于輸出到客戶機的轉義數(shù)據(jù),我使用$html數(shù)組進行存儲,該數(shù)據(jù)首先初始化成一個空數(shù)組,對所有已過濾和已轉義數(shù)據(jù)進行保存。
CODE:
<?php
$html = array( );
$html[’username’] = htmlentities($clean[’username’], ENT_QUOTES, ’UTF-8’);
echo '<p>Welcome back, {$html[’username’]}.</p>';
?>
小提示
htmlspecialchars( )函數(shù)與htmlentities( )函數(shù)基本相同,它們的參數(shù)定義完全相同,只不過是htmlentities( )的轉義更為徹底。
通過$html[’username’]把username輸出到客戶端,你就可以確保其中的特殊字符不會被瀏覽器所錯誤解釋。如果username只包含字母和數(shù)字的話,實際上轉義是沒有必要的,但是這體現(xiàn)了深度防范的原則。轉義任何的輸出是一個非常好的習慣,它可以戲劇性地提高你的軟件的安全性。
另外一個常見的輸出目標是數(shù)據(jù)庫。如果可能的話,你需要對SQL語句中的數(shù)據(jù)使用PHP內建函數(shù)進行轉義。對于MySQL用戶,最好的轉義函數(shù)是mysql_real_escape_string( )。如果你使用的數(shù)據(jù)庫沒有PHP內建轉義函數(shù)可用的話,addslashes( )是最后的選擇。
下面的例子說明了對于MySQL數(shù)據(jù)庫的正確的轉義技巧:
CODE:
<?php
$mysql = array( );
$mysql[’username’] = mysql_real_escape_string($clean[’username’]);
$sql = 'SELECT *
FROM profile
WHERE username = ’{$mysql[’username’]}’';
$result = mysql_query($sql);
?>
相關文章:

網公網安備