Security für die SPS-Programmierung
Secure Coding Practices gab es bislang nur für IT. Das Top 20 Secure PLC Coding-Projekt ändert das
Können wir anfangen, PLC-Eigenheiten als Features, nicht als Bugs für Security zu begreifen?
So dringend brauchen SPSen keine Security in der Programmierung, oder? Und selbst wenn — SPSen wären doch gar nicht in der Lage, Security umzusetzen? Überhaupt, zählt SPSen Programmieren eigentlich als Programmieren?
“Niemand lernt sichere SPS-Programmierung in seiner Ausbildung”, hat Jake Brodsky während des S4x20-Vortrag bemerkt, der die Initialzündung zum Top 20 Secure PLC Coding Practices Project gegeben hat, das Jake Brodsky, Dale Peterson und ich begonnen haben. Es wird von der ISA Global Cybersecurity Alliance gehostet und ist seit heute öffentlich verfügbar.
Dieser Text ist eine Einführung in das Projekt und seine Hintergründe und enthält auch eine deutsche Übersetzung der ersten Top 20-Entwurfsversion.
Für die Ungeduldigen, die statt langen Einführungen lieber direkt ins Projekt einsteigen wollen: https://top20.isa.org ist der Link zur Projektplattform.
Zählt SPS-Programmieren eigentlich als Programmieren?
Ich kann nicht mehr zählen, wie oft ich in dieser Diskussion gelandet bin. Es reicht schon, die ISO/IEC 27001-Controls mit einem OT-Team durchzugehen; unweigerlich landet man irgendwann bei Anforderungen zur sicheren Entwicklung.
“Entwickeln Sie irgendetwas selbst?”
— “Nee.”
“Keine eigene Software-Entwicklung? Programmieren Sie irgendetwas?”
— “Nein, nichts. Also, wir programmieren SPSen. Zählt das auch?”
Ja, da wären wir: Zählt SPS-Programmieren als Programmieren?
Üblicherweise besteht die Antwort aus so etwas wie “ja, gewissermaßen, aber…”. Gewissermaßen, aber es ist anders als “normales” Programmieren. Zum Beispiel nutzt es keine konventionelle Programmiersprache.
Das klingt ein wenig nach Haarspalterei wenn man bedenkt, dass das Wort SPS, kurz für “Speicherprogrammierbare Steuerung”, sogar “programmierbar” im Namen trägt. Aber wir müssen berücksichtigen, in welchem Kontext “programmierbar” hier steht, nämlich “speicherprogrammierbar”. Das klingt nach einem seltsamen Feature, denn wohin soll man denn sonst programmieren, wenn nicht in den Speicher?
Das wird klar, wenn man die Geräte anschaut, von der sich die “speicherprogrammierbaren” Steuerungen abgrenzen sollten: Verbindungsprogrammierte Steuerungen. Es gab also durchaus eine andere Möglichkeit: Programmieren durch Verkabeln. Die Steuerungslogik wurde als im Wortsinn “hartverdrahtet” durch das gezielte Verbinden elektronischer Relais, und SPSen werden immer noch mit dieser Denkweise im Hinterkopf programmiert.
Einer der Väter der heutiger SPSen, Modicons Richard E. Morley, hat angeblich sogar dagegen opponiert, SPSen als “Computer” zu bezeichnen, weil er fürchtete, dass das die Akzeptanz der Geräte unter Automatisierern gefährden könnte.
“Normales” Programmieren und SPS-Programmieren sind wie bei der Geburt getrennte Zwillinge, die unterschiedlich aufgewachsen sind und deswegen komplett verschiedene Erwachsene geworden sind. Wir können nicht annehmen, dass was für den einen Zwilling funktioniert, für den anderen genauso funktionieren wird.
“Normales” Programmieren ist in einer vernetzten Welt groß geworden, deswegen wurde Security schon früh ein Thema. Deswegen lernt jeder Software Engineer Secure Coding Practices in seiner Ausbildung, genauso selbstverständlich wie eine Programmiersprache, die effiziente Nutzung der Hardwareressouren oder brauchbare Code-Dokumentation.
SPS-Programmieren hatte andere Prioritäten. SPSen mussten, vor allem anderen, verlässlich Echtzeitoperationen garantieren. Bis vor ein paar Jahren waren sie daher nicht mit viel mehr verbunden (und schon gar nicht per Netzwerk) als mit ihren Ein- und Ausgängen, benachbarten Steuerungen und vielleicht einem Leitsystem.
Dies ist kein Text über die Unterschiede zwischen IT und OT (den finden Sie hier).
Für unser Thema reicht es, das hier im Hinterkopf zu behalten: Während normale Programme hauptsächlich Daten bewegen, die man nicht sehen und anfassen kann (und deswegen gern mit “Bits und Bytes” oder “Einsen und Nullen” beschreibt), bewegen SPS-Programme sehr sichtbare und berührbare Dinge — Ventile, Tore oder Flüssigkeiten zum Beispiel.
Und: Wir können nicht einfach annehmen, dass was für der Security “normaler” Software zuträglich ist, analog für SPS-Programme funktioniert.
Ausreden, um Secure Coding Practices nicht für SPS-Programmierung zu verwenden
Es gibt also eine Reihe von Gründen, warum Secure Coding Practices für SPSen nicht besonders weit verbreitet sind. Einer ist, dass sich die Idee leicht auf Basis zweier häufig genannter falscher Annahmen wegschieben lässt:
Falsche Annahme: SPSen brauchen keine Secure Coding Practices
Beispiel Input-Validierung: Wichtig, um nicht definierte Programmzustände und die Eingabe von ausführbaren Code zu verhindern. Aber SPS-Inputs sind Messwerte aus einem physischen Prozess, also können sie nur natürliche Werte annehmen, richtig?
Offensichtlich funktioniert die Annahme schon dann nicht mehr, wenn wir manipulierte Messwerte annehmen müssen. Aber das ist nur die halbe Wahrheit, denn es sind ja auch nicht alle Inputs Messwerte. Was ist mit Sollwerten, Zählern Zeiten?
Falsche Annahme: Secure Coding Practices sind auf SPSen technisch nicht umsetzbar
Die etablierten Secure Coding Practices sind nicht für SPSen geschrieben worden. In dieser Annahme kann also Wahrheit stecken: einige der Praktiken sind in der Tat nicht einfach auf SPSen übertragbar.
Beispiel Integritätsprüfungen: In IT-Systemen wird die Integrität oft mittels kryptografischen Mechanism, Prüfsummen oder Hashes, überprüft. Das liefert eine einfache Ausrede: Meine SPS hat nicht genug Ressourcen für kryptografische Algorithmen.
Selbst, wenn das stimmt: Das bedeutet nicht, dass Integritätsprüfungen unmöglich sind.
SPS-Eigenheiten als Feature, nicht als Bug für die sichere Programmierung verstehen
Wie so oft im OT-Security-Engineering, ist auch für die sichere SPS-Programmierung der entscheidene Schritt, die OT-Eigenheiten und Unterschiede zur IT nicht als Hindernis zu verstehen, das man umgehen muss, sondern als Chance, die nutzbar ist. Oder, wie der Programmierer sagen würde: Die SPS-Eigenheiten als Feature nutzen, nicht als Bug verstehen. Für SPSen sind dieselben Security-Anforderungen wichtig wie für die meisten IT-Komponenten — der Unterschied besteht darin, wie sie umgesetzt werden.
Bleiben wir noch einen Moment bei der Security-Anforderung, die Integrität von Code und Daten zu überprüfen: Tatsächlich sind Prüfsummen oder Hashes nicht unbedingt die beste Idee für Integritätsprüfungen auf SPSen, weil sie zu viele zusätzliche Ressourcen verbrauchen.
Aber die SPS bringt dafür ja andere Eigenheiten mit, die wir nutzen könenn, um auf Integritätsverletzungen aufmerksam zu machen:
- Sie regelt einen physischen Prozess
- Sie arbeitet deterministisch (d.h. liefert bei gleichen Eingangsgrößen immer die gleichen Ausgangsgrößen)
Schon diese zwei grundlegenden Eigenheiten bieten überraschend viele Optionen für Security.
Beispiel?
Zuerst zum Determinismus: Weil SPSen, um Echtzeit garantieren zu können, mit einem determinstischen Scan-Zyklus arbeiten, sollten Zykluszeiten zeitlich konstant bleiben. Eine plötzliche Änderung ist deswegen ein Indikator für eine Änderung in SPS-Logik, Netzwerkumgebung oder gesteuertem Prozess, weshalb Nummer 13 auf unserer aktuellen Top 20-Liste lautet wie folgt:
13. SPS-Zykluszeiten zusammenfassen und ihre Entwicklung auf dem HMI anzeigen
Genauso wie die Determiniertheit kann auch die Tatsache, dass an SPSen ein physischer Prozess hängt, für Security nutzbar gemacht werden. Wissen über den physischen Prozess eröffnet Möglichkeiten für die Input-Validierung, die auf einem “normalen”, nur Daten verarbeitenden Computer, nicht möglich wären: Zum Beispiel kann die physisch notwendige Dauer einer Aktion berücksichtigt werden. Wenn ein Tor physisch mindestens eine Minute braucht, um vom vollständig geöffneten zum vollständig geschlossenen Zustand zu wechseln, aber nun nach fünf Sekunden schon Vollzug meldet: Was sagt Ihnen das?
In diesem Kontext stehen die Nummern 1 und 4 auf unserer aktuellen Top 20-Liste:
1. Mit der Instrumentierung Plausibilitätsprüfungen ermöglichen
4. Eingänge basierend auf physikalischer Plausibilität validieren
Eine andere, vielleicht unerwartete Empfehlung auf der Liste kombiniert beide genannten SPS-Eigenheiten, physische Prozesssteuerung und Determisimus: Der I/O-Energieverbrauch kann für Überprüfungen der physischen Integrität verwendet werden.
Wie das?
Wenn Sie alle 4–20 mA-Stromschleifen aufaddieren und dabei ihre aktuellen Zustände und die Anzahl der digitalen I/O-Endgeräte berücksichtigen — beides kennt die SPS — sollte dies dem Gesamt-I/O-Energieverbrauch entsprechen. Eine Abweichung kann darauf hinweisen, dass ein neues Feldgerät mit der SPS verbunden oder die Kabelführung geändert wurde. Beides kann Security-relevant sein (außer, Sie wissen von einer geplanten Änderung).
Entsprechend finde sich die Empfehlung Nummer 16 auf der aktuellen Top20-Liste:
16. Energieverbrauch für alle Ein- und Ausgänge in der SPS aufaddieren
Grundstruktur des Projekts: Es geht nicht nur um Security
Nun, da Sie die Hintergründe kennen und auch schon Beispiele aus dem Entwurf der Top20-Liste gesehen haben, ein paar Worte zum aktuellen Projektaufbau.
Wir haben momentan eine Top 17-Liste von Secure PLC Coding Practices, und ungefähr dreißig weitere Kandidaten für Empfehlungen, die auf der Liste landen könnten, wenn sie besser beschrieben sind.
Jede Empfehlung (“Practice”) auf der Liste hat einen Titel, eine Kurzbeschreibung und eine dreistellige eindeutige ID. Bei Klick auf die ID gelangen Sie zu detaillierteren Informationen.
Neben Titel und Kurzbeschreibung gibt es dort auch noch
- Guidance: Umsetzungshinweise oder Hintergrundwissen
- Examples: Beispiele für die Umsetzung oder für die Probleme, die die Empfehlung vermeidet
- Why?: Gründe, warum die Umsetzung der Empfehlung sinnvoll ist.
Für mich ist das “Why” der wichtigste Absatz — nicht nur, weil er die Motivation hinter den einzelnen Empfehlungen erklärt und damit hoffentlich akzeptanzsteigernd wirkt, sondern auch weil er den Mythos von der Unvereinbarkeit von Security und Nutzerfreundlichkeit widerlegt.
Natürlich dient jede der Empfehlungen der Security, aber die meisten sind auch anderen Zielen zuträglich. Wo zutreffend, listen wir daher Vorzüge der Empfehlungen auf für
- Security
- Realiability / resilience
(Zuverlässigkeit / Resilienz) - Adaptability / agility / maintainabiltiy
(Anpassungsfähigkeit / Agilität / Wartbarkeit) - Sustainability
(Nachhaltigkeit)
Security kostet nur Geld und trägt nicht zum Umsatz bei? Mindestens für SPS-Security lohnt es sich, diesen Gemeinplatz zu hinterfragen.
Secure PLC Coding Practices: Der erste Entwurf der Top 20-Liste
Genug des Vorgeplänkels, Butter bei die Fische: Hier ist die deutsche Übersetzung der aktuellen Secure Coding-Practices-Liste, die bislang 17 Einträge enthält.
Dies kann nur eine Momentaufnahme sein — der aktuelle Stand sowie alle Diskussionsbeiträge befinden sich auf der Projektplattform. Sobald die Version in die Nähe einer “v1.0” kommt, wird sie auch als eigenständige Publikation veröffentlicht.
1. Mit der Instrumentierung Plausibilitätsprüfungen ermöglichen [ID 001]
Die Prozessinstrumentierung sollte so ausgelegt sein, dass sie Plausibilitätsprüfungen ermöglichst; zum Beispiel durch Gegenprüfung verschiedener Messungen.
2. Direkte I/O-Schreibvorgänge unterbinden [ID 205]
Alle direkten Schreibvorgänge von Ein- und Ausgängen in die SPS sollten unterbunden werden — idealerweise von einer Firewall, die auf Basis von Protokollinformationen filtern kann (Deep packet inspection).
3. Dedizierte Registerblöcke als Puffer für die Validierung aller Schreibvorgänge definieren [ID 218]
Dedizierte Registerblöcke der SPS sollten als Puffer reserviert werden. Alle in Schreibvorgängen gesetzten Werte für Ein-/Ausgänge, Zeiten und Zähler sollten dort validiert werden, bevor die SPS die Werte verarbeitet.
4. Eingänge basierend auf physikalischer Plausibilität validieren [ID 216]
Es sollte ein Timer für die Dauer gesetzt werden, die eine Aktion physikalisch benötigt. Abweichungen von der erwarteten Dauer sollten einen Alarm auslösen.
5. Timer und Zähler validieren [ID 207]
Wenn Ausgänge, Zähler und Zeiten für den Timer direkt in das SPS-Programm geschrieben werden, sollten sie durch die SPS hinsichtlich Angemessenheit und Rückwärtszählen auf negative Werten validiert werden.
6. Validieren und Alarmieren von paarweisen Eingängen [ID 206]
Bei paarweisen Eingängen (z.B. START/STOP) sollte sichergestellt werden, dass nicht beide Eingänge gleichzeitig gesetzt werden. Wenn solche physikalisch nicht realisierbaren Eingangszustände sich einstellen, sollte ein Operator alarmiert werden.
7. Validieren von indirekten Adressierungen [ID 204]
Indirekte Adressierungen sollten validiert werden. Dies sorgt auch dafür, dass Zaunpfahlfehler auffallen.
8. SPS-Flags zur Integritätsprüfungen verwenden [ID 213]
Auf alle Flags, insbesondere für das Teilen durch Null, sollten Zähler gesetzt werden, damit Logikfehler auffallen.
9. Dedizierte Registerblöcke für das HMI definieren [ID 303]
Das HMI sollte nur in dedizierte SPS-Registerblöcke schreiben dürfen, um Netzwerkverkehr und -latenzzeiten zu reduzieren. Um das Lesen effizient zu machen, sollte außerdem Register-Array für das Lesen vom HMI reserviert werden.
10. Berechnungen direkt in der SPS machen [ID 209]
So viele Berechnungen (z.B. Summieren oder Integrieren) wie möglich sollten direkt in der SPS durchgeführt werden. Das HMI bekommt nicht genug Aktualisierungen, um dafür eine geeignete Datenbasis zu haben.
11. Betriebsmodi überwachen [ID 214]
Die SPS sollte wann immer möglich im RUN-Modus bleiben. Wenn sie es nicht ist, sollte der Operator alarmiert werden.
12. Zähler für SPS-Kommunikation bündeln und Verlauf auf dem HMI darstellen [ID 210]
Zähler für gesehene, empfangene und gesendete Datenpakete für jedes SPS-Interface über eine frei wählbare Zeitspanne sollten direkt in der SPS zusammengefasst und zu Überwachungszwecken an das HMI gesendet werden.
13. SPS-Zykluszeiten bündeln und Verlauf auf dem HMI darstellen [ID 211]
Die SPS-Zykluszeiten sollten alle 2–3 Sekunden gebündelt und dem HMI zur Verfügung gestellt werden, um den Verlauf als Graph zu visualisieren.
14. Uptime der SPS protokollieren und auf dem HMI verfügbar machen [ID 215]
Die Uptime der SPS sollte protokolliert werden, um Informationen über Neustarts zu bekommen und auch im Nachhinein nachvollziehen zu können. Die Werte sollten auf dem HMI zu Diagnostikzwecken verfügbar sein.
15. (Not-)abschaltungen der SPS protokollieren und auf dem HMI verfügbar machen [ID 208]
SPS-Ereignisse von Fehlern oder Abschaltungen sollten in der SPS gespeichert und dem HMI verfügbar gemacht werden, damit sie konsultiert werden können, bevor die SPS neugestartet wird. Zeitsynchronisation ist dabei wichtig, um die Daten mit anderen Ereignissen korrelieren zu können.
16. Energieverbrauch für alle Ein- und Ausgänge in der SPS aufsummieren [ID 105]
Der aufsummierte Energieverbrauch aller Ein- und Ausgänge kann als physische Integritätsprüfung dienen, um Änderungen in Ein-/Ausgängen, Feldgeräten und Verkabelung zu bemerken.
…
[Die Kandidaten für 17.-19. sind noch zu definieren]
…
20. Das zu erwartende Verhalten in einem Control System Narrative dokumentieren [ID 907]
Das zu erwartende Verhalten der SPS — inklusive der Secure Coding Practices und der Diagnostikmöglichkeiten— sollten im Control System Narrative beschrieben sein. Es kann damit die zentrale Referenz sein, um den SPS-Code gemäß Secure Coding Practices zu schreiben und Anomalien zu identizifieren.
Und nun?
Das Hauptziel für die nächsten Monate wird sein, die vorhanden Empfehlungen auf der Liste zu verbessern sowie neue hinzuzufügen.
Außerdem werden wir darüber nachdenken, wie wir die Liste (und die Details zu den einzelnen Einträgen) am besten organisieren, damit sie zur Denkweise von SPS-Programmierern uund / oder Security-Experten passt — und vielleicht zusätzliche Perspektiven einbauen, die helfen, Kernsaspekte für Managementpositionen zu erklären.
Es ist außerdem angedacht, Querverweise auf bestehende Ressourcen einzubauen oder sogar direkt an Bestehendes anzuknüpfen, zum Beispiel
- Secure Coding Practices für IT (z.B. OWASP, Carnegie Mellon University, CWE, Microsoft)
- Bestehende SPS-Programmierleitlinien wie in IEC 61131, PLCopen (danke, Anton!), ASME NQA-1, or IEEE 7–4.3.2 (danke, Agustin!)
- Allgemeine ICS / OT Security-Standards und -Frameworks wie ICS ATT&CK oder ISA/IEC 62443
Wir planen auch, schrittweise mehr Hintergrundinformationen zu SPS-Eigenheiten bereitzustellen, um die Secure Coding Empfehlungen im Allgemeinen und das “Warum” im Besonderen besser erklären zu können. Das können Modelle und Erklärungen für verschiedene Aspekte wie Verkabelung, Hardware, Software oder den SPS-Scanzyklus sein — prinzipiell ähnlich zum untenstehenden Modell:
Mischen Sie sich ein!
Das Projekt Security in der SPS-Programmierung soll eine Ressource werden, die SPS-Programmierern bei ihrer täglichen Arbeit hilft. Damit das klappt, brauchen wir Input von möglichst vielen Praktikern.
Zusammen können wir aus den Secure PLC Coding Practices Grundlagenwissen machen, so wie es Secure Coding Practices für die IT bereits sind.
Lassen Sie uns aufhören, SPS-Programmieren als eine seltsame Variation von “normalen” Programmieren zu betrachten, die halt nicht mit Security vereinbar ist. Lassen Sie uns stattdessen zeigen, dass Security in der SPS-Programmierung machbar ist, wenn wir SPS-Eigenheiten wie Determinismus und Steuerung eines physischen Prozess als Features statt Bugs für sicheres Programmieren verstehen.
Das Projekt “Top 20 Secure PLC Programming Practices” ist erreichbar unter https://top20.isa.org — gehostet von der ISA Global Cybersecurity Alliance.
Ab heute kann sich jeder registrieren, kommentieren und eigene Ideen beitragen.