[Http] 跨站请求伪造(CSRF)
基本概念
当一个用户已经登录并且在当前域名下存储了相关的 Cookie(如身份验证信息等),如果打开一个伪造的 HTML 页面,并且该页面中的 <form>
元素的 action 属性包含完整的 API 请求全路径指向同一域名,浏览器在发送该表单请求时会自动携带该域名下存储的 Cookie
。
同一域名下的所有请求(包括表单提交、XHR、Fetch 请求等)都会自动附带浏览器中存储的 Cookie
信息,除非使用了 SameSite、HttpOnly 等安全设置来限制特定的 Cookie
行为。
攻击过程
- 用户登录可信站点:用户登录一个网站后,网站通常会在用户浏览器中设置一个认证 cookie,用于维持用户的会话。
- 攻击者伪造请求:攻击者创建一个恶意网页(或者一段恶意代码),该页面向用户已登录的网站发送请求。这些请求可能是通过
<form>
表单提交、图片链接、AJAX 请求等方式伪造的。 - 浏览器自动携带 cookie:由于请求的目标域名与用户登录的网站相同,浏览器会自动附带之前的认证 cookie(如 session cookie),服务器将其视为合法用户的请求。
- 服务器执行请求:如果网站没有足够的防护措施,服务器会执行该请求,认为这是由合法用户发出的,从而造成恶意操作,比如更改账户信息、进行转账等。
假设一个用户登录了银行网站 bank.com
,并且银行网站在用户的浏览器中设置了认证 Cookie。攻击者发送给用户一个包含以下内容的恶意 HTML 页面:
<form action="https://bank.com/transfer" method="POST">
<input type="hidden" name="to_account" value="attacker_account">
<input type="hidden" name="amount" value="1000">
<input type="submit" value="Submit">
</form>
用户一旦打开这个页面,表单会自动提交,并携带浏览器中的认证 Cookie。银行网站接收到请求后,认为这是用户自愿的转账操作,从而执行了转账。
防御 CSRF
- CSRF Token: 在表单中加入一个唯一的 Token(令牌),服务器在接收到请求时验证这个 Token 是否与用户会话中的一致。由于攻击者无法获取合法的 Token,因此伪造的请求会被拒绝。
- SameSite Cookie: 将 Cookie 的
SameSite
属性设置为Lax
或Strict
,限制 Cookie 在跨站请求中的传递。这样,攻击者无法在跨站请求中利用用户的 Cookie。 - 检查 Referer 和 Origin 头: 服务器端可以检查请求的
Referer
或Origin
头,确保请求是来自同一站点,而不是第三方站点。