幸運的是,PHP 提供了 strip_tags() 函數,這個函數能夠清除任何包圍在 HTML 標記中的內容。strip_tags() 函數還容許提供容許標記的列表,好比 <b> 或 <i>。
瀏覽器內的數據操縱
有一類瀏覽器插件容許用戶篡改頁面上的頭部元素和表單元素。使用 Tamper Data(一個 Mozilla 插件),能夠很容易地操縱包含許多隱藏文本字段的簡單表單,從而向 PHP 和 MySQL 發送指令。
用戶在點擊表單上的 Submit 以前,他能夠啓動 Tamper Data。在提交表單時,他會看到表單數據字段的列表。Tamper Data 容許用戶篡改這些數據,而後瀏覽器完成表單提交。
讓咱們回到前面創建的示例。已經檢查了字符串長度、清除了 HTML 標記並刪除了十六進制字符。可是,添加了一些隱藏的文本字段,以下所示:
清單 17. 隱藏變量
<?php
if ($_POST[’submit’] == 「go」){
//strip_tags
$name = strip_tags($_POST[’name’]);
$name = substr($name,0,40);
//clean out any potential hexadecimal characters
$name = cleanHex($name);
//continue processing….
}
function cleanHex($input){
$clean = preg_replace(」![\][xX]([A-Fa-f0-9]{1,3})!」, 「」,$input);
return $clean;
}
?>
<form action=」<?php echo $_SERVER[’PHP_SELF’];?>」 method=」post」>
<p><label for=」name」>Name</label>
<input type=」text」 name=」name」 id=」name」 size=」20″ maxlength=」40″/></p>
<input type=」hidden」 name=」table」 value=」users」/>
<input type=」hidden」 name=」action」 value=」create」/>
<input type=」hidden」 name=」status」 value=」live\」/>
<p><input type=」submit」 name=」submit」 value=」go」/></p>
</form>
注意,隱藏變量之一暴露了表名:users。還會看到一個值爲 create 的 action 字段。只要有基本的 SQL 經驗,就可以看出這些命令可能控制着中間件中的一個 SQL 引擎。想搞大破壞的人只需改變表名或提供另外一個選項,好比 delete。
如今還剩下什麼問題呢?遠程表單提交。
遠程表單提交
Web 的好處是能夠分享信息和服務。壞處也是能夠分享信息和服務,由於有些人作事毫無顧忌。
以 表單爲例。任何人都可以訪問一個 Web 站點,並使用瀏覽器上的 File > Save As 創建表單的本地副本。而後,他能夠修改 action 參數來指向一個徹底限定的 URL(不指向 formHandler.php,而是指向 http://www.yoursite.com/formHandler.php,由於表單在這個站點上),作他但願的任何修改,點擊 Submit,服務器會把這個表單數據做爲合法通訊流接收。
首先可能考慮檢查 $_SERVER[’HTTP_REFERER’],從而判斷請求是否來自本身的服務器,這種方法能夠擋住大多數惡意用戶,可是擋不住最高明的
黑客。這些人足夠聰明,可以篡改頭部中的引用者信息,使表單的遠程副本看起來像是從您的服務器提交的。
處理遠程表單提交更好的方式是,根據一個唯一的字符串或時間戳生成一個令牌,並將這個令牌放在會話變量和表單中。提交表單以後,檢查兩個令牌是否匹配。若是不匹配,就知道有人試圖從表單的遠程副本發送數據。
要建立隨機的令牌,可使用 PHP 內置的 md5()、uniqid() 和 rand() 函數,以下所示:
清單 18. 防護遠程表單提交
<?php
session_start();
if ($_POST[’submit’] == 「go」){
//check token
if ($_POST[’token’] == $_SESSION[’token’]){
//strip_tags
$name = strip_tags($_POST[’name’]);
$name = substr($name,0,40);
//clean out any potential hexadecimal characters
$name = cleanHex($name);
//continue processing….
}else{
//stop all processing! remote form posting attempt!
}
}
$token = md5(uniqid(rand(), true));
$_SESSION[’token’]= $token;
function cleanHex($input){
$clean = preg_replace(」![\][xX]([A-Fa-f0-9]{1,3})!」, 「」,$input);
return $clean;
}
?>
<form action=」<?php echo $_SERVER[’PHP_SELF’];?>」 method=」post」>
<p><label for=」name」>Name</label>
<input type=」text」 name=」name」 id=」name」 size=」20″ maxlength=」40″/></p>
<input type=」hidden」 name=」token」 value=」<?php echo $token;?>」/>
<p><input type=」submit」 name=」submit」 value=」go」/></p>
</form>
這種技術是有效的,這是由於在 PHP 中會話數據沒法在服務器之間遷移。即便有人得到了您的 PHP 源代碼,將它轉移到本身的服務器上,並向您的服務器提交信息,您的服務器接收的也只是空的或畸形的會話令牌和原來提供的表單令牌。它們不匹配,遠程表單提交就失敗了。