Skip to content

unrestricted file upload, and PHP execution from public upload path #158

@Lsra1n

Description

@Lsra1n

Problem

The upload flow accepts extraData.uploadDir and only performs a very weak path safety check based on ... It does not enforce that uploads remain inside a fixed safe directory.

The file upload configuration for the file storage module also does not restrict extensions or MIME types.

Impact

An authenticated user can upload arbitrary file types, including .php, to a chosen location such as:

/application/public/upload/files/Documents

Issue 3: Remote code execution through uploaded PHP files

Problem

Uploaded files can be placed under the public web root, and Nginx/PHP-FPM will execute .php files from that location.

Impact

This leads to authenticated remote code execution.

Observed behavior

A harmless PHP proof file uploaded to the public files directory was executed successfully when requested through the browser.

Issue 4: Sensitive secrets committed to the repository

Problem

The repository includes:

  • .env
  • JWT key files under config/jwt/dev/
  • JWT key files under config/jwt/prod/

Impact

If these values are real and reused in deployments, an attacker may be able to:

  • recover database credentials
  • recover JWT signing material
  • forge valid tokens
  • fully compromise deployed instances

Reproduction overview

I was able to reproduce the issues on a deployed instance with the following high-level flow:

  1. Authenticate as a normal user
  2. Call POST /upload/send/
  3. Set uploadConfigId to the file storage configuration
  4. Provide a .php payload as file content
  5. Set extraData.uploadDir to a public directory under /application/public/upload/files/Documents
  6. Request the uploaded file through the web server
  7. Observe that PHP is executed

I also confirmed that /public/get-file/{path} can be used to retrieve /application/.env.

If needed, I can provide a private PoC.

Expected behavior

  • File download endpoints should only serve files from an explicitly allowed directory
  • Uploads should be restricted to server-defined directories only
  • File storage uploads should reject executable extensions such as .php
  • Public upload directories should never allow PHP execution
  • Secrets and key material should not be committed to the repository

Actual behavior

  • Arbitrary filesystem paths can be read
  • Upload target paths can be influenced by the client
  • Executable files can be uploaded into the public web root
  • Uploaded PHP files are executed by the server
  • Sensitive secrets are present in the repository

Suggested fixes

  1. Restrict /public/get-file/{path} to a fixed allowlisted base directory
  2. Remove support for client-controlled absolute upload directories
  3. Enforce strict extension and MIME allowlists for every upload configuration
  4. Explicitly block executable extensions such as .php, .phtml, .phar, etc.
  5. Store uploads outside the web root
  6. Configure Nginx to never execute PHP from upload directories
  7. Remove committed secrets from the repository
  8. Rotate:
    • database credentials
    • APP_SECRET
    • JWT keys
    • any other exposed credentials

Severity

Critical

Because the current design allows authenticated arbitrary file read and authenticated remote code execution, and repository secrets may further increase the blast radius.

Thanks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions