
Proof-of-concept, der den Hardcoded-Key-Fehler von CVE-2021-22681 reproduziert und eine gerätebezogene gegenseitige TLS/CRL-Behebung über simuliertes EtherNet/IP validiert, mit IEC 62443-4-2-Zuordnung.
Sechs ausführbare Skripte — echter EtherNet/IP-Protokollverkehr (Test 1), echte TLS/PKI-Mechanik (Tests 3–6) — keinerlei Rockwell-Software oder -Lizenzierung in der gesamten Kette. Entwickelt, um eine Behauptung zu testen, bevor sie niedergeschrieben wird, nicht um sie blind zu vertreten.
Herkunft: erstellt am 31.07.2026, parallel zu einer Untersuchung der Kläranlage in Braham, MN — einer der vier öffentlich bekannt gewordenen Versorgungsunternehmen im koordinierten Vorfall im Wassersektor von Minnesota vom 26.–27. Juli 2026. Kontext zu diesem Vorfall findet sich in der CISA-Warnung AA26-097A (gemeinsam von FBI/CISA/NSA/EPA/DOE/USCYBERCOM/Finanzministerium; herausgegeben am 07.04.2026, erweitert am 22.07.2026), die die laufende, dem IRGC zugeschriebene Kampagne CyberAv3ngers abdeckt. Präzise gehaltener Zuschreibungsvorbehalt: Keine Behörde hat den Vorfall in Minnesota im Speziellen formell dieser Gruppe zugeordnet — nur die breitere, laufende Kampagne. Dieser Ordner behandelt die technische Behebungsseite und ist bewusst getrennt von der Vorfalluntersuchung gehalten.
Rockwell PSIRT ([email protected]) und RA Secure Mail ([email protected]) wurden am 31.07.2026 kontaktiert, bevor dieses Repository und der Bericht live gingen (~30 Minuten vorher, laut Dateizeitstempeln). Das Sicherheitsarchitektur-Team von Rockwell hat das Repository geprüft und am 03.08.2026 geantwortet. Direkt zitiert, nicht zu einer stärkeren Aussage umformuliert, als sie gemacht haben:
Rockwell Automation befürwortet oder validiert weder Ihre Interpretation, noch Ihre IEC-62443-4-2-Zuordnung, noch Schlussfolgerungen aus dem Proof of Concept. Bitte stellen Sie die Arbeit nicht als von Rockwell Automation geprüft, genehmigt oder befürwortet dar... die Skripte demonstrieren allgemeine kryptografische und Authentifizierungsprinzipien und nicht etwas spezifisch für CIP Security oder CVE-2021-22681.
Diese Arbeit wurde von Rockwell Automation weder geprüft, genehmigt noch befürwortet, Punkt. Ihre
technische Charakterisierung — allgemeine Prinzipien, nicht CIP-Security-spezifisch — ist dieselbe Unterscheidung,
die die Tabelle „Die harte Grenze" unten bereits über die eigenen Behauptungen dieses Repos trifft; ihre Prüfung bestätigt sie
unabhängig, anstatt sie anzufechten. Für Versorgungsunternehmen mit Hardware, die CIP Security nicht erreichen kann,
verwies Rockwell auf ihren eigenen Converged Plantwide Ethernet (CPwE) Design and Implementation Guide
(zitiert in PHASED_ROLLOUT.md Phase 1) — die bestehende Herstellerressource, zu der dieses Projekt die Leute
hinführen möchte, anstatt sie zu duplizieren.
Die Erkenntnis aus Test 1 — keine Authentifizierung im Standardzustand des Protokolls — ist nicht einzigartig für EtherNet/IP. Modbus TCP, immer noch eines der am weitesten verbreiteten Protokolle in Wasser-/Abwasser- Leitsystemen, hat in der Protokollspezifikation überhaupt kein Authentifizierungskonzept; es stammt aus der seriellen Kommunikation von 1979 und wurde nie mit Blick auf Sicherheit entwickelt. CISA hat genau dieses Versagen wiederholt in ICS-Warnungen benannt (z. B. Mitsubishi Electrics MELSEC-iQ-F-Serie: „MODBUS/TCP mangelt es an ordnungsgemäßer Authentifizierung", was unbefugtes Lesen/Schreiben/Anhalten ermöglicht). Die eigene Antwort der Modbus-Organization, Modbus/TCP Security, ist TLS-Kapselung mit X.509-Zertifikaten — strukturell dieselbe Behebungskategorie, die Test 3 hier demonstriert, standardisiert auf Ebene der Protokollorganisation statt bei einem einzelnen Hersteller. DNP3 hat eine optionale Secure-Authentication-Erweiterung (SAv5, 2012 standardisiert); unabhängige Analysen und Berichte von Implementierern beschreiben sie gleichermaßen als in der Praxis selten konfiguriert, unter Verweis auf Interoperabilitätslücken zwischen OT-Herstellern und echte Protokollkomplexität — was dieselbe Exposition hinterlässt, die Test 1 für EtherNet/IP demonstriert.
Der architektonische Punkt, präzise formuliert, damit er nicht überverkauft wird: Die Behebung aus Test 3 — gegenseitiges TLS, geräteindividuelle Identität im Zertifikat gebunden (nicht nur CA-Gültigkeit), Widerruf per CRL — arbeitet auf der Transportschicht, nicht auf dem ICS-Anwendungsprotokoll. Das Prinzip ist gleichermaßen anwendbar unter Modbus, DNP3 oder einem proprietären Protokoll; was sich ändert, ist der Wrapper, nicht die Form der Behebung. Dieses Repo hat keinen Modbus- oder DNP3-spezifischen PoC erstellt oder ausgeführt — dies ist eine architektonische Verallgemeinerung aus öffentlicher Dokumentation, gehalten an derselben „demonstriert vs. belegt"- Abstufung wie alles andere hier, keine neue getestete Behauptung.
Quellen: CISA-ICS-Warnungen zu Modbus/TCP-Authentifizierungslücken — Industrial Cyber · Modbus/TCP-Security-Überblick — Veridify · Herausforderungen bei der Einführung von DNP3 SAv5/SAv6 — Step Function I/O
Ein Offenlegungspaket steht und fällt damit, diese nicht zu vermischen, denn jeder hat eine andere Behebung:
Die hier demonstrierte Behebung — geräteindividuelle Identitätsbindung (Test 3) — adressiert den Flotten-Schlüssel-Fehler.
| Behauptung | Stufe | Warum | |
|---|---|---|---|
| Das architektonische Prinzip | „Ein einzelnes gemeinsames Geheimnis über eine Flotte wird durch einen einzigen Leak flottenweit kompromittiert; geräteindividuelle, identitätsgebundene Authentifizierung schließt das" | BEWIESEN | demonstriert mit echtem, laufendem Code einschließlich der Negativkontrolle, die beweist, dass die Prüfung notwendig ist, nicht nur, dass sie greift: an einem strengen Endpunkt wird Gerät B's echt CA-gültiges Zertifikat bei Gerät A abgelehnt aufgrund der Identität (Test 3 · Fall 3), aber an einem Endpunkt mit nur CA-Gültigkeit wird dasselbe Zertifikat akzeptiert (Fall 4 — die Kontrolle) → „allein gültig CA-signiert == flottenweiter Zugriff == Test 2 im TLS-Gewand." Die Bindung gilt auch umgekehrt: Ein betrügerischer Server, der ein gültiges Flottenzertifikat präsentiert, wird vom Client abgelehnt (Fall 5). Test 1 zeigt separat die breitere No-Auth-Basislinie. |
| Rockwells spezifische CIP-Security-Implementierung verhält sich identisch | „Das Aktivieren von CIP Security auf echter Rockwell-Hardware behebt CVE-2021-22681 genau auf diese Weise" | LEAD, belegt nicht verifiziert | dies ist die Sprache von Rockwells eigener Warnung (PN1550) — „Bei ordnungsgemäßer Bereitstellung behebt CIP Security diese Schwachstelle... verwendet keine fest verdrahteten Schlüssel" — nichts, was wir unabhängig gegen echte Logix-Hardware bestätigt haben. Wir haben das Prinzip getestet, das ihre Warnung beschreibt, nicht ihre exakte Implementierung auf Drahtebene. |
Vermischen Sie die beiden Zeilen nicht. Das Prinzip ist bewiesen. Die spezifische Implementierung des Herstellers davon ist glaubwürdig (es ist ihre eigene erklärte Designabsicht), aber von uns nicht gegen echte Ausrüstung getestet.
test1_baseline_vulnerable.py — die No-Auth-Basislinie, liveStartet einen echten EtherNet/IP-SPS-Simulator (cpppo, emuliert einen Allen-Bradley ControlLogix) und
liest + schreibt ein Steuer-Tag mit null Anmeldedaten. (Umfang: Dies ist die breite
No-Authentifizierungs-Basislinie, auf die sich die Kampagne stützte — nicht der spezifische Mechanismus mit fest verdrahtetem Schlüssel
von CVE-2021-22681. Bewusst getrennt gehalten; siehe „Drei verschiedene Fehler" oben.)
python test1_baseline_vulnerable.py
test2_shared_secret_fails.py — die Form des Flotten-Schlüssel-Fehlers (narrative Brücke, kein Test)Zwei Endpunkte halten einen statischen Schlüssel; eine Anmeldedaten von Gerät A öffnet Gerät B unverändert — das nächste strukturelle Analogon zu CVE-2021-22681s Ein-Schlüssel-für-alle-Fehler. Aber es ist tautologisch: Beide Handler sind konstruiert, um diesen Schlüssel zu akzeptieren, daher gibt es keinen Ausführungspfad, in dem es fehlschlagen kann. Es demonstriert nichts, was der Code nicht per Definition erschafft. Behalten als narrative Brücke von Test 1 zu Test 3; es trägt kein Beweisgewicht und ist bewusst kein Beweisbein.
python test2_shared_secret_fails.py
test3_mutual_tls_fix.py — die Behebung, mit ihrer Negativkontrolle und beiden RichtungenEchte CA, zwei individuell eindeutige Gerätezertifikate — Identität gebunden im SubjectAlternativeName, nicht im veralteten CommonName. Fünf Fälle, alle ausgeführt:
device-a bindet (check_hostname gegen einen echten SAN). Gegenseitig — beide Enden binden die Identität.python test3_mutual_tls_fix.py
test4_revocation.py — das Lebenszyklus-Bein: WiderrufEine echte, CA-signierte CRL. Eine Client-Anmeldedaten (engineer-1) wird gewährt; dann wird ihre Seriennummer zur
CRL hinzugefügt, und dieselbe weiterhin gültige, nicht abgelaufene, CA-signierte Anmeldedaten wird verweigert — der empirische
Gehalt der Widerrufsklausel CR 1.8 / 1.9. Eindeutigkeit (Test 3) ≠ Widerrufbarkeit; dies zeigt, dass eine
Anmeldedaten zurückgenommen werden kann.
python test4_revocation.py
test5_rotation.py — das Lebenszyklus-Bein, das Test 4 nicht schloss: RotationStellt eine Ersatz-Anmeldedaten (v2) für dieselbe Identität (engineer-1) aus, die bereits eine
gültige (v1) hält. DIE KONTROLLE (Fall 3): v1 wird erneut präsentiert, nachdem v2 existiert, aber bevor
v1 explizit zurückgezogen wird → weiterhin GEWÄHRT — was beweist, dass die Neuausstellung allein die alte
Anmeldedaten nicht zurückzieht. Erst nachdem v1 explizit zur CRL hinzugefügt wurde (Fall 4), wird sie verweigert; v2 ist
währenddessen durchgehend unbeeinflusst (Fall 5) — die Identität verliert während des Übergangs nie den Zugriff. CR 1.8s „eine Ersatz-Anmeldedaten ausstellen und die vorherige zurückziehen" sind zwei Aktionen, und dies zeigt beide, getrennt.
python test5_rotation.py
test6_tamper_injection.py — das Bein, das CR 3.1 nur als „konstruktionsbedingt" nannte: ein dedizierter IntegritätstestEin Relay auf Datensatzebene sitzt zwischen einem echten Mutual-TLS-Client und -Server und leitet TLS-Datensätze weiter, indem es
nur den 5-Byte-Header parst — es sieht nie den Klartext der verschlüsselten Nutzlast. Kontrolle: Jedes
Byte unverändert weitergeleitet → Nachricht unversehrt zugestellt. Manipulation: Ein Bit innerhalb des
Chiffrattexts eines live Application-Data-Datensatzes umgedreht → die AEAD-Prüfung des empfangenden TLS-Stacks schlägt fehl
(SSLV3_ALERT_BAD_RECORD_MAC) und die Verbindung wird abgerissen — beschädigte Daten werden nie so zugestellt, als
wären sie gültig.
Welches Byte und warum es spezifiziert ist: Ein TLS-1.2-AEAD-Datensatzkörper ist
explicit_nonce(8) ‖ ciphertext ‖ auth_tag(16), also ist Byte 0 die Nonce, nicht die Nutzlast. Das Umdrehen
der Nonce löst ebenfalls die AEAD-Prüfung aus — aber indem es die Entschlüsselung verstümmelt, nicht indem das Tag eine
veränderte Nutzlast erfasst. CR 3.1 betrifft unbefugte Modifikation übertragener Informationen, daher zielt das
Umdrehen auf ein Byte in der Mitte des Chiffrattexts, und der Test demonstriert dann genau den
Satz, den er behauptet.
python test6_tamper_injection.py
maximum_version = TLSv1_2 aus zwei Gründen, die Beobachtbarkeit betreffen, nicht
Sicherheit: Unter TLS 1.2 schlägt ein fehlendes oder abgelehntes Client-Zertifikat während des Handshakes fehl,
sodass der Test einen deterministischen, zuschreibbaren Fehler erhält statt TLS 1.3s Fehler nach dem Handshake; und
der Datensatz-Inhaltstyp bleibt im Klartext sichtbar, was Test 6s Relay benötigt, um einen
Application-Data-Datensatz überhaupt zu identifizieren. Setzen Sie die höchste TLS-Version ein, die Ihre Geräte unterstützen — TLS 1.3
wo verfügbar. Nichts in diesem Repo sollte als Ratschlag gelesen werden, ein Produktionssystem auf 1.2 zu begrenzen.presented == KEY, identity in SAN) sind nicht konstantzeit. Hier nicht ausnutzbar — die verglichenen Werte
sind halböffentliche Identitätszeichenfolgen und TLS hat bereits die eigentliche kryptografische
Authentifizierung durchgeführt, bevor der Vergleich läuft — aber gekennzeichnet, weil das Muster an Orte kopiert wird, wo es
doch darauf ankommt.python -m venv venv
venv\Scripts\activate # oder: source venv/bin/activate
pip install -r requirements.txt
62443-4-2_SL2_MAPPING.md (CR 1.2 / 1.8 / 1.9 / 1.14 / 3.1,
ehrlich abgestuft, jede Lücke benannt; CR 1.2, CR 1.9 und CR 1.8s Ausstellungs-/Validierungs-/Widerrufsbein
sind nun demonstriert). Vor PSIRT ([email protected] / [email protected]):
den normativen Text jeder CR gegen eine gekaufte Kopie von IEC 62443-4-2:2019 verifizieren.PHASED_ROLLOUT.md (Phase 0 Blutung stoppen · 1 segmentieren · 2
kompensierende Kontrollen · 3 CIP Security/PKI, hardwareabhängig · 4 betreiben). Passend zugeschnitten für ein kleines
Versorgungsunternehmen; ehrlich, dass CIP Security hardwareabhängig ist, sodass die Phasen 0–2 die Risikoreduzierung unabhängig davon tragen.PHASE0_INVENTORY_WORKSHEET.md (ein ausfüllbares Geräteinventar, nicht nur die Anweisung, eines zu
erstellen), RESOURCES.md (kostenlose CISA-/EPA-/WaterISAC-/AWWA-Unterstützung, live verifiziert, nicht aus dem Gedächtnis),
und INCIDENT_RESPONSE_QUICK_REFERENCE.md (eine Karte für die ersten 60 Minuten, ausdrücklich kein vollständiger IR-
Plan — Betriebssicherheit hat darin immer Vorrang).test5_rotation.py verschiebt CR 1.8
von „aktiviert" zu vollständig demonstriert (Rotation, mit eigener Kontrolle); test6_tamper_injection.py
verschiebt CR 3.1 von „konstruktionsbedingt" zu demonstriert (ein echtes Bit-Umdrehen, von TLS' AEAD-Prüfung abgelehnt).
Beide vor dem Hinzufügen hier wiederholt ohne Flakiness ausgeführt. Ebenfalls hinzugefügt:
PHASE3_CA_QUICKSTART.md (die CA mit „wenigen Codezeilen", als echte getestete openssl-Befehle) und ein
konkretes Allowlist-Beispiel in PHASED_ROLLOUT.md Phase 1.GLOSSARY.md, INTEGRATOR_CHECKLIST.md, PHASE3_CA_QUICKSTART.md) ist nun
tatsächlich aus dem Plan verlinkt, statt unreferenziert zu liegen. Nichts auf dieser Liste ist noch
ENTWURF — alles oben und unten ist gepusht und live im öffentlichen Repo.Jede externe Kennung hier wurde am 31.07.2026 aus einer Live-Quelle gezogen, nicht aus dem
Training erinnert: AA26-097A (mehrere Quellen, inkl. WaterISAC / Tenable / SecurityWeek), Braham als eines der
vier offengelegten Opfer, CyberAv3ngers/IRGC, PN1550 als die echte Rockwell-Warnung bestätigt mit ihrem
Zitat für Zeile 2 wörtlich geprüft („Bei ordnungsgemäßer Bereitstellung behebt CIP Security diese Schwachstelle"
ICSA-21-056-03, und 62443-4-2 CR 1.8 (PKI) + CR 3.1
(Kommunikationsintegrität) exakt bestätigt.
Disziplin für das Paket: Jede Kennung zum Zeitpunkt der Einreichung erneut aus Primärquellen abrufen.
Warnungen werden umnummeriert, erweitert und ersetzt — AA26-097A zeigt bereits eine Erweiterung — also
ist „verifiziert am 31.07.2026" nicht „verifiziert bei der Einreichung." Die vollständige formale CR-für-CR-62443-4-2-Zuordnung ist
nun geschrieben (62443-4-2_SL2_MAPPING.md) — was bleibt, ist das erneute Abrufen ihres zitierten normativen Texts gegen
eine gekaufte Normkopie vor der Einreichung, nicht das Schreiben der Zuordnung selbst.l0gic — Patrick Crosby · 31.07.2026.
Härtungsprotokoll, 03.08.2026: test5_rotation.py und test6_tamper_injection.py hinzugefügt, wodurch die
zwei seit dem 31.07.2026 als offen benannten technischen Punkte geschlossen wurden — jeweils dreimal ohne Flakiness erneut ausgeführt, bevor
sie hier festgehalten wurden. PHASE3_CA_QUICKSTART.md (echte, getestete openssl-Befehle), ein konkretes
Firewall-Allowlist-Beispiel für Phase 1, PHASE0_INVENTORY_WORKSHEET.md, RESOURCES.md,
INCIDENT_RESPONSE_QUICK_REFERENCE.md und die Modbus/DNP3-Verallgemeinerung wurden ebenfalls am selben Tag
hinzugefügt.
Härtungsprotokoll, 03.08.2026 (Fortsetzung) — zwei unabhängige Prüfdurchgänge, beide angewendet: Ein Sicherheits-
Redteam fand und behob eine echte PKI-Schwachstelle im CA-Schnellstart (-copy_extensions copyall
ließ einer bösartigen Zertifikatsanfrage erlauben, sich selbst CA:TRUE zu deklarieren; behoben über explizite -extfile, verifiziert
gegen eine absichtlich bösartige Anfrage in beide Richtungen) und korrigierte Test 6, um gezielt den Chiffrattext
umzudrehen statt Byte 0 (die Nonce), plus eine echte Thread-Sicherheits-Korrektur und Abhängigkeits-Pinning.
Eine separate strukturelle Prüfung — die Phasen als System über die Zeit lesend, nicht als Checkliste — fand
und behob: Phase 3s „wenige Zeilen"-Schlagzeile verbarg, dass Widerruf/Rotation nicht einfach sind; die CRL-
Entscheidung Fail-open/Fail-close war nie getroffen worden (jetzt ist sie es, mit einer Voreinstellung und Begründung); Zertifikatsablauf
war eine neue, unbenannte Ausfallart (Phase 4 trägt nun Test 5s eigene Lektion des sicheren Überlappens); Phase 3
blendet still Phase 2s Schreib-Alarmgeber aus (jetzt benannt, mit vorgeschlagenen Ersatz); NTP war eine
unausgesprochene Voraussetzung; CR 1.14 war als „nicht erfüllt" formuliert, wo „nicht anwendbar auf das
behobene Design" die zutreffende Aussage ist; und INTEGRATOR_CHECKLIST.md/GLOSSARY.md waren verwaiste
Dokumente, auf die nichts verlinkte (jetzt aus Phase 3 und dem Anfang dieses Plans verlinkt). Jede Korrektur verifiziert
durch erneutes Ausführen der betroffenen Tests, nicht nur durch erneutes Lesen des Diffs. Gepusht und live — alle fünf Phasen
des Einführungsplans sind fertig, zweifach geprüft, und nichts von heute liegt mehr nur lokal vor.
Härtungsprotokoll: Test 3 wurde verstärkt um die Negativkontrolle (Fall 4, beweist Notwendigkeit, nicht nur Auslösung), den Fall in umgekehrter Richtung (Fall 5, gegenseitige Bindung) und SAN-basierte Identität (nicht CN), dann durch erneutes Ausführen aller fünf Fälle neu verifiziert; Test 4 (CRL-Widerruf) wurde hinzugefügt. Die Bildunterschriften von Test 1/2 wurden passend zugeschnitten, um die drei Fehlerklassen getrennt zu halten; Test 2 wurde von „Test" auf narrative Brücke herabgestuft; Widerrufs- und Konstantzeit-Umfangsgrenzen wurden hinzugefügt. Die Zitationskette wurde aus Primärquellen abgerufen und für den erneuten Abruf bei der Einreichung gestempelt.