Node.js中的不安全跳转如何防御详解


Posted in Javascript onOctober 21, 2018

导语:

早年在浏览器大战期间,有远见的Chrome认为要运行现代Web应用,浏览器必须有一个性能非常强劲的Java引擎,于是Google自己开发了一个高性能的开源的Java引擎,名字叫V8。在2009年,Ryan正式推出了基于Java语言和V8引擎的开源Web服务器项目,命名为Node.js。

对于任何web开发人员来说,不安全或未经验证的重定向都是重要的安全考虑因素。Express为重定向提供了本地支持,使它们易于实现和使用。Express是一种保持最低程度规模的灵活Node.js Web应用程序框架,为Web和移动应用程序提供一组强大的

什么是不安全的重定向?

对于任何web开发人员来说,不安全或未经验证的重定向都是重要的安全考虑因素。Express为重定向提供了本地支持,使它们易于实现和使用。然而,Express将执行输入验证的工作留给了开发人员。Express是一种保持最低程度规模的灵活Node.js Web应用程序框架,为Web和移动应用程序提供一组强大的功能。

下面是OWASP.org网站给出的“未经验证的重定向和转发”的定义:

如果web应用程序接受不可信的输入,可能导致web应用程序将请求重定向到不可信输入中包含的URL,则可以进行未经验证的重定向和转发。

重定向通常在登录和身份验证过程中使用,因此可以在登录之前将用户重定向到他们所在的页面。但根据业务需求或应用程序类型而有所不同,也存在其他重定向情况。

为什么要避免重定向?

不验证用户输入的重定向,可以使攻击者具备发起网络钓鱼诈骗的条件,从而窃取用户凭据并执行其他恶意操作。

注意:当在Node.js或Express中实现重定向时,在服务器端执行输入验证很重要。

如果攻击者发现用户没有验证外部用户提供的输入,他们可能会利用这个漏洞在论坛、社交媒体和其他公共场所发布专门设计的链接,让用户点击它。

从表面上看,这些URL看起来合法且对用户来说并无威胁,这是因为所有这些要重定向的URL都包含目标的主机名:

https://example.com/login?url=http://examp1e.com/bad/things

但是,如果服务器端重定向逻辑未验证输入url参数的数据,则用户可能最终会访问黑客所提前设置的网站(examp1e.com),满足攻击的需求!以上只是攻击者如何利用不安全重定向逻辑的一个例子。

不安全重定向例子并将其直接传递到Express res.redirect()方法中。因此,只要用户通过身份验证,Express就会将用户重定向到输入或提供的URL。

var express = require('express');
var port = process.env.PORT || 3000;
var app = express();

app.get('/login', function (req, res, next) {

 if(req.session.isAuthenticated()) {

 res.redirect(req.query.url);
 }
});

app.get('/account', function (req, res, next) {
 res.send('Account page');
});

app.get('/profile', function (req, res, next) {
 res.send('Profile page');
});

app.listen(port, function() {
 console.log('Server listening on port ' + port);
});

输入验证有助于防止不安全的重定向

通常,最好避免在代码中使用重定向和转发。如果你一定需要在代码中使用重定向,则首选的方法是使用映射到特定目标的预定义输入,这被称为白名单方法。以下就是实现这种方法的一个具体样本步骤:

1.baseHostname会确保任何重定向都将用户保留在研究人员的主机上;

2.redirectMapping是一个对象,它将预定义的输入(例如,传递给url paramer的内容)映射到服务器上的特定路径;

3.validateRedirect()方法会判断预定义的输入是否存在,如果它们存在,则返回要重定向的适当路径;

4.研究人员修改了/login逻辑,然后将baseHostname+redirectPath变量连接在一起,这就避免了任何用户提供的输入内容直接传递到Express res.redirect()方法中;

5.最后,研究人员使用encodeURI()方法作为额外的安全保证,确保连接字符串的URI部分被正确编码,以允许干净的重定向。

//Configure your whitelist
var baseHostname = "https://example.com";
var redirectMapping = {
 'account': '/account',
 'profile': '/profile'
}

//Create a function to validate whitelist
function validateRedirect(key) {
 if(key in redirectMapping) {

  return redirectMapping[key];
 }else{

  return false;
 }
}

app.get('/login', function (req, res, next) {
 if(req.session.isAuthenticated()) {
 redirectPath = validateRedirect(req.query.url);

 if(redirectPath) {
 res.redirect(encodeURI(baseHostname + redirectPath));
 }else{
 res.send('Not a valid redirect!');
 }
 }
});

其他重定向场景

在某些情况下,将每个组合列入白名单是不切实际的,不过有些安全平台仍然希望重定向用户并将其保留在域内某些边界内。当外部提供的值遵循特定模式(例如16个字符的字母数字字符串)时,最好这样做。字母数字字符串是理想的,因为它们不包含任何可能引入其他攻击的特殊字符,例如目录/路径遍历(依赖于诸如…和向后/向前斜杠之类的字符)。

例如,安全平台可能希望在用户登录后将其重定向回电子商务网站上的特定产品。由于电子商务网站对每种产品都有唯一的字母数字值,因此安全平台可以通过始终根据RegEx白名单验证外部输入来实现安全重定向。在本文所讲的样本在,研究者用的是productId变量。

//Configure your whitelist
var baseHostname = "https://example.com";

