跳至主要内容
版本:5.1

CSRF 防护

跨站点请求伪造 (CSRF) 是一种攻击类型,其中攻击者控制的外部网站上的 HTML 表单用于对目标网站发起攻击。

想象一下以下场景

  • 您以管理员身份运行一个 Joomla 网站,并且当前已登录
  • 在同一个浏览器中,您想从一个陌生人刚刚通过电子邮件发送给您的在线商店购买一台超便宜的新电视
  • 您点击该在线商店的“添加到购物车”按钮 - 但是,您并没有将商品添加到购物车,而是最终进入了 Joomla 网站的管理界面,看到了“用户已添加”的确认消息

所以,刚刚发生了什么?嗯,您被黑了!商店中的“添加到购物车”表单已被攻击者篡改

<form action="https://myjoomlasite.com/administrator/index.php" method="post">
<input type="hidden" name="task" value="user.add" />
<input type="hidden" name="option" value="com_users" />
<input type="hidden" name="jform[username]" value="attackeruser" />
<input type="hidden" name="jform[password]" value="attackerpwd123" />
<input type="submit" value="Add to cart" />
</form>

表单的 action 属性指向受害者的网站 - 因此,该表单的请求数据在两个网站之间被伪造:CSRF 正在发生。在这种情况下,CSRF 用于为攻击者创建一个新用户 - 由于该请求是使用当前登录用户的权限执行的,因此该请求成功。

幸运的是,这种情况是理论上的,因为 Joomla 使用简单的安全措施来防止 CSRF 攻击。

预防

为了防止 CSRF 攻击,每个旨在对网站进行更改的请求都会附加一个随机生成的字符串

<form action="index.php" method="post">
[...]
<?php echo HTMLHelper::_('form.token'); ?>
</form>

form.token 方法生成一个具有随机名称和“1”作为值的隐藏输入元素。随机名称存储在用户会话中,因此 Joomla 可以检查它是否在表单提交后包含在请求中。为了触发检查,在控制器类中使用 $this->checkToken(); 方法,或在控制器之外使用 Session::checkToken() 方法。

由于随机名称存储在用户会话中,因此是特定于会话的,外部攻击者无法将其包含在篡改的表单中。CSRF 攻击将失败。

重要:CSRF 令牌与权限检查无关!通过的 CSRF 检查并不证明用户已登录,或具有执行给定任务的特定权限。