Lasst mich einfach Zahlen eingeben
(gendignoux.com/blog)- Im 6-stelligen E-Mail-Bestätigungsfeld des Schweizer Government-Login-Systems AGOV konnten Zahlen auf französischen AZERTY-Tastaturen nicht verarbeitet werden, sodass die Kontoerstellung vollständig blockiert war.
- Das JavaScript des Eingabefelds fing Tastenanschläge ab und speicherte den Bestätigungscode in einer separaten Variable, wobei es die Shift-Taste ignorierte; damit wurden AZERTY-Layouts, bei denen für Ziffern Shift nötig ist, faktisch ausgeschlossen.
- Derselbe Fehler trat in verschiedenen Kombinationen aus Firefox, Chromium, Chrome, Safari sowie Linux und macOS auf, funktionierte aber mit QWERTY-Tastaturen normal, wodurch sich das Problem nicht auf Browser oder Betriebssystem, sondern auf das Tastaturlayout eingrenzen ließ.
- Auch der offizielle Support war nur nach derselben E-Mail-Bestätigung nutzbar, und es gab keine Alternativen wie E-Mail oder Telefon, sodass Nutzer, die sich nicht einloggen konnten, den Login-Bug nicht einmal melden konnten.
- Wenn statt nativer Eingabefelder komplexe Tastenlogik verwendet wird und Produkt sowie Support-Kanäle an denselben Authentifizierungsablauf gekoppelt sind, brechen Zugänglichkeit und Störungsbearbeitung gemeinsam zusammen; nötig sind daher einfache DOM-basierte Eingaben und unabhängige Support-Kanäle.
AGOV als digitale Identitätsinfrastruktur
- Digitale Identität ist zuletzt zu einem zentralen Streitpunkt im Web geworden und bringt zahlreiche Abhängigkeiten und Kontroversen mit sich.
- Wie Altersverifikation die Online-Anonymität beeinflusst
- Dass Wikipedia im Vereinigten Königreich möglicherweise die Identität von Nutzern prüfen muss
- Das Problem, bei digitalen Identitäts-Wallets als Pflichtplattform von offiziellen iOS- und Android-Apps abhängig zu sein
- Ein Fall, in dem US-Digitalkonten storniert wurden, weil die Betroffenen Richter des Internationalen Strafgerichtshofs waren
- Das Schweizer Government-Login-System AGOV ist seit 2024 in Betrieb und hat 1,6 Millionen Konten erreicht.
- Es wird als Login-Mittel für verschiedene Behördendienste ausgeweitet, darunter Arbeitslosenversicherung und die verpflichtende Steuererklärung.
- Im Kanton Zürich ist es die einzige Login-Möglichkeit für den Zugang zur Einbürgerungsbeantragung.
Registrierung stoppt beim E-Mail-Bestätigungsschritt
- Das AGOV-Registrierungsverfahren beginnt nach Eingabe einer E-Mail-Adresse mit der Eingabe eines 6-stelligen Bestätigungscodes.
- Die UI für den Bestätigungscode besteht aus insgesamt sechs Eingabefeldern, eines pro Ziffer.
- Auch nach Eingabe einer Zahl springt der Fokus nicht zum nächsten Feld.
- Im aktuellen Feld sammeln sich weiter Zahlen an, und es wechselt in einen roten Fehlerzustand.
- Selbst wenn man manuell Feld für Feld weitergeht, erscheint am Ende der Fehler
field required.
- Es wurde versucht, die DOM-Werte direkt in den Entwicklerwerkzeugen zu ändern, aber es gab keine sichtbaren Formularwerte, und auch in der Web-Konsole wurde kein Fehler protokolliert.
- Auch mit einer anderen E-Mail-Adresse oder einer Fake-Adresse wie
test@example.comwar das Ergebnis identisch.example.comist gemäß RFC 6761 eine reservierte Domain.
Browser- und Betriebssystemhypothesen ausgeschlossen
- Zunächst lag die Vermutung nahe, dass die Kombination aus Firefox und Linux nicht unterstützt werde oder CAPTCHA fehlschlage.
- Unmittelbar bevor das Formular für den Bestätigungscode erscheint, wird eine Verbindung zu
eu-api.friendlycaptcha.euaufgebaut. - In den offiziellen Anforderungsdokumenten sind als unterstützte Betriebssysteme nur Windows und macOS aufgeführt.
- Andererseits nennen die Hinweise zu Sicherheitsschlüsseln auch Linux und Firefox als unterstützt.
- Unmittelbar bevor das Formular für den Bestätigungscode erscheint, wird eine Verbindung zu
- In den folgenden sechs Umgebungskombinationen trat überall derselbe Fehler auf.
- Firefox, Chromium und Chrome unter Linux
- Firefox, Safari und Chrome unter macOS
- Auf dem Arbeitslaptop sprang der Fokus nach der Eingabe automatisch ins nächste Feld, und auch die Fehlermeldung
Code entered is incorrectfür einen falschen statt leeren Code erschien korrekt. - Auch auf dem macOS-Computer eines Freundes akzeptierten alle drei Browser den Bestätigungscode.
- Für eine langfristige Interaktion mit Behördendiensten konnte man sich nicht auf einen vom Arbeitgeber bereitgestellten Computer verlassen; selbst wenn die Registrierung auf dem Arbeitsgerät möglich war, blieb das Risiko, sich auf dem privaten Laptop später nicht einloggen zu können.
Support-Struktur blockierte sogar die Fehlermeldung
- Der offizielle Support war nur über ein Webformular erreichbar, und auch dort musste zuerst der E-Mail-Bestätigungscode eingegeben werden.
- In den FAQ steht, dass Support der teilnehmenden Stellen während der Geschäftszeiten nur über das Erstellen eines Online-Tickets angeboten wird.
- Abgesehen von der Postadresse der Swiss Federal Chancellery gab es weder E-Mail-Adresse noch Telefonnummer.
- Auch die Feedback-Funktion für Lob, Kritik oder Anfragen zu AGOV verlangte einen Login mit AGOV oder einem gleichwertigen Konto.
- Nutzer, bei denen die E-Mail-Bestätigung scheiterte, gerieten wegen derselben Authentifizierung in eine zirkuläre Abhängigkeit und konnten das Problem nicht einmal melden.
-
AGOV Access und unterstützte Geräte
- Die AGOV Access Android-App hatte eine Bewertung von 1,4 Sternen, doch in den Google-Play-Reviews ließ sich derselbe Bestätigungscode-Fehler nicht finden.
- In den Bewertungen gab es viele Wünsche nach Unterstützung für das sicherheits- und datenschutzorientierte Android-Derivat GrapheneOS.
- Laut den offiziellen FAQ funktioniert die App nicht mit GrapheneOS, weil ein Härtungs-Framework zum Schutz vor unbefugten Änderungen damit nicht kompatibel ist.
- Die Federal Chancellery habe den Anbieter angewiesen, Kompatibilität sicherzustellen.
- Aktuell sind als zweiter Faktor für Registrierung und Login nur zugelassene Standard-iOS-/Android-Smartphones oder Sicherheitsschlüssel erlaubt; in beiden Fällen muss zuvor die E-Mail-Bestätigung erfolgreich durchlaufen werden.
Die Ursache im JavaScript gefunden
- Die von der Seite geladenen Ressourcen waren zwar überschaubar, doch die nicht obfuskierte, nur minimierte Haupt-JavaScript-Datei war 2,4 MB groß und umfasste ausgeschrieben über 100.000 Zeilen.
- Durch Suche nach dem String
field requiredließ sich die Logik finden, die den Status des Bestätigungscodes setzt.- Wenn keine Variable für den Bestätigungscode vorhanden ist, wird der Status auf
REQUIREDgesetzt. - Stimmt die Länge nicht mit der geforderten Codelänge überein, wird
WRONGverwendet. - Bei passender Länge wird je nach Ergebnis der serverseitigen E-Mail-Bestätigung
VALIDoder ein Fehlerstatus gesetzt.
- Wenn keine Variable für den Bestätigungscode vorhanden ist, wird der Status auf
- Die Funktion
verificationCodeEnteredfängt Tasteneingaben ab und sammelt den Bestätigungscode in einer JavaScript-Variable.Enterführt den Bestätigungs-Callback aus.Backspacelöscht den aktuellen Wert.- Pfeiltasten und
Tabbewegen den Fokus zwischen den Eingabefeldern. - Normale Tasten werden mit
Number(S.key)in Zahlen umgewandelt und anschließend im Code gespeichert. - Tasten wie
Control,Meta,Shift,v,rusw. werden nicht verarbeitet, sondern führen zu einer Rückgabe.
- Da beim Absenden des Formulars keine DOM-Werte gelesen werden, spiegeln Änderungen an den Eingabefeldern per Entwicklerwerkzeugen oder Browser-Erweiterungen sich nicht im separat verwalteten JavaScript-Zustand wider.
Warum auf AZERTY nur Zahlen blockiert waren
- Beim französischen Standard-AZERTY-Layout ist für die Eingabe von Ziffern die Shift-Taste erforderlich.
- Weil der Code Shift-Eingaben ignorierte, konnten auf AZERTY die Ziffern selbst nicht als Bestätigungscode gespeichert werden.
- Der Arbeitscomputer verwendete ein englisches QWERTY-Layout, und unter den Personen, die beim Testen halfen, war niemand Franzose.
- Dadurch sah es so aus, als seien unter den getesteten Geräten nur zwei private Laptops defekt.
- Nachdem das Tastaturlayout im Betriebssystem auf ein anderes Layout umgestellt wurde, funktionierte die Eingabe auch auf den privaten Laptops normal.
- Umgekehrt ließ sich derselbe Fehler reproduzieren, wenn ein zuvor funktionierendes Gerät auf das französische Layout umgestellt wurde.
- Das in der Schweiz übliche französischsprachige Standard-Keyboard gehört zur in Mitteleuropa verbreiteten QWERTZ-Familie.
- Es erlaubt effizientes Tippen auf Französisch und Deutsch, und für Ziffern ist kein Shift nötig, sodass derselbe Fehler dort nicht auftritt.
- Laut dem Swiss Federal Statistical Office leben in der Schweiz rund 171.000 Personen mit französischer Staatsangehörigkeit; Grenzgänger, die mit der Schweizer Regierung interagieren müssen, sind darin nicht enthalten.
Grenzen der Untersuchung bis zur Offenlegung des Quellcodes
- Laut AGOV-FAQ soll der AGOV-Quellcode zur Erfüllung gesetzlicher Vorgaben im Dezember 2026 veröffentlicht werden.
- Artikel 9 EMBAG verlangt, dass Bundesstellen den Quellcode von Software offenlegen, die sie zur Erfüllung ihrer Aufgaben selbst entwickelt oder entwickeln lassen.
- Ausnahmen gelten, wenn Rechte Dritter oder Sicherheitsgründe die Veröffentlichung verhindern oder einschränken.
- Veröffentlicht werden sollen die AGOV-Versionen, die die Projektziele erreicht haben, einschließlich AGOV e-ID Verifier; spätere Versionen sollen mit nach dem Release vorbereiteten Release Notes veröffentlicht werden.
- Obwohl einige Dienste AGOV bereits als Pflicht-Login verwenden, war der Quellcode noch nicht öffentlich, weshalb Nutzer Bugs weder direkt an Entwickler melden noch Workarounds leicht teilen konnten.
Nach der Registrierung überprüfter Umfang der Identitätsprüfung
- Nach dem Wechsel des Tastaturlayouts wurde die E-Mail-Adresse bestätigt und die Registrierung mit einem Sicherheitsschlüssel abgeschlossen.
- Während der Registrierung wurden Name, Telefonnummer und Geburtsdatum eingegeben, diese Angaben wurden jedoch nicht verifiziert.
- In der grundlegenden Registrierungsphase wurden nur zwei Dinge geprüft.
- Dass die E-Mail-Adresse tatsächlich existiert
- Dass der zweite Faktor entweder ein zugelassenes Modell eines Sicherheitsschlüssels ist oder die AGOV-Access-App auf einem zugelassenen Android- oder iOS-Gerät ausgeführt wird
- AGOV ist robust gegen Kontoübernahmen durch Remote-Phishing, verhindert aber in der Basiseinschreibung nicht, dass jemand mit dem Namen und den Identitätsdaten einer anderen Person ein Konto anlegt.
- Weitere Prüfung ergab, dass für als sensibel eingestufte Dienste eine Identitätsprüfung erforderlich ist.
- Unmittelbar nach der Registrierung war auf solche Dienste noch nicht zugegriffen worden.
- Der Bug wurde über das Support-Formular gemeldet, eine Antwort blieb jedoch aus.
Lehren aus dem Design
-
Fragiles Eingabe- und Support-Design
- Eine auffällige UI mit sechs Eingabefeldern und komplexer JavaScript-Logik ist nicht robust.
- Besser wäre ein einziges natives Browser-Eingabefeld, dessen visuelle Form nur per CSS gestaltet wird.
- Wenn Formularlogik vollständig vom DOM getrennt wird, lassen sich beim Absenden keine DOM-Werte lesen, und selbst fortgeschrittene Nutzer oder Browser-Erweiterungen können Eingaben nicht korrigieren.
- Gibt es nur einen Support-Kanal, verschwindet bei einer Störung dieses Kanals auch jede Kontaktmöglichkeit; deshalb braucht es einen zweiten Kanal wie E-Mail oder Telefon.
- Wenn Produkt und Support-Kanal dieselbe Login-Logik verwenden, gehen Bugmeldungen von Nutzern verloren, die sich gar nicht einloggen können.
- Viele Internetdienste betreiben aus demselben Grund Statusseiten auf einer separaten Domain.
- Wenn Support-Anfragen erst nach E-Mail-Bestätigung möglich sind, reduziert das zwar Spam, aber auch echte Störungsmeldungen realer Nutzer.
- Wird Quellcode erst veröffentlicht, nachdem manche Systeme die Nutzung bereits verpflichtend gemacht haben, sind Problemlösung durch Nutzer sowie das Teilen von Bugs und Workarounds eingeschränkt.
- Gesetzlich vorgeschriebene Quelloffenlegung ist nicht nur ein Compliance-Punkt, sondern auch für die Untersuchung realer Störungen nützlich.
-
Das offene Web half bei der Untersuchung
- Da die relevante JavaScript-Logik nicht obfuskiert war, ließ sich die Ursache schon mit einigen String-Suchen finden.
- Weder ein fortgeschrittener Decompiler noch ein teures LLM waren nötig.
- Wäre der Code obfuskiert oder nach WebAssembly kompiliert gewesen, hätte die Ursachenanalyse deutlich mehr Zeit gekostet.
- Der Code wurde nicht nur für genehmigte geschlossene Betriebssysteme ausgeliefert, sondern über das offene Web, sodass er zumindest in minimierter Form heruntergeladen und untersucht werden konnte.
-
Bedingungen, die die Ursachenermittlung ermöglichten
- Durch den Vergleich mehrerer Laptops mit unterschiedlichen Tastaturlayouts ließ sich die Wahrscheinlichkeit eines browser- oder netzwerkspezifischen Problems früh senken.
- Allerdings kostete die systematische Erfassung der Bildschirme für jede Browser-Kombination zunächst Zeit, um auszuschließen, dass es sich um einen Bedienfehler handelte.
1 Kommentare
Lobste.rs-Kommentare
Eine der Praktiken, die ich im Internet besonders hasse, ist, wenn Websites Tastatureingaben abfangen und eigenmächtig verarbeiten, statt sie einfach an den Browser durchzureichen
Websites, die Kopieren und Einfügen in Passwortfeldern verbieten, sind viel häufiger, aber das gehört in dieselbe Kategorie und wirkt vielleicht sogar noch schlimmer
Meist erhöht das die Komplexität nur aus fadenscheinigen Gründen
Ein Eingabefeld pro Zeichen ist wie eine Seuche
Irgendein Unternehmen hat das eingeführt, weil es schick aussah, und jetzt baut jeder seine eigene Version davon
Nutzer erkennen sofort, dass es sich nicht um ein Passwortfeld handelt, auch ohne den Text genau zu lesen
Ein verwandtes Beispiel: Medium once had a bug like this which prevented entering the character 'Ś'
Ich habe über andere Implementierungen nachgedacht, bin aber am Ende auf keine bessere Lösung als ein gewöhnliches
<input type="text" />gekommenSelbst bei CSS-Dekorationen, die es zu anders als ein normales Eingabefeld aussehen lassen, zögere ich. Man könnte den eingegebenen Wert in große Kästchen gespiegelt anzeigen, aber dann muss man alle möglichen Probleme lösen, etwa was passiert, wenn der Nutzer mehr als die erlaubte Länge eingibt, und der Nutzen ist den Aufwand nicht wirklich wert. Höchstens Schriftart und Größe des Eingabefelds würde ich ändern
1224statt1234Die schnellste Korrektur ist, auf die zweite
2zu klicken und3zu drücken, aber das lässt sich mit reinem HTML+CSS nicht umsetzen<input type="text" pattern="[0-9]+" minlength=6 maxlength=6>einen ungewöhnlichen Zeichenabstand geben könnte, damit es optisch wie sechs Kästchen aussiehtDer einfachere Weg wäre, dass der Nutzer in ein einzelnes Textfeld eingibt und JavaScript an einer anderen Stelle im DOM sechs Kästchen zeichnet, die dann über das bei jedem Tastendruck ausgelöste
input-Event aktualisiert werdenWelche Variante für die Barrierefreiheit besser wäre, ist schwer zu sagen. Aus Sicht von Screenreadern könnte Letzteres mit einem normalen
<input>plus dekorativem<canvas alt="">sogar besser sein, und auch die Tastaturbedienung würde nicht seltsam werden. Aber für Nutzer, die andere Hilfsmittel als Screenreader verwenden, kann ein visuell verstecktes<input>eine Katastrophe für die Barrierefreiheit sein, daher wäre ich damit sehr vorsichtigWie viele Dienste könnte man in der E-Mail den Code zusammen mit einem Aktivierungslink bereitstellen
Auch das könnte dasselbe Problem lösen
Man könnte das für eine Ausnahmesituation halten, aber genau darum geht es bei Barrierefreiheit: auch mit solchen Ausnahmen richtig umzugehen
Tridactyl hat genau dasselbe Problem: https://github.com/tridactyl/tridactyl/issues/3257
Es wurde erstmals 2019 gemeldet; vielleicht führt dieser Vorfall immerhin dazu, dass man es aus Scham endlich behebt
Das zeigt erneut, dass es viel mehr Aufwand kostet, kaputte oder langsame Websites zu bauen als Websites, die einfach funktionieren