app.get('/login', function (req, res, next) {
 productId = (req.query.productId || '');
 whitelistRegEx = /^[a-zA-Z0-9]{16}$/;

 if(productId) {
  
  //Validate the productId is alphanumeric and exactly 16 characters
  if(whitelistRegEx.test(productId)) {

   res.redirect(encodeURI(baseHostname + '/item/' + productId));
  }else{

   //The productId did not meet the RegEx whitelist, so return an error
   res.send('Invalid product ID');
  }
 }else{
 
  //No productId was provided, so redirect to home page
  res.redirect('/');
 }
});

最后,安全平台发出警告,警告用户他们正在被自动重定向是值得重视的。如果安全平台有意将用户重定向到域外,则可能需要在流程中创建一个中间页面,该页面会发出如下警告,并包含用户要重定向到的URL。

Node.js中的不安全跳转如何防御详解

注:本文是以Hailstone为例进行讲解的,Hailstone是一个应用程序安全平台,它有查找代码中的漏洞功能。

本文翻译自:https://blog.hailstone.io/how-to-prevent-unsafe-redirects-in-node-js

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
Javascript 获取链接(url)参数的方法
Feb 15 Javascript
jquery 结合C#后台的数组对文章的关键字自动添加链接的代码
Jul 15 Javascript
javascript基础知识大全 便于大家学习,也便于我自己查看
Aug 17 Javascript
Jquery 获取指定标签的对象及属性的设置与移除
May 29 Javascript
信息页文内画中画广告js实现代码(文中加载广告方式)
Jan 03 Javascript
js实现右键自定义菜单
Dec 03 Javascript
新手vue构建单页面应用实例代码
Sep 18 Javascript
js中apply()和call()的区别与用法实例分析
Aug 14 Javascript
vue鼠标移入添加class样式,鼠标移出去除样式(active)实现方法
Aug 22 Javascript
深入解析Vue源码实例挂载与编译流程实现思路详解
May 05 Javascript
JavaScript实现单英文金山打字通
Jul 24 Javascript
VUE 实现动态给对象增加属性,并触发视图更新操作示例
Nov 29 Javascript
详解Axios 如何取消已发送的请求
Oct 20 #Javascript
使用Vue做一个简单的todo应用的三种方式的示例代码
Oct 20 #Javascript
Iview Table组件中各种组件扩展的使用
Oct 20 #Javascript
详解webpack打包第三方类库的正确姿势
Oct 20 #Javascript
详解ES6 Promise对象then方法链式调用
Oct 20 #Javascript
Intellij IDEA搭建vue-cli项目的方法步骤
Oct 20 #Javascript
分享5个小技巧让你写出更好的 JavaScript 条件语句
Oct 20 #Javascript
You might like
php获取当前时间的毫秒数的方法
2014/01/26 PHP
window.js 主要包含了页面的一些操作
2009/12/23 Javascript
window.onbeforeunload方法在IE下无法正常工作的解决办法
2010/01/23 Javascript
Javascript的一种模块模式
2010/09/08 Javascript
用js来定义浏览器中一个左右浮动元素相对于页面主体宽度的位置的函数
2012/01/21 Javascript
使用CSS样式position:fixed水平滚动的方法
2014/02/19 Javascript
jquery移除、绑定、触发元素事件使用示例详解
2014/04/10 Javascript
jQuery 删除/替换DOM元素的几种方式
2014/05/20 Javascript
使用jquery实现的一个图片延迟加载插件(含图片延迟加载原理)
2014/06/05 Javascript
ES6中的数组扩展方法
2016/08/26 Javascript
Vuejs第六篇之Vuejs与form元素实例解析
2016/09/05 Javascript
javascript将扁平的数据转为树形结构的高效率算法
2020/02/27 Javascript
[02:51]2014DOTA2国际邀请赛 IG战队官方纪录片
2014/07/21 DOTA
举例讲解Python中metaclass元类的创建与使用
2016/06/30 Python
Python基于正则表达式实现文件内容替换的方法
2017/08/30 Python
使用Python的Django和layim实现即时通讯的方法
2018/05/25 Python
Python SVM(支持向量机)实现方法完整示例
2018/06/19 Python
Python Django Cookie 简单用法解析
2019/08/13 Python
Python安装及Pycharm安装使用教程图解
2019/09/20 Python
python重要函数eval多种用法解析
2020/01/14 Python
Pytorch中的自动求梯度机制和Variable类实例
2020/02/29 Python
使用Matplotlib绘制不同颜色的带箭头的线实例
2020/04/17 Python
python转化excel数字日期为标准日期操作
2020/07/14 Python
python 实现ping测试延迟的两种方法
2020/12/10 Python
Html5大文件断点续传实现方法
2015/12/05 HTML / CSS
澳大利亚吉他在线:Artist Guitars
2017/03/30 全球购物
哥伦比亚加拿大官网:Columbia Sportswear Canada
2020/09/07 全球购物
师范教师专业大学生职业生涯规划范文
2014/03/02 职场文书
金融学专业大学生职业生涯规划
2014/03/07 职场文书
务虚会发言材料
2014/12/25 职场文书
学生会辞职信
2015/03/02 职场文书
个性与发展自我评价
2015/03/06 职场文书
酒店人事专员岗位职责
2015/04/07 职场文书
2015年创先争优工作总结
2015/05/23 职场文书
导游词之沈阳植物园
2019/11/30 职场文书
解决Git推送错误non-fast-forward的方法
2022/06/25 Servers