用 node 实战一下 CSRF

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

前言

之前面试经常被问到 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页面功能是否都正常

屏幕截图 2023-07-05 232255.png

我们看到此时 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 会在获取过登录凭证下, 再次访问时可以携带呢。

屏幕截图 2023-07-05 232338.png

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

相关文章
|
4月前
|
数据采集 并行计算 JavaScript
实战指南:在 Node.js 中利用多线程提升性能
在 Node.js 的世界中,多线程技术一直是一个受到广泛关注的领域。最初,Node.js 设计为单线程模式。随着技术发展,Node.js 引入了多线程支持,进而利用多核处理器的强大性能,提升了应用性能。接下来的内容将深入探讨 Node.js 如何实现多线程,以及在何种场合应该采用这种技术。
|
11月前
|
JSON 前端开发 JavaScript
前端AJAX入门到实战,学习前端框架前必会的(ajax+node.js+webpack+git)(一)
前端AJAX入门到实战,学习前端框架前必会的(ajax+node.js+webpack+git)(一)
567 0
|
3月前
|
JavaScript 网络协议 前端开发
【Nodejs】WebSocket 全面解析+实战演练——(Nodejs实现简易聊天室)
【Nodejs】WebSocket 全面解析+实战演练——(Nodejs实现简易聊天室)
320 0
|
2月前
|
SQL 安全 数据库
Python Web开发者必学:SQL注入、XSS、CSRF攻击与防御实战演练!
【7月更文挑战第26天】在 Python Web 开发中, 安全性至关重要。本文聚焦 SQL 注入、XSS 和 CSRF 这三大安全威胁,提供实战防御策略。SQL 注入可通过参数化查询和 ORM 框架来防范;XSS 则需 HTML 转义用户输入与实施 CSP;CSRF 防御依赖 CSRF 令牌和双重提交 Cookie。掌握这些技巧,能有效加固 Web 应用的安全防线。安全是持续的过程,需贯穿开发始终。
65 1
Python Web开发者必学:SQL注入、XSS、CSRF攻击与防御实战演练!
|
12天前
|
大数据 数据处理 分布式计算
JSF 逆袭大数据江湖!看前端框架如何挑战数据处理极限?揭秘这场技术与勇气的较量!
【8月更文挑战第31天】在信息爆炸时代,大数据已成为企业和政府决策的关键。JavaServer Faces(JSF)作为标准的 Java Web 框架,如何与大数据技术结合,高效处理大规模数据集?本文探讨大数据的挑战与机遇,介绍 JSF 与 Hadoop、Apache Spark 等技术的融合,展示其实现高效数据存储和处理的潜力,并提供示例代码,助您构建强大的大数据系统。
21 0
|
1月前
|
存储 缓存 JavaScript
构建高效后端服务:Node.js与Express框架的实战应用
【8月更文挑战第2天】在数字化时代的浪潮中,后端服务的构建成为了软件开发的核心。本文将深入探讨如何利用Node.js和Express框架搭建一个高效、可扩展的后端服务。我们将通过实际代码示例,展示从零开始创建一个RESTful API的全过程,包括路由设置、中间件使用以及数据库连接等关键步骤。此外,文章还将触及性能优化和安全性考量,旨在为读者提供一套完整的后端开发解决方案。让我们一同走进Node.js和Express的世界,探索它们如何助力现代Web应用的开发。
|
2月前
|
JavaScript 应用服务中间件 API
Node.js搭建REST API实战:从基础到部署
【7月更文挑战第18天】通过以上步骤,你可以将你的Node.js REST API从开发环境顺利迁移到生产环境,并利用各种工具和技术来确保应用的稳定性、安全性和可扩展性。
|
4月前
|
JavaScript 前端开发 开发工具
【JavaScript 技术专栏】Node.js 基础与实战
【4月更文挑战第30天】本文介绍了Node.js的基础及应用,包括事件驱动的非阻塞I/O、单线程模型和模块系统。内容涵盖Node.js的安装配置、核心模块(如http、fs、path)及实战应用,如Web服务器、文件操作和实时通信。文章还讨论了Node.js的优劣势、与其他技术的结合,并通过案例分析展示项目实施流程。总结来说,Node.js是高效后端开发工具,适合构建高并发应用,其广阔的应用前景值得开发者探索。
49 1
|
4月前
|
安全 关系型数据库 MySQL
node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)
node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)
72 3
|
4月前
|
编解码 前端开发 JavaScript
node实战——koa实现文件下载和图片/pdf/视频预览(node后端储备知识)
node实战——koa实现文件下载和图片/pdf/视频预览(node后端储备知识)
179 1