blog.dbrgn.ch

Die Qualität des Schweizer E-Voting-Programmcodes

written on Friday, February 22, 2019 by

Dieser Blogpost versucht, die aktuelle Kritik am E-Voting-System der Schweizerischen Post laienfreundlich zu erklären. Der Fokus liegt dabei auf der mangelhaften Code-Qualität des Projektes.

Auf viele weitere wichtige Punkte (Fundamentalkritik am E-Voting, Vertrauensdiskussion, usw) wird hier nicht näher eingegangen.

Etwas noch vorneweg: Das E-Voting-Moratorium möchte auf dem Initiativweg einen mindestens 5jährigen Stopp für E-Voting-Projekte erwirken, bis die Sicherheitsproblematik gelöst ist. Für die Unterschriftensammlung werden noch viele Helfer gesucht! Auf Wecollect kann man sich dafür eintragen.

Einleitung

Seit dem Jahr 2000 finden in der Schweiz E-Voting-Versuche statt. Diese Versuche liefen zu Beginn immer in einem sehr begrenzen Rahmen ab. Eine Vorreiterrolle hatte dabei der Kanton Neuenburg. Er setzte dazu eine Software des spanischen Herstellers Scytl ein. Falls dieser Name bekannt erscheint, ist das kein Zufall: Scytl ist ebenfalls der Zulieferer des aktuellen (und des letzten in der Schweiz übrigbleibenden) E-Voting-Systems der Schweizerischen Post. Ich werde an dieser Stelle nicht näher auf Scytl und ihre zweifelhafte Rolle in dieser ganzen Sache eingehen, denn das hat das Magazin "Republik" bereits sehr gut abgedeckt.

Im Jahr 2009 wurde die Berner Fachhochschule auf das Projekt aufmerksam und kritisierte es stark. Ihr Vorwurf: Bei der elektronischen Stimmabgabe kann manipuliert werden. Die Vorwürfe führten dazu, dass das Projekt vorläuftig gestoppt wurde und neue Anforderungen definiert wurden: Ein E-Voting-System muss sicher und überprüfbar sein. Die BFH engagierte sich hier auch stark, um eine Spezifikation für ein solches zumindest in der Theorie sicheres System zu entwickeln. Die resultierende Spezifikation wurde veröffentlicht und ist frei zugänglich. Vorbildlich!

Es wurden also neue, auf äusserst komplexen und relativ neuen kryptografischen Algorithmen aufbauende Systeme entwickelt. Einerseits das System des Kantons Genf, welches ab Ende 2019 aus Kostengründen aufgrund der hohen Sicherheitsanforderungen nicht mehr weiterentwickelt wird. Anderseits das von Scytl entwickelte System, welches die Schweizerische Post verkauft.

Die Spezifikation und fundierte kryptografische Algorithmen sind aber nur ein Teil des Ganzen. Die Mathematik muss auch in die Praxis – in Programmcode – umgesetzt werden. Die Erfahrung zeigt: Dies ist äussert schwierig und fehleranfällig. Praktisch jede Software hat Fehler. Bei kritischer Infrastruktur wie E-Voting-Systemen ist es absolut essentiell, dass Systeme von erfahrenen Sicherheits-Spezialisten entwickelt werden. Die Qualität und Sicherheit hat absolut oberste Priorität.

Es gibt Prozesse, die dabei helfen, höchstmögliche Qualität zu erzielen. Beispiele dafür sind Code Review, Statische Code-Analyse, Dynamische Code-Analyse, Continuous Integration und vieles mehr. Ebenfalls essentiell: Code muss so geschrieben werden, dass falsche Anwendung des Codes möglichst unmöglich wird. Das kann man unter anderem durch Programmiersprachen mit einem starken Typsystem erreichen, wie Ada, OCaml oder Rust. (Java, welches von Scytl verwendet wird, gehört nicht zu dieser Art von Programmiersprachen.)

