同源策略
同源策略:url协议、域名、端口相同,就是同源。默认两个不同的源之间不能操作dom和访问资源
1.dom层面,不能互相访问,postmessage跨文档消息机制
2.数据层面,cookie,localstorage不能互相读取,
3.网络层面,不能跨域请求,跨域资源共享策略
安全问题
xss攻击,恶意脚本攻击
有几种类型的xss攻击
-
存储型,在提交表单时把脚本提交,服务端保存在数据库,当返回给前端再使用时就会执行脚本
-
反射型,提交表单,服务端不保存,处理后即返回。提交脚本也就会返回脚本
-
页面劫持,本地抓包等方式,不经过服务端直接控制页面
解决方案
-
服务端对脚本过滤
-
csp策略:资源黑白名单,禁止加载哪些脚本,禁止向第三方域提交数据
-
设置cookie时加上httponly,则cookie无法通过脚本document.cookie读取
csrf攻击,跨站请求伪造
类型
-
img标签的src是一个请求,而不是图片资源。
-
点一个链接,自动发起请求
解决方案
- 设置cookie的samesite属性值是strict,在第三方域下请求本域时就不会带上有这个属性值的cookie,可以防止第三方域提交
- 服务器通过referer、origin判断请求来源
- csrf token,通过前后端约定的特殊token,不存放在cookie中来判断是否安全
详细(后来用到了看的一篇文章)
CSRF,全称是 Cross-Site Request Forgery,中文常译为“跨站请求伪造”。它也被称为 One-Click Attack(一键攻击)或 Session Riding(会话骑乘)。
核心思想:攻击者诱骗已经登录了目标网站(例如网上银行)的用户,去访问一个恶意网站或点击一个恶意链接。这个恶意网站会利用用户的登录状态(浏览器中保存的 Cookie),以用户的身份向目标网站发起一个用户自己并不知情的请求(比如转账操作)。
简单来说,就是 “冒充用户,发起了用户不想发的请求”。
攻击原理
要理解 CSRF 攻击的原理,需要抓住几个关键点:
- 用户已登录并保持会话:用户已经登录了目标网站(如
bank.com),浏览器中保存了该网站的会话 Cookie(Session Cookie)。这个 Cookie 是用户身份的凭证。 - 浏览器的同源策略不限制跨域请求的“发送”:浏览器虽然限制不同源的网站之间读取对方的 DOM 或响应数据(这是为了防护 XSS),但它不禁止从一个网站向另一个网站的服务器发送请求。当浏览器向
bank.com/transfer发送请求时,它会自动地、默默地将bank.com对应的 Cookie 附带上。 - 请求的不可预测性:对于服务器来说,它收到了一个带有合法 Cookie 的请求,它就认为这是来自用户的真实意愿操作,因为它无法区分这个请求是用户主动在银行页面上点击的,还是从一个恶意网站上自动发出的。
攻击成功的三要素:
- 请求是跨域的:攻击发生在恶意网站(
evil.com),而目标是银行网站(bank.com)。 - 请求是幂等的:通常攻击利用的是 GET 或 POST 请求,这些请求会改变服务器状态(如修改数据、转账)。
- 浏览器自动携带认证信息:关键是浏览器会自动在请求中附上用户的 Cookie。
攻击场景举例
让我们通过几个具体的场景来加深理解。
场景一:GET 请求攻击(最简单直接)
假设银行提供一个通过 GET 请求转账的接口,这本身是非常不安全的:
https://bank.com/transfer?to=attacker_account&amount=1000
攻击步骤:
-
用户登录
bank.com,会话 Cookie 有效。 -
用户在工作之余,被诱导访问了攻击者精心构造的恶意网站
evil.com。 -
evil.com的页面中隐藏着一个标签,其src属性指向银行的转账接口:<img src="https://bank.com/transfer?to=attacker_account&amount=1000" width="0" height="0" /> -
浏览器在加载这个图片时,会向
bank.com发起一个 GET 请求,并自动带上用户的 Cookie。 -
银行服务器验证 Cookie 有效,认为是用户发起的转账操作,于是成功将 1000 元转给了
attacker_account。而用户对此毫无察觉,只看到了evil.com的页面,可能是一个空白或正常的页面。
场景二:POST 请求攻击(更常见)
现代网站更倾向于使用 POST 请求执行重要操作。假设银行的转账表单如下:
<form action="https://bank.com/transfer" method="POST">
<input type="text" name="to"/>
<input type="number" name="amount"/>
<input type="submit" value="Transfer"/>
</form>
攻击步骤:
-
用户同样已登录
bank.com。 -
用户访问
evil.com。 -
evil.com的页面中包含一个自动提交的隐藏表单:<form id="csrf-form" action="https://bank.com/transfer" method="POST" style="display: none;"> <input type="hidden" name="to" value="attacker_account"/> <input type="hidden" name="amount" value="1000"/> </form> <script> document.getElementById('csrf-form').submit(); </script> -
页面加载后,JavaScript 会立即自动提交这个表单。浏览器会向
bank.com发起一个 POST 请求,并自动带上用户的 Cookie。 -
转账再次成功。
场景三:社交工程与链接攻击
攻击者可能不会做一个完整的网站,而是发送一封钓鱼邮件或一条即时消息,里面包含一个看似无害的链接:
https://bank.com/transfer?to=attacker_account&amount=1000
并诱导用户点击,比如伪装成“查看你朋友的照片”、“领取你的奖金”等。用户点击后,同样会触发 GET 请求。
防范措施
理解了原理,防范措施就很有针对性了:核心是让服务器有能力区分“合法请求”和“伪造请求”。
-
同源检测
- 检查 Origin Header 或 Referer Header:服务器在处理敏感请求时,检查请求头中的
Origin或Referer字段。如果请求不是来自合法的源(即你自己的网站域名),则拒绝请求。这是最有效和最简单的方法之一。
- 检查 Origin Header 或 Referer Header:服务器在处理敏感请求时,检查请求头中的
-
CSRF Token(最主流、最可靠的方案)
- 原理:在表单(或请求数据)中嵌入一个随机生成的、不可预测的令牌(Token)。这个 Token 与用户的会话相关联。
- 流程:
- 服务器生成 Token,将其存放在用户的 Session 中,同时将其作为隐藏字段放入表单。
- 用户提交表单时,Token 随请求一起发送到服务器。
- 服务器验证请求中的 Token 是否与 Session 中的一致。
- 为什么有效:攻击者构造的恶意网站无法知道这个 Token 的值(因为受同源策略保护,他无法读取
bank.com页面的内容),因此他发起的伪造请求中无法包含正确的 Token,服务器验证会失败。
-
SameSite Cookie 属性
- 原理:这是一种由浏览器提供的、从源头解决问题的方案。在设置 Cookie 时,可以指定
SameSite属性。 SameSite=Strict:最严格,浏览器完全不会在跨站请求中发送此 Cookie。SameSite=Lax:宽松模式,在安全的 HTTP 方法(如 GET)的跨站请求中会发送,但 POST 等不安全方法不会发送。这能有效防御 CSRF,同时不影响用户体验(例如从搜索引擎链接跳转过来还能保持登录状态)。SameSite=None:等同于不设置,Cookie 在所有上下文中发送。需要同时设置Secure属性(仅限 HTTPS)。
- 原理:这是一种由浏览器提供的、从源头解决问题的方案。在设置 Cookie 时,可以指定
-
双重验证(例如短信/邮箱验证码)
- 在进行关键操作(如转账、修改密码)时,要求用户进行二次验证。这虽然不是专门为 CSRF 设计的,但能有效防御此类攻击,因为攻击者无法获取验证码。