什么是会话固定以及如何在 Node.js 中防止它
什么是会话固定以及如何在 Node.js 中防止它
在深入讨论之前,我们需要了解会话是什么以及会话身份验证如何工作。
什么是会话?
正如我们所知,HTTP 请求是无状态的,这意味着当我们发送登录请求时,并且我们有有效的用户名和密码,没有默认机制可以知道我们是发送下一个请求的同一个人。为了解决这个问题,换句话说,使请求有状态,有一些常用的方法,如Cookie、隐藏表单字段、URL 参数、浏览器存储、JWT 和 Session。在本文中,我们将重点关注Session。
Session是存储在服务器上的数据。每个客户端都会获得一个与服务器上的数据相关的唯一标识符 。客户端必须在每个请求上发送此唯一标识符,以便我们知道谁发送了此请求。该标识符可以在 cookie 或 URL 参数中发送。
下面是使用express-session和express创建session的简单示例:
const app = require('express')();
const session = require('express-session');
app.use(require('cookie-parser')());
app.use(require('body-parser').json());app.use(session({secret: 'secret',cookie: { maxAge: 60000 },name: 'sessionId'
}));app.get('/', (req, res) => {res.send('ping');
});app.listen(3000, () => {console.log('Server is running on port 3000');
});
当第一次发送请求时,express-session中间件会创建一个新的唯一标识符,并将其设置为 cookie 后再将其存储在某处(在本例中为内存,但我们也可以传递自定义存储)。在会话中间件的选项中,我们使用了sessionId存储此唯一标识符的密钥名称。现在,如果我们发送请求,我们会看到如下内容:

浏览器现在设置此 cookie 并自动存储它以供进一步请求。如果我们发送包含有效会话的请求(该会话存在于我们的会话存储中 - 在本例中为内存),在响应中获取标头的标头就不再包含Set-Cookie字段了:

