实现了一下CSRF原来不像背的那么简单,网络安全零基础入门到精通教程!

一、前言

之前面试经常被问到 CSRF, 跨站请求伪造

大概流程比较简单, 大概就是用户登录了A页面,存下来登录凭证(cookie), 攻击者有诱导受害者打开了B页面, B页面中正好像A发送了一个跨域请求,并把cookie进行了携带, 欺骗浏览器以为是用户的行为,进而达到执行危险行为的目的,完成攻击

上面就是面试时,我们通常的回答, 但是到底是不是真是这样呢? 难道这么容易伪造吗?于是我就打算试一下能不能实现

二、实现

接下来,我们就通过node起两个服务 A服务(端口3000)和B服务(端口4000), 然后通过两个页面 A页面、和B页面模拟一下CSRF。

我们先约定一下 B页面是正常的页面, 起一个 4000 的服务, 然后 A页面为伪造者的网站, 服务为3000

先看B页面的代码, B页面有一个登录,和一个获取数据的按钮, 模拟正常网站,需要登录后才可以获取数据

<body>
    <div>
      正常 页面 B
      <button onclick="login()">登录</button>
      <button onclick="getList()">拿数据</button>
      <ul class="box"></ul>
      <div class="tip"></div>
    </div>
  </body>
  <script>
    async function login() {
      const response = await fetch("http://localhost:4000/login", {
        method: "POST",
      });
      const res = await response.json();
      console.log(res, "writeCookie");
      if (res.data === "success") {
        document.querySelector(".tip").innerHTML = "登录成功, 可以拿数据";
      }
    }

    async function getList() {
      const response = await fetch("http://localhost:4000/list", {
        method: "GET",
      });

      if (response.status === 500) {
        document.querySelector(".tip").innerHTML = "cookie失效,请先登录!";
        document.querySelector(".box").innerHTML = "";
      } else {
        document.querySelector(".tip").innerHTML = "";
        const data = await response.json();
        let html = "";
        data.map((el) => {
          html += `<div>${el.id} - ${el.name}</div>`;
        });
        document.querySelector(".box").innerHTML = html;
      }
    }
  </script>

在看B页面的服务端代码如下:

const express = require("express");
const app = express();

app.use(express.json()); // json
app.use(express.urlencoded({ extends: true })); // x-www-form-urlencoded

app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  // 允许客户端跨域传递的请求头
  res.header("Access-Control-Allow-Headers", "Content-Type");
  next();
});

app.use(express.static("public"));

app.get("/list", (req, res) => {
  const cookie = req.headers.cookie;
  if (cookie !== "user=allow") {
    res.sendStatus("500");
  } else {
    res.json([
      { id: 1, name: "zhangsan" },
      { id: 2, name: "lisi" },
    ]);
  }
});

app.post("/login", (req, res) => {
  res.cookie("user", "allow", {
    expires: new Date(Date.now() + 86400 * 1000),
  });
  res.send({ data: "success" });
});

app.post("/delete", (req, res) => {
  const cookie = req.headers.cookie;
  if (req.headers.referer !== req.headers.host) {
    console.log("should ban!");
  }
  if (cookie !== "user=allow") {
    res.sendStatus("500");
  } else {
    res.json({
      data: "delete success",
    });
  }
});

app.listen(4000, () => {
  console.log("sever 4000");
});

B 服务有三个接口, 登录、获取列表、删除。再触发登录接口的时候,会像浏览器写入cookie, 再删除或者获取列表的时候,都先检测有没有将指定的cookie传回,如果有就认为有权限

然后我们打开 http://localhost:4000/B.html 先看看B页面功能是否都正常

在这里插入图片描述

我们看到此时 B 页面功能和接口都是正常的, cookie 也正常进行了设置,每次获取数据的时候,都是会携带cookie到服务端校验的

那么接下来我们就通过A页面,起一个3000端口的服务,来模拟一下跨域情况下,能否完成获取 B服务器数据,调用 B 服务器删除接口的功能

A页面代码

  <body>
    <div>
      伪造者页面 A
      <form action="http://localhost:4000/delete" method="POST">
        <input type="hidden" name="account" value="xiaoming" />
      </form>
      <script>
        // 这行可以放到控制台执行,便于观察效果
        // document.forms[0].submit();
      </script>
    </div>
    <ul class="box"></ul>
    <div class="tip"></div>
</body>

A页面服务端代码

  <body>
    <div>
      伪造者页面 A
      <form action="http://localhost:4000/delete" method="POST">
        <input type="hidden" name="account" value="xiaoming" />
      </form>
      <script>
        // 这行可以放到控制台输入
        // document.forms[0].submit();
      </script>
      <script src="http://localhost:4000/list"></script>
    </div>
  </body>

