Skip to content

ULEARN bundled TinyMCE openmanager fileactions.php allows unauthenticated unrestricted file upload #78

Description

@fa1c4

1. Bug Topic

ULEARN bundled TinyMCE openmanager fileactions.php allows unauthenticated unrestricted file upload

2. Release Version / Commit Hash / Affected Range

Confirmed affected in the InvAudit target snapshot 0762_safytech__ulearn.

The public GitHub repository identifies ULEARN as an open-source LMS script; the target source composer.json has package name ulearnpro/ulearn and requires Laravel 5.8.*. Exact full affected range should be confirmed by the maintainer.

3. Bug Type

Unauthenticated Unrestricted File Upload

4. CWE

CWE-434: Unrestricted Upload of File with Dangerous Type; CWE-306: Missing Authentication for Critical Function

5. Bug Summary

ULEARN includes a public TinyMCE openmanager uploader at public/backend/curriculum/js/plugins/tinymce/jscripts/tiny_mce/plugins/openmanager/php/fileactions.php. The s=uploadfile action accepts user-controlled uploadfolder, mediatype, and original filename, then writes the uploaded file without authentication, CSRF protection, extension allowlist, MIME/content validation, or safe server-generated filenames. An attacker can upload a .php file into a public plugin subdirectory.

6. Root Cause

The root cause is a legacy file manager endpoint exposed under public/backend/... with no request authorization or file-type validation. In upload_file(), the destination is built from ../ plus $_POST['uploadfolder'], media/ or images/, and the original filename from $_FILES['userfile']['name'], then move_uploaded_file() writes the file.

7. Attack Preconditions

The attacker must be able to reach the public fileactions.php?s=uploadfile endpoint. No authentication is required in the vulnerable file. Remote code execution requires that the uploaded .php file be web-accessible and executed by the server; otherwise this is still an unauthenticated arbitrary dangerous file upload to a public path.

8. Impact Analysis

An attacker can upload arbitrary files, including PHP webshells, under a public backend plugin directory such as openmanager/media/shell.php. This can lead to persistent arbitrary file write and, if PHP execution is enabled in that path, remote code execution.

9. Affected Code

  • public/backend/curriculum/js/plugins/tinymce/jscripts/tiny_mce/plugins/openmanager/php/fileactions.php: if ($s == "uploadfile") { upload_file(); }
  • fileactions.php: $uploadfolder = "../".$_POST['uploadfolder'];
  • fileactions.php: $tname = $_FILES['userfile']['name'];
  • fileactions.php: $destination = $uploadfolder.$mediafolder.$name;
  • fileactions.php: move_uploaded_file($_FILES['userfile']['tmp_name'], $destination);

No authentication, CSRF token, extension allowlist, or MIME/content validation is visible before the write.

10. PoC

Standalone Docker PoC directory: https://github.com/fa1c4/security-advisories/tree/main/ulearn.

docker build -t poc-ulearn-openmanager-upload .
docker run --rm poc-ulearn-openmanager-upload

The PoC simulates a public s=uploadfile request with uploadfolder=uploads/, mediatype=media, and userfile=shell.php. The vulnerable path writes the PHP file under uploads/media/; patched controls require authentication/CSRF and reject the .php extension.

11. Expected Result

The openmanager uploader should not be publicly reachable without authorization. Uploads should require authentication and CSRF protection, normalize and constrain the target directory, use a strict extension/MIME allowlist, generate server-side filenames, store files outside executable paths, and reject PHP/PHTML/PHAR or other executable extensions.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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