当用户登录时,我们可以将用户信息存储在 cookie 中(序列化),也可以将其存储在数据库中并将数据与sessionId进行绑定. 让我们使用 Map 作为我们的简单数据库:
const db = new Map();
app.get('/me', (req, res) => {const user = db.get(req.sessionID);res.json({ mySessionId: req.sessionID, me: user ? user : 'anonymous' });
});
const users = [{ name: 'leo', age: 19 }, { name: 'joe', age: 20 }];
app.post('/login', (req, res) => {const { name } = req.body;const user = users.find(u => u.name === name);if (user) {db.set(req.sessionID, user);res.send('ok');} else {res.send('try again');}
});
攻击者可以创建有效的会话 ID 吗?
在本例中,我们使用的是express-session。可以看到我们向express-session中间件传递了一个secret值。这个secret用于签署我们的 cookie 的值。它只是意味着我们确信是我们生成了sessionId。
session示例:
sessionId=s%3AL6j4T8hBwMk1ulJqGoisZbAxUOkOuQqP.x5UxPQEtKrj3sWrIy6S01CQRjAtp4biVs4H2zgqmSs
第一部分:s%3A简单来说:s:这是一个前缀,表明我们的 cookie 会话已签名!
第二部分:L6j4T8hBwMk1ulJqGoisZbAxUOkOuQqP这是我们的sessionId,我们在数据库中使用它来关联数据。
第三部分:x5UxPQEtKrj3sWrIy6S01CQRjAtp4biVs4H2zgqmSs这是签字部分。我们使用我们的secret生成了此文本,因此我们可以确定此 cookie 是由我们生成的。
我们可以简单地重新生成这个标志并检查它是否有效:
const crypto = require('crypto');
const secret = 'secret';
const sessionId = 'L6j4T8hBwMk1ulJqGoisZbAxUOkOuQqP';
const hmac = crypto.createHmac('sha256', secret);
hmac.update(sessionId);
const signature = hmac.digest('base64').replace(/\=+$/, '');
console.log(signature); // x5UxPQEtKrj3sWrIy6S01CQRjAtp4biVs4H2zgqmSs
什么是会话固定?
在会话固定攻击中,攻击者劫持有效的用户会话。我们说过,我们对 cookie 进行签名是为了确保没有人可以劫持其他用户的有效会话。但是,如果攻击者拥有自己的有效会话并尝试将其与另一个用户关联怎么办?在这种情况下,他可以代表受害者采取行动。
当我们没有在 Login 之类的操作上生成新的 sessionIds(唯一标识符)时,就会出现问题。
通过会话固定,攻击者可以劫持有效的用户会话,了解此漏洞并防范它绝对重要。
攻击者如何才能做到这一点?
其中一种情况是攻击者可以物理访问计算机。作为攻击者,我们可以选择一台共享计算机,打开某个已经登录过的网页,然后复制session后发送请求。
sessionId在有些网站在请求中作为 URL 参数传递。在这种情况下,如果攻击者使用其 URL 参数提供登录页面的链接,sessionId则有可能被利用。
如何防止会话固定?
登录时生成新会话
主要解决方案非常简单,通过这样做,始终可以确保不会发生此会话覆盖!
让我们改变代码:
app.post('/login', (req, res) => {const { name } = req.body;req.session.regenerate(err => {if (err) {res.send('error');} else {const user = users.find(u => u.name === name);if (user) {db.set(req.sessionID, user);res.send('ok');} else {res.send('try again');}}});
});
我们可以使用regenerate函数,以便每次有人想要登录时分配一个新的会话。无论我们是否传递会话cookie,它都会生成一个新的会话Id并将其发送到客户端中。
仅使用HTTP Only 的 Cookie
当我们使用HTTP Only时,这意味着只有服务器可以通过Set-Cookie标头设置cookie,而客户端(浏览器JavaScript)无法更改它。所以即使我们的应用存在XSS漏洞,攻击者也无法更改sessionId(cookie)。
防范 XSS
会话固定可以与 XSS 攻击结合使用,从而更加有效,因此如果我们担心会话固定,那么认真对待 XSS 攻击确实有意义。
合理的会话过期时间
会话过期时间应该符合我们的应用程序特定要求,如果我们更关心安全性,那么它应该更短,反之亦然。
正确的注销实施
注销时,我们必须正确销毁现有会话及其与任何数据的关联。否则,这些会话可以在注销后使用。(仅从客户端浏览器中删除 cookie 是不够的!)
相关文章:
什么是会话固定以及如何在 Node.js 中防止它
什么是会话固定以及如何在 Node.js 中防止它 在深入讨论之前,我们需要了解会话是什么以及会话身份验证如何工作。 什么是会话? 正如我们所知,HTTP 请求是无状态的,这意味着当我们发送登录请求时,并且我们有有效的用…...
代码随想录算法训练营第五十二天|300. 最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组
第九章 动态规划part13 300. 最长递增子序列 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数…...
使用 Hugging Face Transformer 微调 BERT
微调 BERT有助于将其语言理解能力扩展到更新的文本领域。BERT 的与众不同之处在于它能够掌握句子的上下文关系,理解每个单词相对于其邻居的含义。我们将使用 Hugging Face Transformers 训练 BERT,还将教 BERT 分析 Arxiv 的摘要并将其分类为 11 个类别之一。 为什么微调 BER…...
Vue原型对象
原型对象 prototype 称为:显示的原型属性,用法:函数.prototype,例如:Vue.prototype __proto__称为:隐式的原型属性,用户:实例.proto,例如:vm.proto 不管如何 …...
向量数据库的分类概况
保存和检索矢量数据的五种方法: 像 Pinecone 这样的纯矢量数据库 全文搜索数据库,例如 ElasticSearch 矢量库,如 Faiss、Annoy 和 Hnswlib 支持矢量的NoSQL 数据库,例如 MongoDB、Cosmos DB 和 Cassandra 支持矢量的SQL 数据库&am…...
工业镜头的类别
工业镜头的类别 按照等效焦距分为: 广角镜头 中焦距镜头 长焦距镜头 广角镜头 等效焦距小于标准镜头(等效焦距为50mm)的镜头。特点是最小工作距离短,景深大,视角大。常常表现为桶形畸变。 中焦距镜头 焦距介于广角镜…...
实验11 SQL互联网业务查询-2
这就是SQL题带给我的自信😕 可能发题解到博客上,主要是写完一遍实在不想看第二遍,太长了,优化都不想优化,看着头疼。 技术栈 – WhiteNights Site 一 USE mydata; #请在此处添加实现代码 ########## Begin #######…...
C++知识点梳理:C++ templates
c模板包括:类模板、类(非模板类和模板类)方法模板、函数模板、别名模板、变量模板。 类模板模板参数列表说明: 1)类定义 仅模板参数列表声明,template<>行。 类名后无需参数说明<>。 2…...
uniapp form表单提交事件手动调用
背景: UI把提交的按钮弄成了图片,之前的button不能用了。 <button form-type"submit">搜索</button> 实现: html: 通过 this.$refs.fd 获取到form的vue对象。手动调用里面的_onSubmit()方法。 methods:…...
Accelerate 0.24.0文档 三:超大模型推理(内存估算、Sharded checkpoints、bitsandbytes量化、分布式推理)
文章目录 一、内存估算1.1 Gradio Demos1.2 The Command 二、使用Accelerate加载超大模型2.1 模型加载的常规流程2.2 加载空模型2.3 分片检查点(Sharded checkpoints)2.4 示例:使用Accelerate推理GPT2-1.5B2.5 device_map 三、bitsandbytes量…...
HackTheBox-Starting Point--Tier 2---Markup
文章目录 一 Markup测试过程1.1 打点1.2 权限获取1.3 权限升级 二 题目 一 Markup测试过程 1.1 打点 1.端口扫描 nmap -A -Pn -sC 10.129.95.1922.访问web网站,登录口爆破发现存在弱口令admin:password 3.抓包,发现请求体是XML格式 4.尝试使…...
android studio导入eclipse项目
网上下载一个老工程,.project文件里有eclipse。 android studio导入eclipse项目 eclipse项目结构 Android studio文件结构 下面是导入步骤: 第一步,打开一个项目。 选择File->New->Import Project 第二步,选择Eclipse项目根…...
如何利用AI实现银行存量客户的营销?
近年来,大数据、人工智能等热门关键字多次被写入中央文件与国务院政府工作报告,目前已上升为国家战略,并将深刻地改变现有行业的游戏规则。 金融行业是当今大数据、人工智能应用最广、最深的领域之一。随着数据仓库和数据科学的发展ÿ…...
springboot327基于Java的医院急诊系统
交流学习: 更多项目: 全网最全的Java成品项目列表 https://docs.qq.com/doc/DUXdsVlhIdVlsemdX 演示 项目功能演示: ————————————————...
Unity3d 导入中文字体转TMPtext asset
外部字体放入unity仓库以后呢,需要把这个字体转成用立体的字体文件才可以被使用! 要想转换的话呢先放入仓库对字体点右键上面有一个Create创建里面有一个TEXT Asset,创建好就可以使用了...
云积万相,焕发电商店铺新活力
数字化时代,电商店铺的运营和营销策略越来越受到重视。如何让店铺在众多的竞争中脱颖而出,吸引更多的顾客,提高销售额,是每个电商品牌都需要思考的问题。云积天赫最近推出的云积万相为电商店铺带来全新的活力和更多的可能性。 …...
字典管理怎么使用,vue3项目使用若依的的字典管理模块
若依框架数据字典的使用_若依数据字典_哈哈水水水水的博客-CSDN博客 【精选】关于数据字典的理解与设计_数据字典怎么设计-CSDN博客 若依的字典值如何使用(超详细图文教程)_若依字典管理_丿BAIKAL巛的博客-CSDN博客 Vue3组合式API:getCurr…...
【汇编】内存中字的存储、用DS和[address]实现字的传送、DS与数据段
文章目录 前言一、内存中字的存储1.1 8086cpu字的概念1.2 16位的字存储在一个16位的寄存器中,如何存储?1.3 字单元 二、用DS和[address]实现字的传送2.1 字的传送是什么意思?2.2 要求原理解决方案:DS和[address]配合8086传送16字节…...
数据分析 - 分散性与变异的量度
全距 - 极差 处理变异性 方差度量 数值与均值的距离,也就是数据的差异性 标准差描述:典型值 和 均值的距离的方法,数据与均值的分散情况...
Neo4j数据库介绍及简单使用
图数据库介绍 图数据库是一种专门设计用于存储和管理图形数据的数据库类型。在图数据库中,数据以图的形式表示,其中节点表示实体,边表示实体之间的关系。这种表示方式非常适合处理具有复杂关系的数据,如社交网络、推荐系统、网络…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
