Skip to content
GHSA 8phf V3xj 8jjg

GHSA 8phf V3xj 8jjg

github.com • October 9, 2026

PlantAttachmentModel accepts plant attachment uploads and saves the file using the client-supplied file extension verbatim, with no allowlist, no blocklist, no MIME check, and no magic-byte validation. Uploaded files land directly in public/attachments/ which is web-accessible. An attacker can upload a .php webshell and request it to achieve remote code execution. A mod_rewrite rule in public/.htaccess blocks common PHP extensions on Apache, but is ineffective on nginx, Docker, IIS, or any deployment where AllowOverride is disabled.

Technical detail (verified in source, current main)

app/models/PlantAttachmentModel.php:28-31 :

Extension sourced entirely from $_FILES['attachment']['name'] (client-controlled). No allowlist, blocklist, MIME check, or magic-byte validation.

Web accessibility: public/attachments/ is web-accessible (root .htaccess rewrites ^((?!public/).*)$ -> public/$1 ). No .htaccess in public/attachments/ itself.

Partial mitigation (Apache-only):

public/.htaccess:9-11 : RewriteRule \.(php[34578]?|phtml|phar|pht)$ - [F,L] blocks common PHP variants.

This rule is mod_rewrite -dependent; it has no effect on nginx, IIS, or Apache with AllowOverride None .

The shipped dockerfile / docker-compose.yml use a base image that defaults to a non-Apache server, bypassing this mitigation entirely on containerized deployments.

The pattern does not cover .PHP (uppercase), .php9 , .php (trailing space), .php::$DATA (Windows NTFS), .cgi , .py , .pl , or other server-side extension types.

Web session route /plants/attachments/add requires UserModel::getAuthUser() (any authenticated web user).

API route /api/plants/attachments/add requires API token.

An authenticated web user uploads shell.php (or shell.PHP , or any server-side script). On nginx, IIS, or Docker deployments (where .htaccess is not parsed), requesting the URL executes the PHP webshell with the web server process's permissions, achieving full RCE. On Apache with .htaccess enforced, PHP execution is blocked, but non-PHP server-side scripts and polyglots remain uploadable depending on server configuration.

Proof of concept (benign)

Replace the extension-from-filename approach with a strict allowlist in PlantAttachmentModel.php :

Additionally: verify MIME type against magic bytes using finfo_file() , serve attachments via a PHP controller (not direct webroot access), and add a per-directory .htaccess to public/attachments/ that denies all script execution as defense in depth.

No existing CVE or GHSA for danielbrendel/hortusfox-web file upload. Distinct from the SQL injection finding (separate attack class, separate file). Novel.

Reported privately via GitHub Private Vulnerability Reporting by @hackchang . Please coordinate a fix under a 90-day window and publish + request a CVE when the fix ships; happy to re-test.

Extracted Entities

Attack Types (1)

MITRE ATT&CK (1)

Platforms (2)

Tools (2)