All Advisories

fbeta ePA3-Service-OpenSource

VAU Server Authentication Bypass via Circular Certificate Trust

fbeta's ePA3-Service fetches the certificate used to verify the server's signed VAU public keys from the same server, with TLS verification disabled, then discards the return value of vau_cert_validation(). Only one of the six A_24624-01 checks is implemented, so a network MITM can serve a self-signed certificate from /CertData, sign the VAU keys with the matching private key, and own the resulting session keys.

SeverityCriticalCVSS 9.1CVSS 3.1 VectorAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:NCWECWE-295 (Improper Certificate Validation)Productfbeta ePA3-Service-OpenSourceAffected VersionsAll versions prior to 1.3.0 (initial commit `a61f91d` through 1.0.1)Fixed In1.3.0 (incorporates pull request #12)GHSAGHSA-q2jw-6c4w-86jc

Description

Defect 1: circular trust. The certificate used to verify the server's signed public keys is fetched from the same server being authenticated, with TLS verification disabled (verify=False). A network MITM can serve their own self-signed certificate from the /CertData endpoint and sign the VAU public keys with the matching private key. The ES256 signature check then passes by construction.

VAUProtokoll.py:267-273

cert_endpoint = urljoin(self.AS_URL, f"/CertData.{cert_hash_hex}-{cdv}")
cert_data_response = self.https_session.get(
cert_endpoint,
verify=False,
headers={"x-useragent": USER_AGENT},
)

View source →

Defect 2: discarded return value. vau_cert_validation() returns False on three failure paths (non-200 CertData response, missing fields, non-EC key) without raising. The caller discards the return value and proceeds with the unauthenticated keys.

VAUProtokoll.py:154-156

self.vau_cert_validation(signed_vau_server_pub_keys)
pub_keys = cbor2.loads(signed_vau_server_pub_keys["signed_pub_keys"])

View source →

Defect 3: only 1 of 6 A_24624-01 checks implemented. gemSpec_Krypt A_24624-01 requires six checks on the server's signed public keys: ES256 signature verification, certificate chain to the TI PKI root, temporal validity, OCSP/CRL revocation, cert_hash integrity, and key-usage / role OID. Only ES256 signature verification is implemented, and that against an attacker-supplied certificate (Defect 1). The ca and rca_chain fields are required to be present in the CertData response but are never used for chain validation.

VAUProtokoll.py:284-287

required_fields = ["cert", "ca", "rca_chain"]
if not all(field in cert_data for field in required_fields):
logger.error("Missing required fields in CertData")
return False

View source →

fbeta's ePA3-Service derives its cryptographic layer from Andreas Hallof's upstream vau-protokoll, which inherits the gap in server-key verification documented in gematik: VAU Handshake Performs Only 2 of 6 Required Server-Key Checks. fbeta added a partial verifier on top, but the return value is discarded and 5 of the 6 required checks are missing.

Impact

  • A network-positioned attacker between the DiGA backend and the ePA Aktensystem intercepts the VAU handshake, serves their own VAU public keys and self-signed certificate, and owns the resulting session keys. All inner HTTP traffic (patient medication records, diagnostic reports, prescription history, document reads/writes, authorization transactions) is then visible to and modifiable by the attacker.
  • Neither transport layer nor application layer authenticates the server. TLS verification is disabled across the library (see fbeta: TLS Certificate Verification Universally Disabled) and the VAU certificate validation is circular; neither transport nor application layer authenticates the server on the patient-data channel.
  • A MITM holding the session keys can read and modify all inner HTTP traffic on the VAU channel. During testing, a single relay read three patients' consent decisions, modified the responses, and injected a third patient's record, all from a self-signed certificate with no CA chain.

Mitigation

Update fbeta ePA3-Service-OpenSource to 1.3.0 or later. The fix implements certificate chain validation against the TI-PKI root, checks the return value of vau_cert_validation() and aborts on failure, and adds the remaining A_24624-01 checks (cert_hash integrity against SHA-256(cert_der), temporal validity, OCSP, and the oid_epa_vau role OID). TI PKI root certificates are not in the standard system trust store; source them from gematik's published TI PKI (gemSpec_PKI, TI Root CA appendix) and pin them explicitly.

Defender's Checklist

  • Update to fbeta ePA3-Service-OpenSource 1.3.0 or later.

    All versions before 1.3.0 are affected; there are no intermediate releases between 1.0.1 and the fix. The fix lives in pull request #12.

  • Verify the trust anchors actually ship.

    The fix requires the gematik TI-PKI root certificates to be available at runtime. Confirm your deployment loads them from gemSpec_PKI's TI Root CA bundle and not from the standard system trust store, which does not contain them.

  • Audit your own callers of vau_cert_validation().

    If you have a fork or downstream wrapper of this library, check every call site of vau_cert_validation() and equivalent verifiers in the same family: the boolean return must be read, and failure must abort the handshake. A discarded return value is the same as no check at all.

  • Test with a self-signed peer.

    Stand up a local VAU peer that responds to Message 2 with attacker-controlled public keys, a self-signed cert, and arbitrary signatureEs256 bytes. The client must refuse the handshake. If it does not, the validator is not wired in.

Severity Reasoning

AV:NThe threat model A_24624-01 is written against is a network attacker on the path between the DiGA backend and the ePA Aktensystem.AC:LThree independent defects line up to remove server authentication; a single self-signed certificate at the /CertData endpoint is sufficient. No timing or environmental conditions.PR:NNo credentials needed beyond the network position itself.UI:NThe DiGA backend initiates the VAU handshake on its own schedule.S:UImpact is bounded to the VAU channel and the ePA payloads it carries.C:HPlaintext access to ePA document reads and metadata for any patient whose DiGA uses this library.I:HPlaintext access to and modification of ePA document writes and authorization flows.A:NNo availability impact.

References

How We Can Help

Who We Are

The security researchers behind this advisory.

Dr. Simon Weber Profile

Dr. rer. nat. Simon Weber

Senior Pentester & MedSec Researcher

I evaluate your SaMD with the same industry-defining security insight I contributed to the BAK MV for the revision of the B3S standard.

  • PhD on Hospital Cybersecurity
  • Critical vulnerabilities found in hospital systems
  • Alumni of THB MedSec Research Group
  • gematik Security Hero
Volker Schönefeld Profile

Dipl.-Inf. Volker Schönefeld

Senior Application Security Expert

As a former CTO and developer turned pentester, I work alongside your team to uncover vulnerabilities and find solutions that fit your architecture.

  • 20+ years as CTO, 50M+ app downloads
  • Architected and secured large-scale IoT fleets
  • Certified Web Exploitation Specialist
  • gematik Security Hero

Looking for a Penetration Test?

Machine Spirits specializes in security assessments for medical devices and healthcare IT. From MDR penetration testing to C5 cloud compliance, we help MedTech companies meet regulatory requirements.