清单 11 提供了一个基本示例,在该示例中将弹出一个新窗口并打开 Google 的主页。如果您的 Web 应用程序不针对 XSS 攻击进行保护,则会造成严重的破坏。例如,某个人可以添加模仿站点样式的链接以达到欺骗(phishing)目的(请参阅 参考资料)。 清单 11. 恶意输入文本样例 [U]复制代码[/U] 代码如下:
要防止受到 XSS 攻击,只要变量的值将被打印到输出中,就需要通过 htmlentities() 函数过滤输入。记住要遵循第一个习惯:在 Web 应用程序的名称、电子邮件地址、电话号码和帐单信息的输入中用白名单中的值验证输入数据。
下面显示了更安全的显示文本输入的页面。 清单 12. 更安全的表单 [U]复制代码[/U] 代码如下:
Results demonstrating XSS
You typed this:
");
echo("");
echo(htmlentities($_POST['myText']));
echo("
");
?>
针对无效 post 进行保护 表单欺骗 是指有人把 post 从某个不恰当的位置发到您的表单中。欺骗表单的最简单方法就是创建一个通过提交至表单来传递所有值的 Web 页面。由于 Web 应用程序是没有状态的,因此没有一种绝对可行的方法可以确保所发布数据来自指定位置。从 IP 地址到主机名,所有内容都是可以欺骗的。清单 13 显示了允许输入信息的典型表单。 清单 13. 处理文本的表单 [U]复制代码[/U] 代码如下:
Form spoofing example
I am processing your text: ");
echo($_POST['myText']);
echo("
");
}
?>
清单 14 显示了将发布到清单 13 所示表单中的表单。要尝试此操作,您可以把该表单放到 Web 站点中,然后把清单 14 中的代码另存为桌面上的 HTML 文档。在保存表单后,在浏览器中打开该表单。然后可以填写数据并提交表单,从而观察如何处理数据。 清单 14. 收集数据的表单 [U]复制代码[/U] 代码如下:
Collecting your data
Yes
No
表单欺骗的潜在影响是,如果拥有含下拉框、单选按钮、复选框或其他限制输入的表单,则当表单被欺骗时这些限制没有任何意义。考虑清单 15 中的代码,其中包含带有无效数据的表单。 清单 15. 带有无效数据的表单 [U]复制代码[/U] 代码如下:
Collecting your data
思考一下:如果拥有限制用户输入量的下拉框或单选按钮,您可能会认为不用担心验证输入的问题。毕竟,输入表单将确保用户只能输入某些数据,对吧?要限制表单欺骗,需要进行验证以确保发布者的身份是真实的。您可以使用一种一次性使用标记,虽然这种技术仍然不能确保表单绝对安全,但是会使表单欺骗更加困难。由于在每次调用表单时都会更改标记,因此想要成为攻击者就必须获得发送表单的实例,去掉标记,并把它放到假表单中。使用这项技术可以阻止恶意用户构建持久的 Web 表单来向应用程序发布不适当的请求。清单 16 提供了一种表单标记示例。 清单 16. 使用一次性表单标记 [U]复制代码[/U] 代码如下:
SQL Injection Test
Go away!';
}
$token = md5(uniqid(rand(), true));
$_SESSION['token'] = $token;
?>
"
method="post"> " /> " />
针对 CSRF 进行保护 跨站点请求伪造(CSRF 攻击)是利用用户权限执行攻击的结果。在 CSRF 攻击中,您的用户可以轻易地成为预料不到的帮凶。清单 17 提供了执行特定操作的页面示例。此页面将从 cookie 中查找用户登录信息。只要 cookie 有效,Web 页面就会处理请求。 清单 17. CSRF 示例 [U]复制代码[/U] 代码如下:
CSRF 攻击通常是以 标记的形式出现的,因为浏览器将在不知情的情况下调用该 URL 以获得图像。但是,图像来源可以是根据传入参数进行处理的同一个站点中的页面 URL。当此 标记与 XSS 攻击结合在一起时 — 在已归档的攻击中最常见 — 用户可以在不知情的情况下轻松地对其凭证执行一些操作 — 因此是伪造的。
为了保护您免受 CSRF 攻击,需要使用在检验表单 post 时使用的一次性标记方法。此外,使用显式的 $_POST 变量而非 $_REQUEST。清单 18 演示了处理相同 Web 页面的糟糕示例 — 无论是通过 GET 请求调用页面还是通过把表单发布到页面中。 清单 18. 从 $_REQUEST 中获得数据 [U]复制代码[/U] 代码如下:
Processes both posts AND gets
I am processing your text: ");
echo(htmlentities($_REQUEST['text']));
echo("
");
}
?>
清单 19 显示了只使用表单 POST 的干净页面。 清单 19. 仅从 $_POST 中获得数据 [U]复制代码[/U] 代码如下:
Processes both posts AND gets
I am processing your text: ");
echo(htmlentities($_POST['text']));
echo("
");
}
?>