什么是 CSRF ?
跨站请求伪造(CSRF,Cross-site request forgery),也称为 XSRF,Sea Surf 或Session Riding,是一个攻击向量,它欺骗 Web 浏览器在登录用户的应用程序中执行不需要的动作。
CSRF 是一个网络安全漏洞,允许攻击者诱使用户执行他们不打算执行的操作。它允许攻击者部分规避相同的原始策略,该策略旨在防止不同的网站相互干预。恶意 Web 程序可以通过多种方式发起请求,例如特制图像标签,隐藏表单,AJAX 请求等。它们可以在用户不参与甚至不知情的情况下运行。
成功的 CSRF 攻击对于企业和用户来说都是毁灭性的。它可能导致客户关系受损,未经授权的基金转移,更改密码和数据盗窃(包括被盗的会话 cookie)。
CSRF 通常是使用恶意社会工程学进行的,例如电子邮件或链接,该电子邮件欺骗受害者将伪造的请求发送到服务器。由于在攻击时通过其应用程序来验证毫无戒心的用户,因此不可能将合法请求与伪造的请求区分开。
【问题咨询和282G网络安全资料的领取点击这里】
CSRF 攻击影响
在成功的 CSRF 攻击中,攻击者会导致受害者用户无意地采取行动。例如,这可能是更改其帐户上的电子邮件地址,更改其密码或进行资金转移。根据操作的性质,攻击者可能能够完全控制用户的帐户。如果妥协的用户在应用程序中具有特权角色,则攻击者可能能够完全控制应用程序的所有数据和功能。
CSRF 例子
在执行攻击之前,肇事者通常会研究应用程序,以使伪造请求尽可能合法。
例如,典型的收到100美元银行转让的请求可能看起来像:
GET http://netbank.com/transfer.do?acct=PersonB&amount=$100 HTTP/1.1
黑客可以修改此脚本,以便将100美元转移到他们自己的帐户中。现在恶意请求可能看起来像:
GET http://netbank.com/transfer.do?acct=AttackerA&amount=$100 HTTP/1.1
CSRF 怎么工作
为了实现CSRF攻击,必须有三个关键条件:
- 相关动作。应用程序中有一个动作,攻击者有理由诱发。这可能是特权操作(例如为其他用户修改权限)或对用户特定数据的任何操作(例如更改用户自己的密码)。
- 基于 Cookie 的会话处理。执行该操作涉及发布一个或多个HTTP请求,该应用程序仅依靠会话Cookie来确定已提出该请求的用户。没有其他机制来跟踪会话或验证用户请求。
- 没有不可预测的请求参数。执行操作的请求不包含任何值的参数,其值无法确定或猜测。例如,当导致用户更改密码时,如果攻击者需要知道现有密码的值,则该功能并不脆弱。
例如,假设应用程序包含一个函数,该函数使用户可以在其帐户上更改电子邮件地址。当用户执行此操作时,他们会像以下内容一样提出 HTTP 请求:
POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
Cookie: session=yvthwsztyeQkAPzeQ5gHgTvlyxHfsAfE
email=wiener@normal-user.com
这符合 CSRF 所需的条件:
- 攻击者通常将能够触发密码重置并完全控制用户帐户
- 该应用程序使用会话 cookie 确定哪个用户发布了请求。没有其他令牌或机制来跟踪用户会话
- 攻击者可以轻松地确定执行操作所需的请求参数的值
有了这些条件,攻击者可以构建一个包含以下 HTML 的网页:
如果受害者用户访问了攻击者的网页,则会发生以下情况:
- 攻击者的页面将触发 HTTP 请求到易受攻击的网站
- 如果用户已登录到易受攻击的网站,则其浏览器将在请求中自动包含其会话 cookie(假设未使用 Samesite Cookie)
- 易受攻击的网站将以正常的方式处理请求,将其视为受害者用户提供的请求,并更改其电子邮件地址。
CSRF 解决方法
有许多有效的方法可以预防和缓解 CSRF 攻击。从用户的角度来看,预防是维护登录凭据并拒绝未经授权的参与者访问应用程序的问题。
最佳实践如下:
- 当不使用时登出 Web 应用程序
- 确保用户名和密码
- 不允许浏览器记住密码
- 登录到应用程序时避免同时浏览
对于 Web 应用程序,存在多种解决方案来阻止恶意流量并防止攻击。最常见的缓解方法之一是为每个会话请求或 ID 生成唯一的随机令牌。这些服务器随后由服务器检查和验证。具有重复令牌或缺失值的会话请求被阻止。或者,不匹配其会话 ID 令牌的请求是阻止到达应用程序的。
双重提交 Cookie 是阻止 CSRF 的另一种众所周知的方法。类似于使用唯一令牌,随机令牌被分配给 cookie 和请求参数。然后,服务器在授予对应用程序的访问之前验证令牌是否匹配。
虽然有效,但可以在许多点上公开代币,包括在浏览器历史记录中,HTTP 日志文件,网络设备记录 HTTP 请求的第一行和引用器标头(如果受保护的站点链接到外部 URL)。这些潜在的弱点使代币成为一个不隔热的解决方案。
使用自定义规则防止 CSRF 攻击
验证 HTTP Referer 字段
根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。这个 Referer 字段主要是标明我们请求的来源,当我们通过一个恶意站点去访问一个可信任的站点的时候,可信任站点其实是能够识别这个请求是来自恶意站点的,因为 Referer 字段会标明它的来源.站点还可以对一些敏感操作限制其Referer字段的值,比如某站点转账的时候使用:http:bank.example/withdraw?account=bob&amount=10000000&for=Mallory
那么转账的操作一定是用户登录知乎在本站点的页面上操作的,因为可以将Referer字段限制为只允许本站点。
在请求地址中添加token并验证
CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
在 HTTP 头中自定义属性并验证
这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。
- Cross-site request forgery (CSRF)