# File Upload(RCE) Vulnerability in admidio

Admidio's UploadHandlerFile skips extension validation when CSRF token is invalid, letting any upload-permitted user drop a PHP webshell and get RCE.

- Payout: Research
- Severity: high
- Program: Admidio
- Found by: arrester
- Disclosed: 2026-03-16
- CVE: CVE-2026-32756
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-95cq-p4w2-32w5
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-95cq-p4w2-32w5
- Tags: area:web domain:web impact:integrity impact:rce kind:research platform:ghsa sev:high tech:php technique:source-review vuln:csrf vuln:file-upload vuln:rce

**Target:** Documents & Files upload endpoint /system/file_upload.php
**Root cause:** handle_form_data() sets $file->error on CSRF failure but does not terminate the request; handle_file_upload() writes the file to disk via the parent class, then only runs allowedFileExtension() and cleanup inside `if (!isset($file->error))`, so a CSRF error skips the extension check and deletion.
**Steps:**
1. Log in as a user with upload rights on Documents & Files and open a folder.
2. Intercept the upload POST to `/system/file_upload.php?module=documents_files&mode=upload_files&uuid=<folder_uuid>`.
3. Replace `adm_csrf_token` with an arbitrary invalid string (e.g. `webshellgogo`).
4. Set the uploaded file to a PHP webshell, e.g. `<?php system($_GET[1]); ?>`.
5. Forward the request; server returns 200 with `"error":"Invalid or missing CSRF token!"` but the file persists at the `url` in the response.
6. Request the returned URL to execute commands.
**How found:** Code review of UploadHandlerFile.php noticing the extension check and deleteFileIfExists cleanup are gated behind `if (!isset($file->error))` while the parent class already wrote the file to disk, then testing a forced CSRF failure to skip that branch.
**Exploitation:** Authenticated upload-permitted user submits a PHP webshell with a deliberately invalid CSRF token; the file is written to disk before validation, extension check and cleanup are skipped due to the error flag, and the returned URL serves the script for arbitrary command execution.
**Insight:** When a handler writes to disk before validation and gates cleanup on an error flag, look for any earlier check (CSRF, size, MIME) that sets that flag without terminating the request — deliberately failing it can skip the dangerous-file cleanup.

