浏览器5-安全

5 阅读6分钟

同源策略

同源策略:url协议、域名、端口相同,就是同源。默认两个不同的源之间不能操作dom和访问资源

1.dom层面,不能互相访问,postmessage跨文档消息机制

2.数据层面,cookie,localstorage不能互相读取,

3.网络层面,不能跨域请求,跨域资源共享策略

安全问题

xss攻击,恶意脚本攻击

有几种类型的xss攻击

  1. 存储型,在提交表单时把脚本提交,服务端保存在数据库,当返回给前端再使用时就会执行脚本

  2. 反射型,提交表单,服务端不保存,处理后即返回。提交脚本也就会返回脚本

  3. 页面劫持,本地抓包等方式,不经过服务端直接控制页面

解决方案

  1. 服务端对脚本过滤

  2. csp策略:资源黑白名单,禁止加载哪些脚本,禁止向第三方域提交数据

  3. 设置cookie时加上httponly,则cookie无法通过脚本document.cookie读取

csrf攻击,跨站请求伪造

类型

  1. img标签的src是一个请求,而不是图片资源。

  2. 点一个链接,自动发起请求

解决方案

  1. 设置cookie的samesite属性值是strict,在第三方域下请求本域时就不会带上有这个属性值的cookie,可以防止第三方域提交
  2. 服务器通过referer、origin判断请求来源
  3. csrf token,通过前后端约定的特殊token,不存放在cookie中来判断是否安全

详细(后来用到了看的一篇文章)

CSRF,全称是 Cross-Site Request Forgery,中文常译为“跨站请求伪造”。它也被称为 One-Click Attack(一键攻击)或 Session Riding(会话骑乘)。

核心思想攻击者诱骗已经登录了目标网站(例如网上银行)的用户,去访问一个恶意网站或点击一个恶意链接。这个恶意网站会利用用户的登录状态(浏览器中保存的 Cookie),以用户的身份向目标网站发起一个用户自己并不知情的请求(比如转账操作)。

简单来说,就是 “冒充用户,发起了用户不想发的请求”

攻击原理

要理解 CSRF 攻击的原理,需要抓住几个关键点:

  1. 用户已登录并保持会话:用户已经登录了目标网站(如 bank.com),浏览器中保存了该网站的会话 Cookie(Session Cookie)。这个 Cookie 是用户身份的凭证。
  2. 浏览器的同源策略不限制跨域请求的“发送”:浏览器虽然限制不同源的网站之间读取对方的 DOM 或响应数据(这是为了防护 XSS),但它不禁止从一个网站向另一个网站的服务器发送请求。当浏览器向 bank.com/transfer 发送请求时,它会自动地、默默地bank.com 对应的 Cookie 附带上。
  3. 请求的不可预测性:对于服务器来说,它收到了一个带有合法 Cookie 的请求,它就认为这是来自用户的真实意愿操作,因为它无法区分这个请求是用户主动在银行页面上点击的,还是从一个恶意网站上自动发出的。

攻击成功的三要素

  • 请求是跨域的:攻击发生在恶意网站(evil.com),而目标是银行网站(bank.com)。
  • 请求是幂等的:通常攻击利用的是 GET 或 POST 请求,这些请求会改变服务器状态(如修改数据、转账)。
  • 浏览器自动携带认证信息:关键是浏览器会自动在请求中附上用户的 Cookie。

攻击场景举例

让我们通过几个具体的场景来加深理解。

场景一:GET 请求攻击(最简单直接)

假设银行提供一个通过 GET 请求转账的接口,这本身是非常不安全的:

https://bank.com/transfer?to=attacker_account&amount=1000

攻击步骤:

  1. 用户登录 bank.com,会话 Cookie 有效。

  2. 用户在工作之余,被诱导访问了攻击者精心构造的恶意网站 evil.com

  3. evil.com 的页面中隐藏着一个标签,其 src 属性指向银行的转账接口:

    <img src="https://bank.com/transfer?to=attacker_account&amount=1000" width="0" height="0" />
    
  4. 浏览器在加载这个图片时,会向 bank.com 发起一个 GET 请求,并自动带上用户的 Cookie。

  5. 银行服务器验证 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>

攻击步骤:

  1. 用户同样已登录 bank.com

  2. 用户访问 evil.com

  3. 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>
    
  4. 页面加载后,JavaScript 会立即自动提交这个表单。浏览器会向 bank.com 发起一个 POST 请求,并自动带上用户的 Cookie。

  5. 转账再次成功。

场景三:社交工程与链接攻击

攻击者可能不会做一个完整的网站,而是发送一封钓鱼邮件或一条即时消息,里面包含一个看似无害的链接:

https://bank.com/transfer?to=attacker_account&amount=1000

并诱导用户点击,比如伪装成“查看你朋友的照片”、“领取你的奖金”等。用户点击后,同样会触发 GET 请求。

防范措施

理解了原理,防范措施就很有针对性了:核心是让服务器有能力区分“合法请求”和“伪造请求”。

  1. 同源检测

    • 检查 Origin Header 或 Referer Header:服务器在处理敏感请求时,检查请求头中的 OriginReferer 字段。如果请求不是来自合法的源(即你自己的网站域名),则拒绝请求。这是最有效和最简单的方法之一。
  2. CSRF Token(最主流、最可靠的方案)

    • 原理:在表单(或请求数据)中嵌入一个随机生成的、不可预测的令牌(Token)。这个 Token 与用户的会话相关联。
    • 流程
      1. 服务器生成 Token,将其存放在用户的 Session 中,同时将其作为隐藏字段放入表单。
      2. 用户提交表单时,Token 随请求一起发送到服务器。
      3. 服务器验证请求中的 Token 是否与 Session 中的一致。
    • 为什么有效:攻击者构造的恶意网站无法知道这个 Token 的值(因为受同源策略保护,他无法读取 bank.com 页面的内容),因此他发起的伪造请求中无法包含正确的 Token,服务器验证会失败。
  3. SameSite Cookie 属性

    • 原理:这是一种由浏览器提供的、从源头解决问题的方案。在设置 Cookie 时,可以指定 SameSite 属性。
    • SameSite=Strict:最严格,浏览器完全不会在跨站请求中发送此 Cookie。
    • SameSite=Lax:宽松模式,在安全的 HTTP 方法(如 GET)的跨站请求中会发送,但 POST 等不安全方法不会发送。这能有效防御 CSRF,同时不影响用户体验(例如从搜索引擎链接跳转过来还能保持登录状态)。
    • SameSite=None:等同于不设置,Cookie 在所有上下文中发送。需要同时设置 Secure 属性(仅限 HTTPS)。
  4. 双重验证(例如短信/邮箱验证码)

    • 在进行关键操作(如转账、修改密码)时,要求用户进行二次验证。这虽然不是专门为 CSRF 设计的,但能有效防御此类攻击,因为攻击者无法获取验证码。