幸运的是,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 源代码,将它转移到本身的服务器上,并向您的服务器提交信息,您的服务器接收的也只是空的或畸形的会话令牌和原来提供的表单令牌。它们不匹配,远程表单提交就失败了。