All Advisories

fbeta ePA3-Service-OpenSource

AES-GCM Nonce Reuse via Frozen VAU Request Counter

fbeta's ePA3-Service initialises request_counter but never increments it; every outgoing inner-VAU message header carries request_counter=0. The gematik lib-vau server uses that value for the counter portion of its own AES-GCM IV, reducing IV uniqueness to 32 random bits and exposing the channel to the Joux forbidden attack at ~77,000 responses.

SeverityHighCVSS 7.4CVSS 3.1 VectorAV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:NCWECWE-323 (Reusing a Nonce, Key Pair in Encryption)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 #10)GHSAGHSA-vmfm-3f7g-r9qg

Description

The VAU client initialises two counters at VAUProtokoll.py:64-65: encryption_counter, used for the client's own IV and incremented at line 399, and request_counter, used in the outgoing message header and never incremented anywhere. The gematik specification A_24628-01 requires the client to increment this counter for every request. Andreas Hallof's upstream vau-protokoll (from which fbeta's cryptographic layer is derived) includes the increment; the corresponding fbeta code path does not.

VAUProtokoll.py:64-65

self.encryption_counter = 0
self.request_counter = 0

View source →

VAUProtokoll.py:407 (counter in outgoing header)

header.extend(self.request_counter.to_bytes(8, "big"))

View source →

The gematik lib-vau server stores the client-supplied counter without monotonicity checks and uses it to construct the counter portion of its own AES-GCM IV, in violation of A_24631 (which requires an independent server-side counter). With the client locked at zero, the server's response IV becomes random(4) || 0x0000000000000000: 32 bits of entropy, with a birthday collision probability reaching 50% at ~77,000 messages. The corresponding lib-vau side is published as the gematik: AES-GCM Nonce Reuse in VAU Server Encryption.

Birthday collision probability for a fixed 64-bit counter:

Collision probability under a fixed counter

Messages P(IV collision)
100 < 0.01 %
1,000 0.01 %
10,000 1.16 %
50,000 25.23 %
77,163 50.00 %
100,000 68.55 %

AES-GCM provides no confidentiality or integrity guarantees on nonce reuse. The Joux forbidden attack (2006) lets an attacker who observes two ciphertexts encrypted under the same key and IV recover the GHASH authentication key H from the two authentication tags, and XOR the two ciphertexts to recover plaintext bytes. The inner HTTP responses on the VAU channel have highly predictable structure (HTTP headers, JSON fields, fixed-position KVNR digits), so partial-known-plaintext recovery is feasible without any further attacker capability.

During testing, a transparent proxy observed only encrypted traffic (no MITM, no decryption) and waited for a birthday collision on the 32-bit random IV prefix. After 57,248 encrypted responses two messages shared the same IV; all 9 patient-ID digits differed between the two patients, and the candidate-pair counts per digit position reduced the joint search space by a factor of 60:

Passive nonce collision observed by transparent proxy

11m43s | 55451 unique IVs | prob: 30.1%
COLLISION after 57248 encrypted responses.
Response A (#53331): IV = e0cc7a0e 00000000
Response B (#57247): IV = e0cc7a0e 00000000
Patient ID digits (bytes 188-196):
Pos 0: XOR=0x06 8 candidate pairs
Pos 1: XOR=0x07 8 candidate pairs
Pos 2: XOR=0x0b 4 candidate pairs
Pos 3: XOR=0x04 8 candidate pairs
Pos 4: XOR=0x07 8 candidate pairs
Pos 5: XOR=0x06 8 candidate pairs
Pos 6: XOR=0x0d 4 candidate pairs
Pos 7: XOR=0x02 8 candidate pairs
Pos 8: XOR=0x0d 4 candidate pairs
9/9 digits differ between the two patients.
Search space: 1,000,000,000 -> 16,777,216
Reduced by factor 60x from a single collision.

A second collision typically narrows the joint candidate set to a unique recovery.

Impact

  • The inner-VAU layer protects a patient's medication records, diagnostic reports, prescription history, KVNRs, document reads and writes, and the authorization transactions that control access to the record.
  • A passive attacker who observes only encrypted VAU responses on the network path can wait for a birthday IV collision (~77k responses for 50% probability, observed at ~57k during testing) and recover patient-ID digits and other predictable plaintext from the XOR of the two colliding ciphertexts. The precondition is passive network observation; no active intervention is required.
  • An attacker who recovers two ciphertexts under the same IV applies the Joux forbidden attack to recover the GHASH authentication key H. With H, the attacker forges the GCM authentication tag for ciphertexts under any IV where a collision has been observed, enabling tampering with server-to-client VAU messages: injecting false patient data or fake authorization responses into the channel.
  • If fbeta: TLS Certificate Verification Universally Disabled is also unmitigated, TLS termination removes the passive-observation prerequisite and the system-level AC collapses to L.

Mitigation

Update fbeta ePA3-Service-OpenSource to 1.3.0 or later. The fix increments request_counter on every outgoing message and validates response counter monotonicity to prevent replay. The same root condition exists upstream in the gematik lib-vau server (which stores the client counter without monotonicity check and uses it as the IV counter portion); see the gematik: AES-GCM Nonce Reuse in VAU Server Encryption. A downstream fix that always sends a fresh counter removes the passive trigger of the server-side condition but does not close the server-side gap against an active MITM who pins a fixed counter at the relay layer.

Defender's Checklist

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

    All versions before 1.3.0 are affected. The fix lives in pull request #10.

  • Verify the increment in your build.

    In your deployment of the library, run a short integration test that captures two consecutive outgoing VAU messages and asserts that the 8-byte request_counter field in the header changes between them. The original gap manifested as a single missing line in the encrypt path; an integration assertion is the cheapest way to keep it from coming back in a fork.

  • Check response counter monotonicity.

    The fix also adds monotonicity validation on the response counter. If you maintain a custom client, replace any equality check on the response counter with response_counter > last_seen_response_counter to prevent replays of past server responses.

  • Treat session length as a security parameter while a fix rolls out.

    Until the increment is in place across your fleet, rotate VAU sessions well below the 2^16-message boundary. The IV-collision probability passes 1% around 10,000 same-counter responses; that is your operational margin.

Severity Reasoning

AV:NReachable by any party that can observe VAU response traffic on the network path between the DiGA backend and the ePA Aktensystem.AC:HRequires collecting on the order of 2^16 to 2^17 server responses under the fixed client counter (~57k to 77k empirically) and applying the Joux GHASH-key recovery on a collision.PR:NNo credentials needed; passive observation of encrypted traffic suffices to trigger the precondition.UI:NNo second-party interaction is needed.S:UImpact is bounded to the cryptographic guarantees of the VAU channel.C:HPlaintext recovery from XOR of colliding ciphertexts; patient-ID digits and other predictable fields fall out of a single collision.I:HGHASH-key recovery enables forgery of authenticated server-to-client VAU messages, including injection of false patient data or fake authorization responses.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.