In der Software-Industrie und der dazugehörigen Disziplin des Software-Engineering gibt es klare Best Practices, die in kritischen Situationen eingesetzt werden. Diese werden in gewissen Branchen wie der Aviatik- oder Automobilbranche auch forciert.

Offenlegungspflicht

Um das Vertrauen der Öffentlichkeit in das System zu stärken, gibt es eine spezielle Anforderung an ein Schweizer E-Voting-System: Der Quellcode muss offengelegt werden. Zitat aus der Verordnung über die elektronische Stimmabgabe (VEleS) Art. 7:

Art. 7ab

Der offengelegte Code muss nach "besten Praktiken" aufbereitet und dokumentiert werden. Eine Dokumentation zum System und dessen Betrieb muss beiliegen. "Jeder und jede" darf den Quellcode "zu ideellen Zwecken untersuchen, verändern, kompilieren und ausführen sowie dazu Studien verfassen und diese publizieren".

Die Post hat den Quellcode ihres E-Voting-Systems vor wenigen Tagen veröffentlicht. Naja, zumindest teilweise. Um auf den Quellcode zugreifen zu können, müssen zuerst ihre Bedingungen akzeptiert werden. Darin stehen ein paar problematische Dinge, auf die ich an dieser Stelle nicht eingehen werde.

Die Verordnung verlangt, dass "jeder und jede" den Quellcode untersuchen darf. Die Leute, die die Bedingungen akzeptiert haben, sind jedoch eine Untermenge von "jeder und jede". Ob dies legal ist? Ich weiss es nicht. Die Post stützt sich jedenfalls auf ihre Immaterialgüterrechte und betrachtet den Quellcode als veröffentlicht.

Unzufrieden mit den Bedingungen, veröffentlichte eine unbekannte Person den Quellcode auf gitlab.com. Dies ermöglichte allen interessierten Personen, sich den Code ohne Einschränkungen näher anzusehen.

Codequalität: Komplexität

Sarah Jamie Lewis ist Gründerin von Open Privacy und Sicherheitsforscherin mit viel Erfahrung im Auditieren von sicherheitsrelevanten Enterprise-Systemen. Zu ihren früheren Arbeitgebern gehören Amazon und der britische Geheimdienst GCHQ. Sie weiss, worauf es ankommt, wenn man sicheren Code schreiben will.

Auf den ersten Blick war sie nicht gerade begeistert vom E-Voting der Post:

Erste Kritik: Der Quellcode für das sogenannte Mixnet (welches die Zuordnung von Stimmen zu Personen trennt) ist über viele verschiedene Dateien verteilt, so dass es sowohl für Entwickler wie auch Prüfer sehr schwierig ist, den Überblick zu bewahren. Das ist sehr schlecht wenn es um Kryptografie geht, da man kryptografischen Code so einfach und übersichtlich wie möglich halten will, weil ansonsten die Wahrscheinlichkeit von Fehlern steigt.

Das gibt schon einen Hinweis auf einen ganz wichtigen Aspekt bei solchen Systemen: Sie sollten so einfach verständlich sein wie möglich! Auch Programmierer sind nur Menschen und machen Fehler. Die Fehlerwahrscheinlichkeit ist ungleich höher, wenn der Code Komplex ist.

Und komplex, das ist der Code in diesem Fall:

Gleichzeitig wurde auch Matthew Green auf den Code aufmerksam. Matthew ist Professor für Kryptografie an der renommierten John Hopkins Universität. Er forscht primär im Feld der Angewandten Kryptografie. Dabei geht es explizit darum, wie kryptografische Systeme (wie z.B. E-Voting) sicher in der Praxis umgesetzt werden können. Matthew hat einen sehr guten Ruf, hat schon dutzende wissenschaftliche Publikationen veröffentlicht und ist mit 87'000 Followern auch auf Twitter ziemlich bekannt.

Das ist seine Meinung zum Code der Post:

Sein Fazit:

