Adolf Hitlers Covid-Zertifikat ist nicht „gefälscht“ …

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 2021

There 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-510b12d50939

Although 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.