会话管理安全:保护用户会话的最佳实践
#javascript #opensourcesecurity #codesecurity

会话管理安全性是Web应用程序开发的重要组成部分。它可以保护用户会议并防止未经授权的访问。管理会议确保敏感用户数据的机密性,完整性和可用性。它还保护大型用户隐私,这对于维持用户对应用程序的信任至关重要。

当我们安全地管理会话时,我们会在用户注销或他们的会话结束时建立流程以销毁会话令牌。这种方法可以防止窃听连接网络或想模仿它的任何人未经授权的访问。

在这篇动手的文章中,我们将审查如何实施安全的会话管理和这样做的最佳实践。

了解会话管理安全

要了解会话管理在域级别上的重要性,我们将开发一个简单的node.js应用程序,该应用程序实现了基本的登录,注销和会话管理功能。

先决条件

要跟随本教程,您需要:

请注意,此演示使用Windows操作系统及其相关命令。

有关完整项目的概述,请查看complete code

在node.js中实现会话

开始,转到您的命令提示符(CMD),然后使用以下代码创建一个名为sessions的文件夹,更改为其,然后初始化应用程序:

mkdir session 
cd sessions
npm init -y

运行上方自动生成的命令,该命令保存了项目中安装的所有依赖项。

接下来,我们需要安装一些软件包,以实现执行范围的目标。这些软件包是express,这是一个用于创建Web服务器的框架,而express-session是一个服务器端HTTP框架创建会话中间件所需的服务器端HTTP框架。使用下面的代码安装两个软件包:

npm i express express-session

现在,在Visual Studio代码中打开项目。

要保留我们的应用程序逻辑,我们需要创建一个index.js文件。在您的CMD中,使用touch index.js命令创建一个index.js文件。然后,使用以下代码更新index.js文件:

const express = require('express'); 
const session = require('express-session');

const  app = express();
const port = 3001;

// Session Middlewares, and Login and Logout Routes go here
app.use(session({
  secret: '38sisjsk92',
  resave: false,
  saveUninitialized: true
}));

// URL-encoded middleware
app.use(express.urlencoded({ extended: true }));

app.listen(port, () => {
  console.log(`Server listening on port ${port}`);
});

上面的代码片段包含node.js应用程序的启动代码。它在我们项目的正文中设置了session middleware for the Express app

URL编码的中间件负责在任何Express.js应用程序中对URL编码的表单数据的传入请求。

接下来,在index.js文件中的中间Wares下方添加以下代码,以处理会话中用户的登录和注销功能:

// Routes
app.get('/', (req, res) => {
  if (req.session.username) {
    res.send(`Welcome to the page, ${req.session.username}! [Logout](/logout)`);
  } else {
    res.send('Welcome, Please [login](/login).');
  }
  console.log(req.session)
});

app.get('/login', (req, res) => {
  if (req.session.username) {
    res.redirect('/');
  } else {
    res.send(`









 Login

    `);
  }
});

// validate your username and password here
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  req.session.username = username;
  req.password = password;
  res.redirect('/');
});

app.get('/logout', (req, res) => {
  req.session.destroy();
  res.redirect('/');
});

在我们继续之前,让我们快速查看上述代码中发生的事情:

  • 第一个路线app.get('/')处理了应用程序的根URL的请求。它欢迎在会话中存储用户名的用户,并为他们提供了注销的链接。否则,它提示用户登录。
  • 第二个路线app.get('/login')处理登录URL的请求。
  • 第三个路线app.post('/login')处理登录表单提交。
  • 第四条路线app.get('/logout')GET的请求处理到注销URL。它破坏了用户的会话并将其重定向到根网址。

保存所有更改,然后转到您的终端并使用此命令执行应用程序:

node index.js

由于我们收听端口3001,因此在浏览器中打开http://localhost:3001/。当您导航到URL时,您会看到此简单的登录链接:


单击登录链接并输入您的名称。这将带您进入以下着陆页:


现在,去检查终端。您会看到看起来像这样的会话对象:


第一个属性是路径。它代表了会话cookie的有效路径。接下来,是一个会话到期的时间,cookie弹出何时的持续时间以及设置为truehttpOnly属性,以防止任何客户端攻击,例如cross-site scripting (XSS)。会话对象还显示当前用户名。

会话管理及其在Web应用程序中的作用

现在,我们准备了一个示例申请,让我们回顾一下会话管理的工作方式,以及为什么对会话安全管理如此关键。

