如何防止PHP中的跨站点伪造伪造(CSRF)攻击?
                           
天天向上
发布: 2025-06-28 12:49:05

原创
385 人浏览过

防止 PHP 中的跨站请求伪造(CSRF, Cross-Site Request Forgery)攻击,是保障 Web 应用安全性的重要措施之一。以下适用于你在使用 PHP 构建登录、表单、数据修改等功能时有效防御 CSRF 攻击。


什么是 CSRF 攻击?

CSRF 是一种利用用户登录状态,诱导其在不知情情况下执行恶意操作的攻击。

例如:

<img src="http://example.com/delete-user.php?id=123"> <!-- 用户已登录,被诱导点击 -->

防御 CSRF 的通用思路

核心原则是:验证每个敏感请求是否来自“可信页面”,主要方法:

  1. 使用 CSRF Token(推荐做法)
  2. 设置 Referer 验证(辅助防御)
  3. 使用 SameSite Cookie 属性
  4. 使用双重 Cookie 验证机制(更高级)
  5. 对表单/接口做白名单过滤

方法 1:使用 CSRF Token(最推荐)

每次生成一个随机的令牌(token),保存在用户 Session,并插入表单中。提交时进行验证。

1️⃣ 生成 CSRF Token(保存到 Session)

session_start();

if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

2️⃣ 表单中插入隐藏字段

<form method="POST" action="update-profile.php">
    <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
    <input type="text" name="name">
    <input type="submit" value="更新">
</form>

3️⃣ 提交后验证 Token

session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
        die("⚠️ CSRF 验证失败!");
    }

    // 安全处理业务逻辑
}

📌 hash_equals 可防止时序攻击。


方法 2:检查 HTTP Referer(辅助方法)

$referer = $_SERVER['HTTP_REFERER'] ?? '';
if (strpos($referer, 'https://yourdomain.com') !== 0) {
    die("⚠️ 非法请求!");
}

⚠️ 缺点:部分浏览器可能不发送 Referer,或被篡改,因此 只能作为辅助


方法 3:设置 SameSite Cookie 属性(现代浏览器支持)

在设置 session cookie 时添加 SameSite 限制:

session_set_cookie_params([
    'lifetime' => 0,
    'path' => '/',
    'domain' => 'yourdomain.com',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Strict' // 或 Lax
]);
session_start();

📌 Strict 最安全,但可能导致跨站跳转失败;Lax 较宽松。


方法 4:双重 Cookie 验证机制(Double Submit Cookie)

适用于 无 Session 的 REST API / SPA 场景。

  • 服务器发送一个 CSRF Token Cookie
  • 客户端每次请求时,在 header 或 body 中回传 token
  • 服务器验证 cookie 与 body 中 token 一致

方法 5:使用 Web 框架内建 CSRF 防护

很多 PHP 框架已经默认支持:

框架防护机制
Laravel自动为所有 POST、PUT、PATCH、DELETE 请求验证 CSRF
Symfony使用 CSRF Token Manager
Yii2自动开启表单 CSRF 验证

Laravel 示例:

<form method="POST" action="/profile">
    @csrf
</form>

实战检测:常见 CSRF 攻击页面如何伪造请求

<form action="http://victim-site.com/update-password.php" method="POST">
    <input type="hidden" name="password" value="123456">
    <input type="submit" value="Click me">
</form>

✅ 防御成功的表现:服务器发现 CSRF Token 不匹配,直接拒绝请求。


📚 权威资料与文档链接


总结防御建议

方法安全性推荐等级
CSRF Token + Session⭐⭐⭐⭐⭐✅ 推荐
CSRF Token + Double Cookie⭐⭐⭐⭐REST API 场景
SameSite Cookie⭐⭐⭐辅助
Referer 验证⭐⭐不可靠,仅参考

更多详细内容,请关注其他相关文章!

发表回复 0

Your email address will not be published. Required fields are marked *