Php 简明教程
PHP – CSRF
缩写词“CSRF”代表跨站点请求伪造。CSRF 是一种 Internet 漏洞,涉及受信任网站用户的发出未经授权的命令。通过采取本章中说明的措施,可以为 PHP Web 应用程序提供充足的保护来防御此类攻击。
默认情况下,浏览器使用“GET”请求方法来发送数据。这通常用作 CSRF 中的利用点。为了将命令注入到特定网站中,攻击者会使用诸如“IMG”之类的 HTML 标签。例如,Web 应用程序的 URL 端点,如“/delete.php?empcode=1234”,会删除从 GET 请求的 empcode 参数中传递的帐户。现在,如果经过身份验证的用户在任何其他应用程序中遇到以下脚本。
<img src="http://example.com/delete.php?empcode=1234"
width="0" height="0" border="0">
会不经意地导致与 empcode=1234 相关的数据被删除。
此问题的常见解决方法是使用 CSRF 令牌。CSRF 令牌是一串随机字符,嵌入到请求中,以便 Web 应用程序可以相信已从预期来源接收请求(按照正常工作流程)。
Steps to Implement CSRF
在 PHP 中实现 CSRF 令牌保护的步骤如下 -
-
通过启动新会话来开始脚本。
-
生成随机字符令牌。你可以使用 PHP 提供的几个内置函数来生成随机字符串。使用 md5() 函数来获取会生成唯一随机字符串的 uniqueid() 函数的哈希值。
-
在为用户准备以提交数据而提供的 HTML 表单内,包括一个隐藏文件,其值是上述步骤中生成的随机令牌。
-
在表单提交之后,服务器可以根据用户会话验证令牌,以消除恶意请求。
-
你还可以添加另一个赋值为当前时间的会话变量,并发送一个用于验证目的的到期时间。
Example
以下 PHP 代码实现了 CSRF 令牌验证机制。以下脚本生成一个令牌并将其嵌入到 HTML 表单中。
<?php
session_start();
if(!isset($_SESSION["csrf_token"])) {
// No token present, generate a new one
$token = md5(uniqid(rand(), true));
$_SESSION["csrf_token"] = $token;
} else {
// Reuse the token
$token = $_SESSION["csrf_token"];
}
?>
<html>
<body>
<form method="get" action="test.php">
<input type="text" name="empcode" placeholder="empcode" />
<input type="hidden" name="csrf_token" value="<?php echo $token;?>" />
<input type="submit" />
</form>
</body>
</html>
该表单提交到 "test.php" 脚本,如下所示 -
<?php
session_start();
echo "hello";
if ($_GET["csrf_token"] == $_SESSION["csrf_token"]) {
// Reset token
echo $_GET["csrf_token"] . "<br>";
echo $_SESSION["csrf_token"] . "<br>";
echo "<h3>CSRF token validation successful. Proceed to further action</h3>";
} else {
echo "<h3>CSRF token validation failed</h3>";
}
?>
它将生成以下 output −
要模拟 CSRF 验证失败,请打开浏览器的检查工具,手动编辑隐藏字段中的值,然后提交表单以查看令牌不匹配,从而导致验证失败。