AdonisJS任意文件写(CVE-2026-21440)漏洞复现

admin 2026-01-14 23:13:05 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文复现了AdonisJSbodyparser组件v10.1.2以下版本的任意文件写入漏洞CVE-2026-21440。漏洞因MultipartFile类直接使用用户可控文件名拼接路径导致,允许攻击者利用路径穿越覆盖任意文件。建议受影响用户立即升级至v10.1.2或更高版本以消除风险。 综合评分: 84 文章分类: 漏洞分析,WEB安全,漏洞POC


cover_image

AdonisJS 任意文件写(CVE-2026-21440) 漏洞复现

船山信安

2026年1月14日 17:00 湖南

组件简介

AdonisJS 是一个功能完善的 Node.js 后端框架。该框架从零开始构建,重点强调开发者体验和易用性。

它是 Node.js 社区中较为少见的框架之一,内置了一整套官方的一方(first-party)功能包,帮助开发者在无需花费数百小时拼装各种 npm 包的情况下,就能完成产品的开发与交付。

影响版本

bodyparser < v10.1.2

环境搭建

GPT 梭一个简单的 web

app.js

import express from 'express'
import { MultipartFile } from '@adonisjs/bodyparser'
import { Form } from '@poppinss/multiparty'

const app = express()

app.get('/', (req, res) => {
&nbsp; res.send(`
&nbsp; &nbsp; <!DOCTYPE html>
&nbsp; &nbsp; <html>
&nbsp; &nbsp; <head>
&nbsp; &nbsp; &nbsp; <title>File Upload</title>
&nbsp; &nbsp; &nbsp; <style>
&nbsp; &nbsp; &nbsp; &nbsp; body { font-family: Arial; max-width: 600px; margin: 50px auto; padding: 20px; }
&nbsp; &nbsp; &nbsp; &nbsp; form { border: 2px dashed&nbsp;#ccc; padding: 30px; text-align: center; }
&nbsp; &nbsp; &nbsp; &nbsp; input[type="file"] { margin: 20px 0; }
&nbsp; &nbsp; &nbsp; &nbsp; button { background:&nbsp;#007bff; color: white; border: none; padding: 10px 20px; cursor: pointer; }
&nbsp; &nbsp; &nbsp; &nbsp; button:hover { background:&nbsp;#0056b3; }
&nbsp; &nbsp; &nbsp; </style>
&nbsp; &nbsp; </head>
&nbsp; &nbsp; <body>
&nbsp; &nbsp; &nbsp; <h1>File Upload</h1>
&nbsp; &nbsp; &nbsp; <form action="/upload" method="POST" enctype="multipart/form-data">
&nbsp; &nbsp; &nbsp; &nbsp; <input type="file" name="file" required>
&nbsp; &nbsp; &nbsp; &nbsp; <br>
&nbsp; &nbsp; &nbsp; &nbsp; <button type="submit">Upload</button>
&nbsp; &nbsp; &nbsp; </form>
&nbsp; &nbsp; </body>
&nbsp; &nbsp; </html>
&nbsp; `)
})

app.post('/upload', (req, res) => {
&nbsp; const form = new Form()

&nbsp; form.parse(req, (err, fields, files) => {
&nbsp; &nbsp; if (err) {
&nbsp; &nbsp; &nbsp; return res.status(400).json({ error: err.message })
&nbsp; &nbsp; }

&nbsp; &nbsp; const uploadedFile = files.file?.[0]
&nbsp; &nbsp; if (!uploadedFile) {
&nbsp; &nbsp; &nbsp; return res.status(400).json({ error: 'No file uploaded' })
&nbsp; &nbsp; }

&nbsp; &nbsp; const file = new MultipartFile({
&nbsp; &nbsp; &nbsp; fieldName: 'file',
&nbsp; &nbsp; &nbsp; clientName: uploadedFile.originalFilename,
&nbsp; &nbsp; &nbsp; headers: uploadedFile.headers,
&nbsp; &nbsp; }, {})

&nbsp; &nbsp; file.tmpPath = uploadedFile.path
&nbsp; &nbsp; file.size = uploadedFile.size

&nbsp; &nbsp; file.move('./uploads').then(() => {
&nbsp; &nbsp; &nbsp; res.json({
&nbsp; &nbsp; &nbsp; &nbsp; success: true,
&nbsp; &nbsp; &nbsp; &nbsp; filename: file.fileName,
&nbsp; &nbsp; &nbsp; &nbsp; size: file.size
&nbsp; &nbsp; &nbsp; })
&nbsp; &nbsp; }).catch(err => {
&nbsp; &nbsp; &nbsp; res.status(500).json({ error: err.message })
&nbsp; &nbsp; })
&nbsp; })
})

app.listen(3333, () => {
&nbsp; console.log('Server running on http://localhost:3333')
})

package.json

{
&nbsp; "name": "file-upload-service",
&nbsp; "version": "1.0.0",
&nbsp; "type": "module",
&nbsp; "scripts": {
&nbsp; &nbsp; "dev": "node app.js"
&nbsp; },
&nbsp; "dependencies": {
&nbsp; &nbsp; "@adonisjs/bodyparser": "10.1.1",
&nbsp; &nbsp; "@poppinss/multiparty": "^2.0.0",
&nbsp; &nbsp; "express": "^4.18.0"
&nbsp; }
}

分析过程

body_parser.spec.ts

overwrite 默认为 true name 则使用用户上传的文件名

然后使用 path.join 进行拼接  path.join 无限制 直接拼接

这里就是漏洞成因

修复方案

高版本不再使用用户提供的参数作为参数


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:船山信安 《AdonisJS 任意文件写(CVE-2026-21440) 漏洞复现》

评论:0   参与:  0