Sowohl Matthew wie auch Sarah kritisieren in diesen Tweets nicht konkrete Fehler oder Sicherheitslücken. Was sie sagen ist, dass der Code nicht nach Best Practices geschrieben ist. Er ist komplex, er ist über viele verschiedene Dateien verteilt, er ist fehleranfällig. Und so komplexer Code kann kaum vollständig auditiert werden.

In der Praxis passieren die meisten Fehler nämlich nicht in den Kernalgorithmen, sondern im Zusammenspiel der verschiedenen Komponenten:

Und die Konsequenzen eines Fehlers wären fatal für das Vertrauen in die Schweizer Demokratie:

Codequalität: Defensiver Programmierstil

Beim Schreiben von sicherem Code geht es aber nicht nur um die Komplexität. Es geht auch um das Fehlerverhalten. Falls sich doch irgendwo ein Fehler enschleicht, soll dieser möglichst die negativen Auswirkungen minimieren.

Ein Beispiel: Wenn ein kryptografischer Beweis einer Stimme verifiziert werden soll, dann ist es schlimmer wenn eine ungültige oder gefälschte Stimme als gültig erklärt wird, als wenn eine gültige Stimme als ungültig erklärt wird und dann zu einer Fehlermeldung führt.

Man sollte also von der Grundannahme ausgehen, dass der Beweis ungültig ist, um anschliessend das Gegenteil zu beweisen. Scytl hat offenbar von diesem Prinzip noch nichts gehört: Die Funktion, die prüft ob ein Beweis gültig ist, geht von der Grundannahme aus, dass alles in Ordnung ist. Dies erhöht die Fehlerwahrscheinlichkeit. Sarah war nicht begeistert.

Codequalität: Automatisierte Tests

Korrekten Code zu schreiben ist herausfordernd. Noch viel herausfordernder ist es, Code zu schreiben welcher sich auch bei Veränderung oder Erweiterung des Systems immer noch korrekt verhält. In der Software-Industrie weiss man dies schon lange, deshalb verwendet man automatisierte Tests um die Grundannahmen und korrekte Funktionsweise des Systems schnell und regelmässig zu überprüfen. Typischerweise werden diese Tests automatisiert bei jeder Änderung des Programmcodes ausgeführt. Eine Änderung wird nur in das Projekt integriert, wenn diese Tests erfolgreich sind. Besonders wichtig ist dies natürlich bei allem, was Kryptografie betrifft.

Die Tests im Quellcode der Post sind lückenhaft.

Und so wie es aussieht, sind sich manchmal nichtmal die Entwickler selbst ganz sicher, ob die Tests wirklich das testen was sie testen sollten 😉 (Zeilen 72 und 73 im folgenden Screenshot.)

Codequalität: Prozesse

Jede Software-Ingenieurin und jeder Kryptografie-Experte macht mal Fehler. Das ist menschlich. Eines der effektivsten Mittel, um die Fehlerrate um 30-60% zu verringern, ist das Code Review (also das gegenseitige Gegenlesen und Prüfen von neuem Programmcode). Konsequent umgesetzte Code-Review-Prozesse verlangen, dass kein Code ins System gelangen darf, welcher nicht von einer weiteren Person mit Fachkenntnissen angeschaut und für gut befunden wurde. Code Review ist für hohe Qualität in einem sicherheitsrelevantem Umfeld unabdingbar.

Den folgenden Tweet für Laien zu erklären ist etwas schwierig, deshalb zusammengefasst: Wie es die untenstehenden Konfigurationsdateien mit nicht aufgelösten Merge-Konflikten durch einen Code-Review-Prozess geschafft haben, ist mir unerklärlich. Ausser natürlich, wenn es bei Scytl kein konsequentes Code Review gibt. Hmmmmm... 🤔

Codequalität: Analyse-Tools

Selbst bei Code-Reviews werden gewisse Probleme ab und zu übersehen. Um Software weiteren Checks zu unterziehen, gibt es daher statische Code-Analyse-Tools, welche den Quellcode untersuchen und potentielle Probleme und Fehler aufzeigen.

