Node.js CVE-2017-14849 漏洞分析

  • A+
所属分类:网络安全

1. 漏洞简介

2017年9月28日,公司扫描器发现某业务存在一例任意文件读取漏洞,团队跟进分析后发现这是Node.js和Express共同导致的一个通用漏洞。在我们准备告知官方时,发现Node.js官网于9月29号给出了漏洞公告,对应的CVE编号为CVE-2017-14849。

1.1 关于Node.js

Node.js是一个Javascript运行环境(runtime),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。Node.js对一些特殊用例进行优化,提供替代的API,使得V8在非浏览器环境下运行得更好。

1.2 关于Express

Express 是一个简洁而灵活的 node.js Web应用框架, 提供一系列强大特性帮助你创建各种Web应用。Express 不对 node.js 已有的特性进行二次抽象,我们只是在它之上扩展了Web应用所需的功能。丰富的HTTP工具以及来自Connect框架的中间件随取随用,创建强健、友好的API变得快速又简单。

1.3 漏洞影响

Node.js 8.5.0 + Express 3.19.0-3.21.2
Node.js 8.5.0 + Express 4.11.0-4.15.5

2. 漏洞演示

1.安装Node.js 8.5.0
2.下载并解压express-4.15.5.zip
3.expresss-4.15.5目录下执行npm install
4.expresss-4.15.5/examples/static-files目录里执行nodejs index.js
5.使用POC测试(web监听了5678端口,默认3000)如下图

Node.js CVE-2017-14849 漏洞分析

3. 漏洞分析

Express依赖Send组件,Send组件0.11.0-0.15.6版本pipe()函数中,如图:

Node.js CVE-2017-14849 漏洞分析

Send模块通过normalize('.' + sep + path)标准化路径path后,并没有赋值给path,而是仅仅判断了下是否存在目录跳转字符。如果我们能绕过目录跳转字符的判断,就能把目录跳转字符带入545行的join(root, path)函数中,跳转到我们想要跳转到的目录中,这是Send模块的一个bug,目前已经修复。

再来看Node.js,Node.js 8.5.0对path.js文件中的normalizeStringPosix函数进行了修改,使其能够对路径做到如下的标准化:

assert.strictEqual(path.posix.normalize('bar/foo../..'), 'bar');

新的修改带来了问题,通过单步调试我们发现,可以通过foo../../和目录跳转字符一起注入到路径中,foo../../可以把变量isAboveRoot设置为false(代码161行),并且在代码135行把自己删掉;变量isAboveRootfalse的情况下,可以在foo../../两边设置同样数量的跳转字符,让他们同样在代码135行把自己删除,这样就可以构造出一个带有跳转字符,但是通过normalizeStringPosix函数标准化后又会全部自动移除的payload,这个payload配合上面提到的Send模块bug就能够成功的返回一个我们想要的物理路径,最后在Send模块中读取并返回文件。normalizeStringPosix函数如下图:

Node.js CVE-2017-14849 漏洞分析
Node.js CVE-2017-14849 漏洞分析

4. 参考连接

  1. https://nodejs.org/en/blog/vulnerability/september-2017-path-validation/

  2. https://github.com/nodejs/node/commit/b98e8d995efb426bbdee56ce503017bdcbbc6332#diff-c0fae59301ef49fb71b43278db9ad881

  3. https://github.com/nodejs/node/commit/cfee1c977867defa2866eebb23a9fabec4003f52#diff-c0fae59301ef49fb71b43278db9ad881

  4. https://github.com/pillarjs/send/commit/a472ed304701ef2c091ce4dddb89bdddfccc98da#diff-168726dbe96b3ce427e7fedce31bb0bc

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: