当前位置: 当前位置:首页 > 时尚 > 跨站请求伪造漏洞正文

跨站请求伪造漏洞

作者:综合 来源:娱乐 浏览: 【大 中 小】 发布时间:2026-10-17 06:08:14 评论数:
```html

攻击者根本不需要拿到你的跨站密码。他只需要让你在已登录某网站的请求状态下,点开一个链接、伪造加载一张图片,漏洞甚至只是跨站打开一封邮件——你的浏览器就会自动带着你的身份凭证,替攻击者完成一笔转账、请求改掉你的伪造邮箱、或者发一条你毫不知情的漏洞动态。这就是跨站跨站请求伪造(CSRF)的可怕之处:它不偷你的钥匙,而是请求骗你亲手把门打开。

我见过一个真实案例。伪造某小型银行的漏洞后台系统,转账接口只校验了会话Cookie,跨站没加任何随机令牌。请求攻击者给柜员发了一封“客户投诉材料”的伪造邮件,里面嵌入一张看似普通的图片,实际指向转账接口:https://bank.example/transfer?to=attacker&amount=50000。柜员打开邮件,浏览器自动请求该地址,因为柜员刚登录系统不久,Cookie还在有效期内,服务器认为这是柜员本人的操作。五万块就这么划走了。没有弹窗,没有确认,柜员甚至不知道发生了什么。

为什么浏览器会这么“听话”?因为HTTP是无状态的,网站靠Cookie来记住你是谁。浏览器有个默认规则:只要请求的目标域名和Cookie的域匹配,就自动带上Cookie。这个规则本意是提供便利,却成了CSRF的温床。攻击者把恶意请求藏在第三方页面里,你的浏览器分不清这是你主动点的,还是别人诱导你点的。

常见的触发方式不止图片。一个隐藏的<iframe>、一段自动提交的表单、甚至CSS里的background:url(...)都能发起跨站请求。POST请求也不安全,攻击者可以构造一个自动提交的表单,用JavaScript在页面加载时触发submit()。你看到的可能只是一个空白页,但请求已经发出去了。

防御CSRF,最有效的办法是给每个请求加一个攻击者猜不到的随机令牌(CSRF Token)。这个令牌存在服务器端,嵌入表单或请求头里,每次提交都要验证。攻击者无法从第三方页面读取这个令牌,因为同源策略会阻止跨域读取。但这里有个坑:很多开发者只给POST加令牌,忘了GET。如果一个删除操作是GET请求,比如/delete?id=123,攻击者直接放个<img src="/delete?id=123">就完事了。所以RESTful设计里,GET只用于读取,任何写操作必须用POST/PUT/DELETE,并且都带上令牌。

另一个常被忽略的点是SameSite Cookie属性。把会话Cookie设为SameSite=Lax或Strict,浏览器就不会在跨站请求中发送它。Lax允许顶级导航的GET请求携带Cookie,比如从外部链接点进来,但POST、iframe、图片请求都不带。Strict更严格,任何跨站请求都不带。这招能挡住大部分CSRF,但老浏览器支持不好,而且如果网站有多个子域,配置起来要小心。

有些开发者觉得“我用了JSON API,Content-Type是application/json,攻击者没法用表单伪造”。这想法对了一半。表单确实只能发application/x-www-form-urlencoded、multipart/form-data、text/plain三种类型,但攻击者可以用text/plain发一个JSON字符串,服务器如果解析时不检查Content-Type,照样中招。我就测试过一个接口,它用text/plain发JSON,后端直接json.loads,结果CSRF成功。所以别依赖Content-Type做防御,令牌才是硬道理。

还有种情况是“登录CSRF”。攻击者伪造一个登录请求,让你登录到攻击者的账号。之后你所有操作都记录在攻击者账号下,比如你上传的隐私文件、绑定的支付方式,攻击者都能看到。这种攻击不直接偷钱,但危害更隐蔽。防御方法和普通CSRF一样,登录表单也要加令牌。

我个人的经验是:任何状态改变的操作,都必须同时满足三个条件——验证CSRF令牌、检查Origin/Referer头、Cookie设SameSite。别只靠一种。Origin头在现代浏览器里跨站请求会带上,但有些隐私设置会去掉它,所以只能作为辅助。令牌要绑定用户会话,别用全局固定值。令牌别放在URL里,会泄露到Referer和日志中。

最后说个容易犯的错:令牌验证失败时,别返回“令牌错误”这种具体信息,直接返回403或者跳转到首页。否则攻击者能通过错误信息判断令牌是否存在、是否过期,辅助爆破。安全设计里,模糊化错误信息是基本功。

CSRF不像SQL注入那样直接拖库,但它能借用户之手完成攻击者想做的任何事。一个转账、一次改密、一条删除,都可能因为一个没加令牌的接口而失控。检查你写的每个表单、每个AJAX请求,别让浏览器替用户做决定。

```