于是在我们 访问 http://localhost:3000/A.html 页面的时候发现, 发现list列表确实,请求到了, 控制台输入 document.forms[0].submit() 时发现,确实删除也发送成功了, 是不是说明csrf就成功了呢, 但是其实还不是, 关键的一点是, 我们在B页面设置cookie的时候, domain设置的是 localhost 那么其实在A页面, 发送请求的时候cookie是共享的状态, 真实情况下,肯定不会是这样, 那么为了模拟真实情况, 我们把 http://localhost:3000/A.html 改为 http://127.0.0.1:3000/A.html, 这时发现,以及无法访问了, 那么这是怎么回事呢, 说好的,cookie 会在获取过登录凭证下, 再次访问时可以携带呢。

在这里插入图片描述

于是,想了半天也没有想明白, 难道是浏览器限制严格进行了限制, 限制规避了这个问题?难道我们背的面试题是错误的?

有知道的小伙伴,欢迎下方讨论

三、 sameSite 设置

其实上面的问题无法实现 CSRF 是由于 SameSite 的设置问题, 其实关键是要设置 SameSite=None 简单看一下下面三个设置的区分

  • None: 通常用于处理第三方提供的资源或服务,白话就是不受域的限制,不同域间可以传递身份验证凭证(可以做单点登录), 但是要配合Secure 标志, 即实用 HTTPS 协议

  • Strict: 严格模式,完全禁止,只有自己网站的请求发送cookie

  • Lax:浏览器的默认值, 用户从外部导航到你的网站时,可以发送cookie

接下来我们就把上面的 B 服务进行改造, 再设置cookie的时候, 同时设置 sameSite 和 Secure

app.post("/login", (req, res) => {
  res.cookie("user", "allow", {
    expires: new Date(Date.now() + 86400 * 1000),
    sameSite: "none",
    secure: true,
  });
  res.send({ data: "success" });
});

然后再次打开 http://127.0.0.1:3000/A.html 会发现 cookie 正常设置到了浏览器,

在这里插入图片描述

我们再次在控制台 输入 document.forms[0].submit() 发现删除操作也正常执行了

在这里插入图片描述

如图,我们就完成了 CSRF 攻击

四、总结

CSRF —— 跨域请求伪造, 顾名思义,攻击是发生在第三方页面, 利用了浏览器在跨域的情况下,在一些跨域的请求时(如 script 、 img、 form 表单提交、 a标签等)可以携带cookie的特性, 使得一些伪造的构建请求可以执行成功, 进而对正常网页造成危害的行为。我们通过代码也能看出来, 其实现代浏览器对跨域cookie的限制比较多了, 但是在一些情况下,依然可以发生, 比如设置 sameSite: None 时,虽然会增加安全风险, 但是 samesite为 None 又有一些场景需要跨域下可以共享cookie,比如单点登录、内嵌广告、资源时, 所以无法完全禁止, 由此我们就可以总结一些避免CSRF攻击的手段了,

  1. 使用同源策略, 限制不同来源直接资源共享

  2. 检查 Refer 头部, 设置白名单(并不保险,比如 a标签可以设置 rel=“noreferrer” 绕开refer检查

  3. 使用 CSRF Token 每个用户会话设置一个不可预测 唯一的 token,每次请求校验

  4. 尽量使用 POST 和 其他安全的HTTP方法, 不在 GET 请求中实现数据写入操作

  5. 敏感操作,增加验证码二次验证

  6. 服务端把 Cookie 的SameSite 属性设置为 Lax

  7. 表单提交增加 csrfToken 隐藏字段

额外:由于CSRF攻击原理是浏览器自动携带 Cookie, 如果放开跨站Cookie有CSRF 风险,但是不放开又无法做单点登录, 所以对于SPA应用来说, JWT 认证的方式更好一些,token 会在 Authorization 头部进行传递

网络安全学习资源分享:

给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

因篇幅有限,仅展示部分资料,朋友们如果有需要全套《网络安全入门+进阶学习资源包,需要点击下方链接即可前往获取

读者福利 | CSDN大礼包:《网络安全入门&进阶学习资源包》免费分享 (安全链接,放心点击)

👉1.成长路线图&学习规划👈

要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

在这里插入图片描述
在这里插入图片描述

👉2.网安入门到进阶视频教程👈

很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。(全套教程文末领取哈)
在这里插入图片描述

在这里插入图片描述

👉3.SRC&黑客文档👈

大家最喜欢也是最关心的SRC技术文籍&黑客技术也有收录

SRC技术文籍:

在这里插入图片描述

黑客资料由于是敏感资源,这里不能直接展示哦!(全套教程文末领取哈)

👉4.护网行动资料👈

其中关于HW护网行动,也准备了对应的资料,这些内容可相当于比赛的金手指!

在这里插入图片描述

👉5.黑客必读书单👈

在这里插入图片描述

👉6.网络安全岗面试题合集👈

当你自学到这里,你就要开始思考找工作的事情了,而工作绕不开的就是真题和面试题。
在这里插入图片描述
所有资料共282G,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,可以扫描下方二维码或链接免费领取~

读者福利 | CSDN大礼包:《网络安全入门&进阶学习资源包》免费分享 (安全链接,放心点击)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值