Update: Das Covid-Zertifikat wurde revoziert, siehe Abschnitt „Nachtrag“.
… weil es mit einem offiziellen anerkannten Signing Certificate signiert wurde und deshalb von allen europäischen Check-Apps (in der Schweiz bspw. die iOS App Covid Check) als echt eingestuft wird.
Richtigerweise müsste man sagen: „Es sind echte Zertifikate mit unplausiblen Angaben im Umlauf“.
Via eines Artikels des Redaktionsnetzwerkes Deutschland: Fake-Impfzertifikat für „Adolf Hitler“ wird von offiziellen Apps akzeptiert
Zwischenbemerkung: Ich bin kein Public-key Kryptographiehirsch und es kann daher durchaus sein, dass ich mit meinem Halbwissen hier falsche Begriffe verwende und die Mechanismen fehlerhaft wiedergebe. Man möge mich darauf hinweisen, mir verzeihen und mich nicht wie Kimmich auf dem Scheiterhaufen der Narrativfrevler verbrennen.
Hier der QR-Code zum selber abföttelen (und zwecks Extraktion zusätzlicher Informationen, die in der Check App nicht angezeigt werden):
Offenbar sind weitere solche Zertifikate im Umlauf, wie eine Diskussion auf GitHub zeigt. Unter anderem eines ausgestellt auf den Herrn Mickey Mouse.
Auf Grund der offensichtlich unplausiblen Namen auf den Zertifikaten kann man im Ausschlussverfahren bereits einige Feststellungen machen:
- Dem Ersteller war es egal, aufzufallen. Sonst hätten sie nicht Zertifikate auf Namen von toten Diktatoren und von Comicfiguren ausgestellt.
- Und da sie aufgefallen/aufgeflogen sind, ging es ihnen offenbar auch nicht darum, mit dem „Hack“ Geld zu verdienen, noch die sich der Impfung verweigernden Mitglieder ihrer Grossfamilie und sonstige Bekannte still und leise mit gültigen Zertifikaten zu versorgen.
- Stattdessen — und das ist aus meiner Sicht das wahrscheinlichste Szenario — ging es dem Ersteller darum, das Zertifikatssystem blosszustellen und zu diskreditieren.
- (Oder aber diese auffälligen Zertifikate wurden erst erstellt, nachdem der Ersteller aufgeflogen waren und sie sich sagten: „Jetzt ist eh alles aus, dann machen wir noch ein, zwei Zertifikate für Ruhm und Ehre in den Hackerkreisen, um allen zu zeigen dass wir es geschafft haben und beliebige Zertifikate ausstellen konnten“)
Was bedeutet das nun konkret für das Zertifikat-Ökosystem?
- Ein (oder mehrere!) Private Keys hinter den Signing Certificates sind in die falschen Hände gelangt. Dies würde bedeuten, dass alle von der betroffenen Certificate Authority ausgegebenen Zertifikate storniert und erneut generiert werden müssten — nachdem man ein neues Signing Certificate erstellt hat. Chaos vorprogrammiert, und insbesondere der Reputationsschaden.
- Ich hoffe aber, dass die Private Keys entsprechend der Industry Good Practices geschützt in einem HSM abgelegt sind. Und wirklich nur dort.
- Auch erachte ich es als unwahrscheinlich, dass der Private Key mit Brute Force berechnet wurde.
- Ein (oder mehrere!) Insider mit Zugang zu den Systemen zur Ausstellung haben aus Jux solche Zertifikate generiert. In diesem Fall wird es relativ einfach sein, an Hand der Logs der offiziellen Systeme die fehlbaren Personen ausfinding zu machen (wäre der Private Key geleakt könnte man die Zertifikate auf irgendeinem System ausstellen). Ausserdem müssten die personenspezifischen Zertifikate revoziert werden, sofern das System darauf ausgelegt ist. Selbst wenn sie erfolgreich revoziert sind, müssten die Check Apps beim Scannen eines Zertifikats diese dann auch noch gegen die Revozierungsliste prüfen. Ob die Apps das wirklich machen, und wie das genau geht (in Echtzeit? oder mittels einer Denylist, die periodisch heruntergeladen wird, wenn das Smartphone einen Internetzugang hat), weiss ich nicht.
- Verwandt: Unauthorisierte Angreifer sind eines oder mehrere Ausstellungssysteme eingedrungen, und zeigen uns und der Welt, dass sie mit ihrem Angriff erfolgreich waren.
- Verwandt: Es handelt sich um Zertifikate, die Entwickler aus Testgründen erstellt haben. Entweder haben sie diese dann selber willentlich verbreitet, oder die Zertifikate wurden von deren Systemen gestohlen.
Sind wir gespannt, was nun passiert. Ich hole mir schon einmal eine Tüte Popcorn hervor … das wird lustig.
Nachtrag
Gestern (28. Oktober 2021) mit der Covid Check-Applikation:
Heute (29. Oktober 2021) mit der Covid Check-Applikation:
Erkenntnis: Die Covid Check-Applikation hat die Möglichkeit, revozierte Zertifikate zu erkennen.
Nachtrag 2
Mich nahm es Wunder, wie die Liste der revozierten Zertifikate in die Covid Check-App kommt.
Leider schaffte ich es in der Eile nicht, mich mittels mitmproxy noch mittels Proxyman zwischen die Kommunikation der App mit den Servern zu hängen.
Immerhin fand ich in den DNS-Logs beim Prüfen des Adolf-Zertifikats folgende Einträge:
29-Oct-2021 23:08:00.511 queries: info: client @0x7f02940a72b8 10.1.2.3#62957 (www.cc.bit.admin.ch): query: www.cc.bit.admin.ch IN TYPE65 + (10.1.2.53) 29-Oct-2021 23:08:00.511 queries: info: client @0x7f0294075c88 10.1.2.3#50648 (www.cc.bit.admin.ch): query: www.cc.bit.admin.ch IN A + (10.1.2.53) 29-Oct-2021 23:08:00.559 queries: info: client @0x7f029c0812c8 10.1.2.3#61548 (d1m3nqpmh6pah2.cloudfront.net): query: d1m3nqpmh6pah2.cloudfront.net IN TYPE65 + (10.1.2.53)
Damit ausgerüstet entdeckte ich das GitHub-Script verify_ehc.py:
... # Switzerland: # See: https://github.com/cn-uofbasel/ch-dcc-keys ROOT_CERT_URL_CH = 'https://www.bit.admin.ch/dam/bit/en/dokumente/pki/scanning_center/swiss_governmentrootcaii.crt.download.crt/swiss_governmentrootcaii.crt' CERTS_URL_CH = 'https://www.cc.bit.admin.ch/trust/v1/keys/list' UPDATE_URL_CH = 'https://www.cc.bit.admin.ch/trust/v1/keys/updates?certFormat=ANDROID' ...
Ein Aufruf dieser URLs produziert folgende Fehlermeldung:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sun Oct 31 12:32:59 CET 2021There was an unexpected error (type=Forbidden, status=403).
Auf der ebenfalls erwähnten GitHub-Seite github.com/cn-uofbasel/ch-dcc-keys liest man dann:
The BIT (Bundesamt für Informatik und Telekommunikation) has two REST endpoints at https://www.cc.bit.admin.ch/trust/v1 where (a) a list of DCC key parameters, and (b) a table of active key IDs can be fetched. Both calls seem to need a bearer token which we extracted from the BIT’s Android CovidCertificate app. As of July 15, 2021, the token is:
Authorization: Bearer 0795dc8b-d8d0-4313-abf2-510b12d50939Although we don’t make use of the SDK (and therefore are not bound by the following) and believe that access to governmental public keys should be permissionless, we point to the comment in the Android app’s source code:
// If you intend to integrate the CovidCertificate-SDK into your app, // please get in touch with BIT/BAG to get a token assigned.See https://github.com/admin-ch/CovidCertificate-SDK-Android/ from where we grabbed the bearer token value from the gradle file.
Dann versuchen wir das mal:
$ curl --header "Authorization: Bearer 0795dc8b-d8d0-4313-abf2-510b12d50939" https://www.cc.bit.admin.ch/trust/v1/keys/list { "activeKeyIds": [ "e/YRqyv++qY=", "jYpr5GHCDiQ=", "JkFekJel6/o=", "/IcqIBnnZzc=", "02vdAOY/+gI=", "0L7AaIwu+EY=", "0kAwFy+vLpg=", "1+da8dKEjlE=", "25QCxBrBJvA=", "2BGoyFIyYPs=", "2JelGO/ymxQ=", "3IsdmTYkAAM=", "3LCRmucB9kU=", "3jqajzfHpKE=", "3lTmAZX19GQ=", "3lrBUHc4iQE=", "3oYtiEZ9wp4=", "4GkJs9YsYS4=", "4Qmniw7B0gc=", "5xtSr6KkAGA=", "6CDB1hL+uKU=", "6FNkACSMLEc=", "6VdOPLF8/Fg=", "6ag2wJkSHtk=", "7AfAwcpWOv0=", "7XLhQx1KXdQ=", "7rZbUrXNlLk=", "7z8+6oww2a8=", "8AnF/hcilSo=", "90CNG8dcdn0=", "9IZVOkJRZPQ=", "9v3FozjKAUo=", "AN1EeLIMAmo=", "AQCGDydsS1Q=", "ARrNkCRtprY=", "BEnvMVnNFK8=", "BKBFhNFXWAU=", "CvktK3hdjeY=", "CvmI4xOoMj4=", "DusseXrzqO8=", "Er5OTMwLd78=", "EzYR1uk/E0I=", "FDNJjaSCWi0=", "G3jDFQ1oK0Q=", "GMFMBu1RlCg=", "GuQPQRxbMsU=", "GvVR3e6VJIM=", "HeWuzGwEM5c=", "HhkeqvrtQ0U=", "IZftFLRmKGY=", "IaGR283U1jA=", "Is2JtrOJhik=", "JHd4CkNzadI=", "Jjql9rBrjHI=", "KG9lzdohSY0=", "L7XIA2gi2ps=", "M8bcnysCMj4=", "MrT00mhDxLQ=", "MtI93IMknMk=", "MxhfdcoHinc=", "NAyCKly+hCg=", "NCc6YSsVioM=", "NCdyt3s+cak=", "NJpCsMLQco4=", "ODqaG8mnbro=", "OKpEjMo/2MY=", "PBpDVqnJ7Us=", "Pbydc1LscXo=", "QacbC7DdD4U=", "R7q7yd90ZPU=", "TGjTR+Re+yk=", "TpQIkAHAym4=", "UZ1cSMaPcaQ=", "Uj77p+qIQNs=", "XkVWZqUeeFc=", "XuCERkHu8kY=", "YRYidQ+wetg=", "YU9+X9nepqU=", "YVpBYnLh1Hs=", "Yr8a8Rd+zqI=", "Z7k1XpIWZOE=", "ZDoFfkn+yhY=", "ZcfkloEvfGQ=", "bBnmkeVMV6A=", "bKmas9wa5tc=", "bfoj2trt6bE=", "c1XrnEBoj/c=", "ccgQ13tmkU8=", "cdm9Ymfwn2I=", "dhSzPDr4G2M=", "e+bFdywyJQE=", "e4lH6I4iMIM=", "e9SH8dtWwdY=", "eNNsg2jd4wA=", "eQOY6BDp+vM=", "f+4yAPIGTWg=", "f6J92LRKpj0=", "fGLuvg6n5wk=", "fNf883wPIEg=", "hA1+pwEOxCI=", "hFpY/ySOrwI=", "hgpHHrTb4ws=", "i5SVuCsR5TA=", "izUDZjGtHWY=", "juskqrNQf6k=", "kjEx2H7huNE=", "ln8K+9SqfuA=", "lrxgMs2Duac=", "lshLbYfCWRg=", "nHmZ5K96UY4=", "nPKEYm3gXzU=", "nTrG8glLUls=", "npo0ZWgdQSY=", "pSEfhlMubh4=", "qFNF2dC+mjQ=", "r9YkEJZgi9k=", "rKMDA66RiLE=", "rXP9L7xddL8=", "sYXcYixrOGA=", "tCM87WnaaQE=", "ub6Qmv9xtAo=", "vjm0I2ATJ+Y=", "vq08l/LTxhk=", "vvYa1vaWkGg=", "wb/2450PPrc=", "wtYpyAmNmdk=", "x3ch4ml934I=", "yWCRdph8XJs=", "7GBun0USD5E=", "IMgNr10pfPQ=", "YDAy+yvD5lU=", "r9RtWK9x7dM=", "crm1HLAeaTo=", "2Bh+2HrOg0c=", "lzGYCpOBQsU=", "ryvXsisPPeU=", "0JzyumjttZU=", "H6b6bQ8qij4=", "T8kbYovQlYU=", "4Ss2raOqhTw=", "JsReuAsmza8=", "ypEjzbYNqEw=", "2Yv0kajsIlA=", "mo/w8S8rZ0Q=", "FhciF/j3plg=", "gEIK4Q/lAG0=", "Amn7EaBy1ag=", "M+R7JFFk6G8=", "MJuQDybecd4=", "o11W81MgYYg=", "AX/m4PDDCXE=", "pe6raiG2dWE=", "rLMiGt6uB3U=", "eUVY16rD2Kc=", "hHffSLS1AIU=", "fNstNUxgGSI=", "l8W4rhh9nTs=", "ZpnsokK1DgM=", "Ui7DXQikstE=", "26Fcjnjuf2s=", "72XVTQ2A9Jw=", "7byt9scureM=", "EDSWY8Hnul4=", "IKMstf8yj/4=", "hWoyHrtJs+E=", "cS/wou0g/po=", "Xo78qgBEx8k=", "mqWkXpNR0Rk=", "FtUwA9uHJoo=", "Pcl7yBWEQ7c=", "Cj0KwOpRFvQ=", "53FOjX/4aJs=", "ohI9KlFR2P8=", "rVPuf3yKLBg=", "l+UqotarLJc=", "hGUS4Zj9fLM=", "2eCjZcuOoEo=", "d+WbDD8Gr5g=", "TQeqi04M2ek=", "JZhMLV9Gyck=", "oVKwwScGxuY=", "Ll3NP03zOxY=", "rTEJEs6D1ik=", "1MTFjluEWHU=", "KBPNEuXUvrY=", "1PtilTAMiyk=", "I0+qkOLr2e0=", "jeetFC69E6o=", "lYkujLws7SE=", "osFRFyFIWdU=", "W0NjksmJMm0=", "26YSc5g0nG8=", "1J9pb87ndV0=" ], "validDuration": 172800000 }
Hierbei handelt es sich vermutlich um die Liste der derzeit anerkannten Signing Certificates aller Herren Länder. 1J9pb87ndV0= scheint bspw. von Grossbritannien in Belfast (Nordirland) verwendet zu werden, während 2eCjZcuOoEo= (Zufallstreffer, i schwöre!) ein Schweizerisches Signing Certificate zu sein schein (Quelle).
Dasselbe klappt auch mit der Update API, welche offenbar auch die oben aufgeführten Keys enthält, aber noch mit mehr Informationen ausgeschmückt sind (ich zähle heute, am 31. Oktober 2021, für beide Listen je 193 Einträge; die zweite URL liefert 193 Zeilen mit „keyID“, die erste Liste enthält ebenfalls 193 Keys):
$ curl --header "Authorization: Bearer 0795dc8b-d8d0-4313-abf2-510b12d50939" https://www.cc.bit.admin.ch/trust/v1/keys/updates?certFormat=ANDROID { "certs": [ { "keyId": "e/YRqyv++qY=", "use": "sig", "alg": "ES256", "n": null, "e": null, "subjectPublicKeyInfo": null, "crv": "P-256", "x": "mCCGUDO95y6Rj40KX74cFgc99I9BnFoPBkZ3kcAyo2o=", "y": "v7JjeIG2FpKwtljBK7DfM2d+wvUYQBpR2AzfLTyW4gM=" }, { "keyId": "jYpr5GHCDiQ=", "use": "sig", "alg": "ES256", "n": null, "e": null, "subjectPublicKeyInfo": null, "crv": "P-256", "x": "lHOTKQPe3GZKCAIsaBbPpAfJZ30ftIUsb/r6gHu19cI=", "y": "NtVzH4mQ0LiN8HvNns7Jsoy/4369c5UWKly5m6jq5CQ=" }, { "keyId": "JkFekJel6/o=", "use": "sig", "alg": "ES256", ...
Ist das Adolf-Zertifikat vielleicht hier aufgeführt? Dazu verwende ich vacdec, um den QR-Code zu entschlüsseln:
$ ./vacdec "Adolf-Hitler-COVID-Zertifikat.png" {-260: {1: {'dob': '1900-01-01', 'nam': {'fn': 'HITLER', 'fnt': 'HITLER', 'gn': 'ADOLF', 'gnt': 'ADOLF'}, 'v': [{'ci': 'URN:UVCI:01:FR:T5DWTJYS4ZR8#4', 'co': 'FR', 'dn': 2, 'dt': '2021-10-01', 'is': 'CNAM', 'ma': 'ORG-100030215', 'mp': 'EU/1/20/1528', 'sd': 2, 'tg': '840539006', 'vp': 'J07BX03'}], 'ver': '1.3.0'}}, 1: 'CNAM', 4: 1697234400, 6: 1635199742}
Die Felder sind hier dokumentiert (v1.3.0). Der Einfachheit halber hier wiedergegeben:
- dob
- Date of Birth
- nam/fn
- Surname
- nam/fnt
- Standardized Surname
- nam/gn
- Forename
- nam/gnt
- Standardized Forename
- v/ci
- Unique certificate identifier
- v/co
- Country
- v/dn
- Number in a series of doses
- v/dt
- Date of vaccination
- v/is
- Certificate Issuer (CNAM = Das cnam?)
- v/ma
- Marketing authorisation (der Impfhersteller)
- v/mp
- Vaccine product (das Impfprodukt)
- v/sd
- Overall number of doses (die technische Spezifikation erwähnt im Juni 2021 (!) bereits 3 im Falle eines Boosters …)
- v/tg
- Disease or agent targeted
- v/vp
- Vaccine or prophylaxis used
Hmmm, habe nach T5DWTJYS4ZR8 und J07BX03 in den JSONs gesucht, aber nichts gefunden. Die JSON-Listen führen also effektiv nur die vertrauenswürdigen Zertifikats-Issuer auf.
2 Kommentare Kommentare
Stand heute (04.12.2021) ist das Zertifikat immer noch gülitg. Gerade gechecked mit CovidPass Check aus Google Play Store.
Anmerkung: im QR-Code befindet sich ein COSE Objekt (Signed CBOR). Programme wie VacDec überspringen den COSE Header und die abschließenden Signatur und decodieren direkt den innenliegenden CBOR Teil (was vermutlich ja die meisten Nutzer interessiert). Die Kid (Key ID) steht aber im Header. Hier das Vollständige COSE Objekt:
tag 18
[
A201260448E7714E8D7FF8689B // protected header
{} // unprotected header
// CBOR object
A40164434E414D041A6529BDE0061A61772AFE390103A101A4617681AA626369781D55524E3A555643493A30313A46523A54354457544A5953345A5238233462636F62465262646E026264746A323032312D31302D303162697364434E414D626D616D4F52472D313030303330323135626D706C45552F312F32302F313532386273640262746769383430353339303036627670674A30374258303363646F626A313930302D30312D3031636E616DA462666E664849544C455262676E6541444F4C4663666E74664849544C455263676E746541444F4C466376657265312E332E30
// signature
F8E43D7E980CC61891E209FC8EA8430BD3E88AE1EEDA9E312AE1CE5EFAF22C4516346FEF09AF0057599EA6B04EA7E2B0F0BBB0780230E0FAF0E7AFAA9EAB6A5D
]
Der dekodierte Header sieht dann so aus:
{
1: 7
4: E7714E8D7FF8689B // Kid
}
die Kid von Herrn H.’s Zertifikat ist also die E7714E8D7FF8689B oder in Base64 53FOjX/4aJs=
Diese Id führt uns dann zu einem Signatur Schlüssel aus Italien:
„53FOjX/4aJs=“: {
„serialNumber“: „6e3a243ea72c2bd04f6bd51d59ec497b212a8a5a“,
„subject“: „C=FR, O=CNAM, OU=180035024, CN=DSC_FR_023“,
„issuer“: „C=FR, O=Gouv, CN=CSCA-FRANCE“,
„notBefore“: „2021-10-14T22:00:00.000Z“,
„notAfter“: „2023-10-14T22:00:00.000Z“,
„signatureAlgorithm“: „RSASSA-PKCS1-v1_5“,
„fingerprint“: „be552cc91a5fe934268b9db169db6349311ad693“,
„publicKeyAlgorithm“: {
„hash“: {
„name“: „SHA-256“
},
„name“: „ECDSA“,
„namedCurve“: „P-256“
},
„publicKeyPem“: „MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgu/WJBn1Q+RCOfQx3NLT5oIGUCHsqSRXuu7EZsqfqZN5PvHk6/E++88wvj2fMrfmAptk5tVld2xBH4P4tRs8JQ==“
Interessant hier auch, dass der Zertifikat des Herrn H. am 1.10.2021 ausgestellt wurde, der Schlüssel aber erst am dem 14.10.2021 gültig ist („notBefore“: „2021-10-14T22:00:00.000Z“)…nun „gut“, nachdem so einiges an diesem Zertifikat nicht zu stimmen scheint, ist das Datum wohl eher nicht so wichtig.
Obwohl das bei einer meiner Impfungen auch vorgekommen ist. Das Zertifikat wurde vor der Gültigkeit des signierenden Schlüssels ausgestellt…