在Web应用程序中,用户与应用程序之间的交互通常包含敏感信息 - 此处是密码。会话管理确保这些交互对于身份验证的用户是安全的,并且会话期间提供的信息始终是安全的。不这样做可能会导致会话管理漏洞。

一些常见的漏洞包括:

  • 会话劫持劫持劫持,当攻击者通过窃取或预测其代表其所有者而窃取或预测其未经授权的访问服务器时,就会发生会话令牌。攻击者可以通过几种方式实现这一目标。一种方法是使用XSS。如果Web应用程序访问用户的httponly属性设置为false,则通过客户端劫持的会话劫持程度非常高,为XSS攻击创建了一个开口。
  • Man-in-the-middle (MITM) 攻击这些攻击是劫机的另一种类型。恶意演员可以在用户和服务器通信时拦截会话ID来访问会话。这是会话ID为纯文本的时候,可以在数据频道中的拦截器轻松读取。
  • fixation “固定”发生在攻击者欺骗用户使用已有的会话ID通过劫持有效的用户会话来访问服务器的情况。它主要发生在使用会话ID正确验证会话的用户时。当攻击者在URL中向受害人发送脆弱的会话ID时,也可能发生。

与不安全的会话管理流程相关的风险可能很大。使用获得的敏感数据,不良的参与者可以实施欺诈,盗窃并获得对特权信息的访问。这些安全漏洞对用户极为有害,并且可能对他们对应用程序的信任有害。

幸运的是,我们可以实施几种策略来确保我们的会话管理流程。以下各节强调了这样做的一些方法,并演示了如何实施它们。

实施安全的cookie

使用cookie可以安全地管理会话。在会话管理中,Cookie可以将用户链接到服务器端上的会话对象。借助其唯一的标识符,cookie包含了他们访问的实例中所有用户相关的活动。

例如,当用户访问应用程序登录时,此操作会创建一个会话对象并为会话ID分配。 Cookie存储会话ID并将其发送到浏览器作为响应。当用户提出请求时,浏览器会发送cookie,该cookie验证会话ID并检索与之相关的对象。这意味着服务器可以验证用户并通过不同的页面和不同的请求维护其会话。

考虑到这一点,系统开发人员,应用程序架构师和管理员应确保使用cookie尽可能安全。

保护cookie的一种方法是使用安全标志,这需要仅通过HTTPS允许请求。它可以保护网络中的用户免受数据路径中的MITM的侵害,因为发送的数据包在明文中是不可读的。

除了MITM攻击外,Cookie还容易受到XSS攻击的影响,因为它们通过网络传输数据包。我们可以使用HttpOnly flag,该HttpOnly flag阻止JavaScript阅读会话cookie,以防止这些攻击。

要实现此标志,我们需要检查会话的HttpOnly会话对象是否分配给了一个布尔。

使用以下命令:

npm i cookie-parser bcrypt@v4.0.1

然后,在index.js文件中,如下更新代码:

const cookieParser = require('cookie-parser');

// Enable cookie parsing
app.use(cookieParser());

// Set up session middleware
app.use(session({
  secret: '38sisjsk92',
  resave: false,
  saveUninitialized: true,
  cookie: {
    httpOnly: true, 
    secure: false, // Sent only over HTTPS if true
  },   
}));

要查看Visual Studio代码中代码中检测到的漏洞,您必须确保在帐户上启用SNYK代码。您可以通过Visual Studio代码扩展或Synk网站进行操作。如果您在问题选项卡上仔细观察视觉工作室代码终端,则会发现Snyk突出了该代码中的几个漏洞:


扫描显示您的代码中有一个硬编码的秘密,禁用cross-site request forgery (CSRF),一个残疾人的安全标志和一个脆弱的软件包。

Snyk建议通过遵循所提供的提示来调解这些问题的几种方法。让我们解决其中的几个问题。

首先,Snyk建议使用环境变量避免硬编码。要实现此更改,请转到您的终端并执行以下命令:

npm i dotenv
touch .env

第一个命令安装了用于读取设定环境变量的dotenv软件包,第二个命令创建了一个用于存储此类敏感信息的环境文件。

现在,将此配置添加到.env文件:

SESSION_SECRET=38sisjsk92

然后,在index.js中,文件使用此代码更新会话中间软件:

require('dotenv').config(); // loads env variables 
app.use(session({
  secret: process.env.SESSION_SECRET,
}));

这些更新确保将从环境变量中读取秘密。

接下来,将安全标志转到true

由于启用CSRF会为我们的应用程序添加相当多的其他代码,因此我们将忽略它。但是请记住使用csrf package在您自己的应用中解决此问题。