Ein vereinfachtes Beispiel: Ein Reisebüro programmiert ein Anmelde-Formular für eine Ferienreise. In diesem Formular ist der Name ein Pflichtfeld und der Kunde muss mindestens 18 Jahre alt sein. Das Reisebüro schreibt also zwei "Code-Schnipsel" (Funktionen), das erste prüft ob ein Textfeld nicht leer ist und das zweite prüft ob eine Jahrgangs-Zahl tiefer ist als 2001.

Nun könnte ein Flüchtigkeitsfehler passieren, so dass sowohl beim Namen wie auch bei der Jahreszahl nur geprüft wird, ob das Feld nicht leer ist. Der Code, welcher prüft ob eine Zahl kleiner als 2001 ist, ist somit ungenutzt (sogennanter "Dead Code"). Das Formular scheint auf den ersten Blick zu funktionieren, allerdings ist die Validierung subtil falsch (allerdings nur bei gewissen Eingabewerten, nämlich wenn sich eine minderjährige Person registriert). Solche Fehler sind eher schwierig zu entdecken, da auf den ersten Blick alles korrekt zu funktionieren scheint. Statische Code-Analyse kann solche Fehler aufdecken und warnt, wenn Code im Projekt enthalten ist, welcher gar nie benutzt wird.

Ungenutzter Code ist nur eines der vielen Probleme, die mit statischer Code-Analyse aufgedeckt werden kann. Wie der folgende Screenshot von Sarah zeigt, hat ein Code-Analyse-Tool beim Prüfen des E-Voting-Programmcodes 436 Warnungen generiert. Ob darunter echte Fehler stecken, weiss ich nicht. Viele Projekte haben aber Richtlinien, die besagen dass alle Warnungen entweder behandelt oder explizit deaktiviert werden müssen ("No-Warnings Policy").

Ein weiteres verbreitetes Code-Analyse-Tool prüft Code auf Abhängigkeiten zu Drittkomponenten, welche veraltet sind und Sicherheitslücken enthalten. Auch hier gab's auf Anhieb mehrere Treffer.

Ob diese Fehler in Drittkomponenten relevant sind, weiss ich nicht. Aber es ist zumindest beunruhigend, so viele potentielle Sicherheitslücken zu sehen.

Fazit

Ich hoffe, ich konnte einen kleinen Einblick in moderne Software-Entwicklungsmethoden geben. Von einer Firma wie Scytl, deren Slogan "We Power Democracy" lautet, sollte man Entwicklungsprozesse auf höchstem Sicherheitsniveau erwarten können. Solche Erwartungen wurden in den letzten Tagen aber hart auf den Boden der doch eher beängstigenden Realität zurückgeholt.

Selbst wenn beim Intrusion-Test der Post keine Sicherheitslücken gefunden werden sollten (was ich für beinahe ausgeschlossen halte), bleiben die Eindrücke der unzulänglichen Entwicklungsprozesse bestehen. Auch wenn das System den Intrusion-Test erfolgreich "bestanden" hat, ist dies kein Sicherheitsbeweis. Einen solchen wird es nie geben.

Neben der Sicherheit wurden ganz viele kritische Aspekte von E-Voting (Vertrauen, Nachvollziehbarkeit, Finanzen, Abhängigkeiten, Wahrung des Stimmgeheimnisses und vieles mehr) von diesem Post noch gar nicht abgedeckt... Was braucht es denn, um in der Schweiz eine sichere und vertrauenswürdige Demokratie zu erhalten? Gemäss Sarah könnten wir's mal mit Glück probieren:

Alternativ könnte man auch auf Wecollect das parteiübergreifende E-Voting-Moratorium unterstützen.

Danke für's Lesen!


Weiterführende Links:

Update 2019-02-25: Nach 3 weiteren Tagen der Code-Analyse hat Sarah folgendes Fazit gezogen: "lol burn it with fire" ("Haha, verbrennt es mit Feuer")



This entry was tagged evoting, politics, security and switzerland