Php 简明教程
PHP – CSRF
缩写词“CSRF”代表跨站点请求伪造。CSRF 是一种 Internet 漏洞,涉及受信任网站用户的发出未经授权的命令。通过采取本章中说明的措施,可以为 PHP Web 应用程序提供充足的保护来防御此类攻击。
The acronym "CSRF" stands for Cross-Site Request Forgery. CSRF is an Internet exploit that involves a trusted website user issuing unauthorized commands. Providing adequate protection to a PHP web application against this attack can be achieved by taking the measures explained in this chapter.
默认情况下,浏览器使用“GET”请求方法来发送数据。这通常用作 CSRF 中的利用点。为了将命令注入到特定网站中,攻击者会使用诸如“IMG”之类的 HTML 标签。例如,Web 应用程序的 URL 端点,如“/delete.php?empcode=1234”,会删除从 GET 请求的 empcode 参数中传递的帐户。现在,如果经过身份验证的用户在任何其他应用程序中遇到以下脚本。
By default, the browser uses the "GET" request method to send data. This is commonly used as the exploit point in a CSRF. To inject commands into a specific website, the attacker employs HTML tags like "IMG." For example, the url endpoint of a web application such as "/delete.php?empcode=1234" deletes account as passed from empcode parameter of a GET request. Now, if an authenticated user come across the following script in any other application.
<img src="http://example.com/delete.php?empcode=1234"
width="0" height="0" border="0">
会不经意地导致与 empcode=1234 相关的数据被删除。
Inadvertently causes the data related to empcode=1234 to be deleted.
此问题的常见解决方法是使用 CSRF 令牌。CSRF 令牌是一串随机字符,嵌入到请求中,以便 Web 应用程序可以相信已从预期来源接收请求(按照正常工作流程)。
A common workaround for this problem is the use of CSRF tokens. A CSRF token is a string of random characters embedded into requests so that a web application can trust that a request has been received from an expected source as per the normal workflow.
Steps to Implement CSRF
在 PHP 中实现 CSRF 令牌保护的步骤如下 -
The steps to implement CSRF token protection in PHP are as follows −
-
Begin the script by starting a new session.
-
Generate a token of random characters. You can use any of the several built-in function that PHP provides for generation of random string. Let use md5() function to obtain the hash value of uniqueid() function that generates a unique randome string.
-
Inside the HTML form to be provided for the user to submit the data, include a hidden file with its value as the random token generated in the above step.
-
The token can is then validated by the server against the user session after form submission to eliminate malicious requests.
-
You can also add another session variable whose value is the current time, and send an expiry time for the validation purpose.
Example
以下 PHP 代码实现了 CSRF 令牌验证机制。以下脚本生成一个令牌并将其嵌入到 HTML 表单中。
Here is the PHP code that implements CSRF token verification mechanism. The following script generates a token and embeds in a HTML form.
<?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" 脚本,如下所示 -
The form is submitted to "test.php" script as below −
<?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 −
It will produce the following output −
要模拟 CSRF 验证失败,请打开浏览器的检查工具,手动编辑隐藏字段中的值,然后提交表单以查看令牌不匹配,从而导致验证失败。
To simulate the failure of CSRF validation, open the inspect tool of the browser, edit the value in the hidden field manually and submit the form to see that the tokens don’t match leading to the validation failure.