Key Takeaways:
- A vulnerability in public administration systems allowed attackers to generate a certificate with another person’s data and bypass authorization in Social Security, e-Courts, and e-Health platforms.
- Lack of proper cryptographic verification of the issuer (Trust Anchor) allows attackers to inject forged certificates.
- In the Gadnet system, we use full RFC 5280 certification path validation using native libraries (C-Rust) rather than “manual” code comparisons.
- Famous blunders by tech giants (e.g., Apple “goto fail”, Microsoft CurveBall) prove that cryptography must always be delegated to proven libraries.
This morning, we woke up to a new reality in Polish cybersecurity. The shocking news about a vulnerability allowing access to any citizen’s account in state services made us all realize how powerful seemingly boring “technicalities” can be. When we designed the certificate architecture and IoT device verification from scratch at GADNET, we were extremely rigorous about our Public Key Infrastructure (PKI). What we treated as critical and absolute rules during our security audits has unfortunately failed on an unprecedented scale in key Polish public systems.
The e-Signature Verification That Failed
The Polish internet was buzzing with news about a critical vulnerability in the eZUS, e-Court, and e-Health systems. It is crucial to clarify: the state architecture itself didn’t have a “magic loophole” – the direct cause was a critical flaw inside the Szafir software (provided by KIR), which these systems integrated to handle logins. The logic implemented in this specific application completely failed to properly verify whether the qualified signature card was issued by a trusted and authorized certification entity.
In practice, these systems trusted the spoofed issuer data saved on a forged certificate. The lack of a full, cryptographic verification of the Chain of Trust allowed attackers to “issue” themselves cards containing the first name, last name, and national ID number (PESEL) of any victim, resulting in a complete bypass of authorization to log into citizens’ accounts.
Manual Verification vs Structural Cryptography
To understand the difference, let’s look at the comparison of approaches. In the overall security architecture of GADNET, we deliberately moved away from simple, manual “name checking”. Instead of writing our own risky verification conditions in the application code, we use industry-proven mechanisms for policy handling (such as the PolicyBuilder object), which implements strict chain validation of the entire certificate path in accordance with the RFC 5280 Section 6.1 standard. This means checking the path from the client, through the intermediate issuer, to the Root CA, while cryptographically verifying every digital signature along the certification path.
| Feature | Manual Verification (Naive) | GADNET PKI (RFC 5280) |
|---|---|---|
| Issuer comparison | Only the “Issuer” field | Cryptographic signature verification with CA key |
| Code delegation | Custom, unverified code | Native cryptographic modules (C/Rust) e.g., from cryptography library |
| Permissions validation | Often skipped | Required Key Usage and EKU (Client Authentication) |
| Forgery resistance | Vulnerable to fake certificates | Computationally infeasible without access to the CA private key |
However, we must emphasize the most crucial detail: cryptographic signature verification alone is not enough if the system blindly trusts any Root CA provided by the client. Full path validation protects against attacks only when the Trust Anchor is a closed, rigorously controlled list of authorities (in Poland, e.g., the National Certification Center - NCCert). Only the combination of mathematical signature verification with a closed list of permitted Root CAs completely blocks attackers.
The Biggest PKI Implementation Errors in the World
Poor certificate verification and flawed cryptography implementation are problems as old as the IT industry itself. History is full of spectacular failures:
- Apple “goto fail” (CVE-2014-1266): In 2014, the world held its breath when a bug was found in the Apple iOS and OS X code. A doubly typed
goto fail;instruction in C unconditionally bypassed a crucial loop verifying SSL/TLS signatures. The bug allowed for massive Man-in-the-Middle attacks. - Microsoft CryptoAPI “CurveBall” (CVE-2020-0601): In 2020, a vulnerability was discovered in the Windows Crypt32.dll library. Microsoft’s code poorly validated certificates based on Elliptic Curve Cryptography (ECC). This allowed cybercriminals to “sign” malware with a fake certificate that pretended to be Microsoft, and Windows completely trusted it.
- Debian and predictable keys (CVE-2008-0166): In 2008, the maintainer of the OpenSSL package in Debian, wanting to remove code analyzer warnings, deleted crucial lines responsible for the randomness of the generator. For nearly 2 years, systems generated weak keys - there were only 32,768 possible variants.
The golden rule of cryptography states: “Don’t roll your own crypto”. While the developers of the vulnerable software didn’t implement their own math, they made the mistake of trying to “manually” handle the certificate validation logic. The conclusion is ruthless: do not write your own conditional statements to check issuers - instead, entrust the entire verification to a trusted, audited library that strictly and flawlessly executes every step of the complex RFC standard. In Gadnet, this is exactly what we stick to.