要解决脆弱的软件包问题,请访问官方的npm documentation并安装更新版本或经过测试的secure bcryptjs package

一旦Snyk扩展程序在这些更新后扫描了您的应用程序,您会注意到大多数错误现在已经消失了。如果您目前正在运行该应用程序,则如果使用HTTPS,Localhost将无法正常工作,并且它将不断将您重定向到根URL。

除了将本地存储用于客户端 - 重点存储之外,您可以将应用程序会话数据存储在数据库中。数据库允许您启动基于唯一的会话ID坚持会话数据的服务器重新启动,从而使用户易于登录而无需每次输入其凭据。另外,您可以使用内存库,例如Redis

实施会话超时

会话超时会在用户的会话大赛中,自动将其记录在系统中时。这限制了会话攻击的窗口,并确保在特定时期后销毁会话。

设置会话超时持续时间时有几个因素:

  • 应用程序的类型确定适合您应用程序的数据的会话时间长度。
  • 用户行为确保用户不会受到超时的影响。

我们在会话中间软件中实现了会话超时。使用下面的摘要更新代码,将会话超时设置为一个小时:

// Set up session middleware
app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: true,
  cookie: {
    maxAge: 3600000, // Expires after 1 hour (in milliseconds)
    httpOnly: true, // Accessible only via HTTP(S)
    secure: false, // Sent only over HTTPS
  },   
}));

实施正确的注销功能

注销功能可确保用户在与应用程序进行交互时可以明确结束会话。实施注销功能使用户负责终止其cookie会话,从而使他们对安全感有所所有权。

但是,注销功能仍然需要开发人员的注意。当用户启动注销时,客户端会话可能会终止。但是在服务器端,会话cookie可能还没有完全无效。模仿者可以使用这些会话令牌并执行操作,就好像他们是原始用户一样。

为了防止此安全漏洞,我们必须确保用户的会话令牌和会话ID在服务器端被破坏。使用以下代码作为index.js文件中的最后一个路由在应用程序中实现此功能:

app.get('/logout', (req, res) => {
  req.session.destroy(err => {
    if (err) {
      console.log(err)
    } else {
      res.clearCookie('connect.sid');
      res.redirect('/');
    }
  });
});

此代码带有回调函数调用destroy(),以在用户注销时在服务器端删除会话。它还称为clearCookie()并删除connection.sid,这是分配给已登录的用户值的密钥。

如果您通过Inspect选项检查浏览器中登录用户的cookie,则应看到一个connection.sid,如下所示:


通过实施上述步骤,我们可以确保系统用户可以在不担心其在线安全性的情况下注销。 SNYK代码扩展程序使您可以查看我们项目中完成的所有漏洞扫描,为每个漏洞提供状态,帮助我们确保应用程序在向用户提供之前没有曝光。

在本文中,我们使用Snyk扫描我们的项目,这使我们能够查看如何解决诸如硬编码秘密,与会话相关的问题以及使用脆弱软件包等脆弱性问题。现在,我们减轻了Snyk标记的漏洞,我们的系统没有任何内容,如下所示:

安全会议管理的其他最佳实践

除了我们在本文中所审查的过程外,这里还有一些最佳的实践,可以更安全地管理课程:

  • 使用安全的会话标识符 - 安全的会话标识符是用于身份验证用户会话的一系列独特字符串。我们可以自动生成这些标识符。随机性和不可预测性使细致的攻击者即使使用统计分析技术也很难猜测,并且弦长的长度足以抵抗蛮力攻击。
  • 使用服务器端会话管理 在客户端捕获会话标识符,尽管是独特生成的,但仍会导致漏洞。我们可以使用服务器端会话管理来存储这些会话标识符,并将它们与应用程序中的用户匹配。使用此会话存储类型,敏感的用户凭据更安全,用户可以自由使用该系统而不必担心被模仿。
  • 正确验证注销 <当用户登录到一个实例时,登录了,系统应在用户访问的所有实例上正确地将注销无效。在不同步整个实例中的会话数据的情况下实现这一目标可能很复杂。尽管如此,必须这样做,因为实例可以成为模仿者窃取用户信息的切入点。

结论

在本文中,我们探讨了几种提高会话管理安全性的策略,以最大程度地提高访问者安全性并最大程度地减少攻击次数。安全的会话管理确保尽管用户可能会留下的个人跟踪,但个人信息,数据和帐户仍然安全。

它还可以在用户与我们的网站和Web应用程序进行交互时保护他们。通过实施此处概述的最佳实践和安全策略,我们可以帮助我们的用户确信他们的证书和机密信息是安全的。