随着 Web 应用程序的发展和普及,网络安全问题变得越来越重要。跨站请求伪造(CSRF)攻击成为了其中一种常见的攻击手段。CSRF攻击是指攻击者通过仿冒合法用户的请求来执行一些恶意操作,例如在用户没有意识到的情况下转账、修改密码等。为了保护用户和 Web 应用程序的安全,开发者需要采取措施来防御此类攻击。本文将介绍如何使用 PHP 来防御CSRF攻击。
什么是CSRF?
CSRF,全称为Cross-Site Request Forgery(跨站请求伪造),是一种常见的网络安全漏洞和攻击方式。它利用了Web应用程序中的信任机制,通过欺骗用户在已登录的状态下执行非意愿的操作,从而导致未经授权的请求被发送到目标网站。
CSRF攻击的基本原理
- 用户在已登录的状态下访问恶意网站或点击恶意链接。
- 恶意网站或链接中包含了对目标网站的请求,该请求可能是修改用户个人信息、进行资金转账、删除数据等未经授权的操作。
- 用户的浏览器会自动发送该请求,因为用户已经在目标网站中登录并保留了有效的身份验证凭证(如Cookie)。
- 目标网站接收到请求后,无法分辨这是来自用户的合法请求还是恶意请求,并按照请求执行了相应的操作。
生成和验证CSRF令牌
生成CSRF令牌
session_start();
$token = bin2hex(random_bytes(32)); // 生成32个字节的随机令牌
$_SESSION['csrf_token'] = $token; // 将令牌存储在会话中
在表单中嵌入CSRF令牌
<form action="process.php" method="POST">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<!-- 其他表单字段 -->
<button type="submit">提交</button>
</form>
验证CSRF令牌
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
// 令牌验证失败,执行相应的错误处理
die("CSRF攻击检测到!请求被拒绝。");
}
// 令牌验证成功,继续处理请求
}
同源检测
检查请求的来源头部
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$referer = $_SERVER['HTTP_REFERER'];
$origin = $_SERVER['HTTP_ORIGIN'];
$allowedOrigins = array('https://example.com', 'https://www.example.com'); // 允许的合法来源
if (!in_array($referer, $allowedOrigins) || !in_array($origin, $allowedOrigins)) {
// 来源验证失败,执行相应的错误处理
die("CSRF攻击检测到!请求被拒绝。");
}
// 来源验证成功,继续处理请求
}
添加验证码
生成和验证验证码
session_start();
$randomNumber = rand(1000, 9999); // 生成随机验证码
$_SESSION['captcha'] = $randomNumber; // 将验证码存储在会话中
// 在表单中显示验证码图像
<img src="captcha.php" alt="验证码">
// 验证用户输入的验证码
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!isset($_POST['captcha']) || $_POST['captcha'] !== $_SESSION['captcha']) {
// 验证码验证失败,执行相应的错误处理
die("验证码验证失败!请求被拒绝。");
}
// 验证码验证成功,继续处理请求
}
设置HTTP头部
设置SameSite属性为Strict或Lax
header('Set-Cookie: mycookie=value; SameSite=Strict');
或
header('Set-Cookie: mycookie=value; SameSite=Lax');