
Prueba de concepto que reproduce la falla de clave codificada de CVE-2021-22681 y valida una corrección de TLS mutuo/CRL por dispositivo sobre EtherNet/IP simulado, con mapeo de IEC 62443-4-2.
Cuatro scripts ejecutables. Tráfico real del protocolo EtherNet/IP, criptografía real, cero software o licencias de Rockwell en cualquier punto de la cadena. Construido para probar una afirmación antes de documentarla, no para defenderla por fe.
Procedencia: construido el 2026-07-31, junto con una investigación paralela sobre la PTAR de Braham, MN — una de las cuatro empresas de servicios públicos divulgadas públicamente en el incidente coordinado del sector del agua de Minnesota del 26 al 27 de julio de 2026. El contexto de ese incidente se encuentra en el aviso de CISA AA26-097A (conjunto FBI/CISA/NSA/EPA/DOE/USCYBERCOM/Treasury; emitido el 2026-04-07, ampliado el 2026-07-22), que cubre la campaña en curso CyberAv3ngers, afiliada al IRGC. Advertencia de atribución, mantenida con precisión: ninguna agencia ha atribuido formalmente el incidente de Minnesota específicamente a ese grupo — solo se ha atribuido la campaña más amplia en curso. Esta carpeta es el lado de la corrección técnica, mantenida separada de la investigación del incidente a propósito.
Un paquete de divulgación vive o muere según no mezcle estas tres cosas, porque cada una tiene una corrección diferente:
La corrección demostrada aquí — vinculación de identidad por dispositivo (Prueba 3) — aborda la falla de la clave de flota.
No confunda las dos filas. El principio está probado. La implementación específica del proveedor es creíble (es su propia intención de diseño declarada), pero no la hemos probado contra equipos reales.
test1_baseline_vulnerable.py — la línea base sin autenticación, en vivoLevanta un simulador real de PLC EtherNet/IP (cpppo, que emula un Allen-Bradley ControlLogix) y lee + escribe una etiqueta de control con cero credenciales. (Alcance: esta es la amplia línea base sin autenticación en la que se apoyó la campaña — no el mecanismo específico de clave hardcodeada de CVE-2021-22681. Se mantiene distinta a propósito; véase "Tres fallas diferentes" arriba.)
python test1_baseline_vulnerable.py
test2_shared_secret_fails.py — la forma de la falla de clave de flota (puente narrativo, no una prueba)Dos endpoints contienen una única clave estática; una credencial del Dispositivo A abre el Dispositivo B sin cambios — el análogo estructural más cercano a la falla de una-clave-para-todos de CVE-2021-22681. Pero es tautológico: ambos manejadores están construidos para aceptar esa clave, por lo que no hay una ruta de ejecución en la que pueda fallar. No demuestra nada que el código no cree por construcción. Se mantiene como puente narrativo de la Prueba 1 a la Prueba 3; no tiene peso probatorio y deliberadamente no es una pata de la prueba.
python test2_shared_secret_fails.py
test3_mutual_tls_fix.py — la corrección, con su control negativo y ambas direccionesCA real, dos certificados de dispositivo individualmente únicos — identidad vinculada en el SubjectAlternativeName, no en el CommonName obsoleto. Cinco casos, todos ejecutados:
device-a (check_hostname contra un SAN real). Mutuo — ambos extremos vinculan la identidad.python test3_mutual_tls_fix.py
test4_revocation.py — la pata del ciclo de vida: revocaciónUna CRL real firmada por la CA. Una credencial de cliente (engineer-1) se concede; luego su serial se agrega a la CRL, y la misma credencial aún válida, no expirada y firmada por la CA es denegada — el contenido empírico de la cláusula de revocación CR 1.8 / 1.9. Unicidad (Prueba 3) ≠ revocabilidad; esto demuestra que una credencial puede retirarse.
python test4_revocation.py
test4_revocation.py); rotación — aún no. La unicidad por dispositivo (Prueba 3) no es lo mismo que la revocabilidad; la Prueba 4 cierra esa brecha — una credencial aún válida, no expirada y firmada por la CA se concede antes de la revocación y se deniega después, únicamente porque la CRL firmada por la CA ahora incluye su serial. La rotación (re-emitir una credencial de reemplazo y retirar la anterior) está estrechamente relacionada y habilitada por la misma PKI, pero no se demuestra por separado aquí — por lo que la "vinculación de identidad por dispositivo" aún no debe expandirse silenciosamente a "rotación resuelta".presented == KEY, identity in SAN) no son de tiempo constante. No explotable aquí — los valores comparados son cadenas de identidad semi-públicas y TLS ya ha realizado la autenticación criptográfica real antes de que se ejecute la comparación — pero se señala porque el patrón se copia en lugares donde sí importa.python -m venv venv
venv\Scripts\activate # or: 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, con niveles honestos, cada brecha nombrada; la CR 1.2, la CR 1.9 y la pata de emisión/validación/revocación de la CR 1.8 están ahora demostradas). Antes de PSIRT ([email protected] / [email protected]): verificar el texto normativo de cada CR contra una copia comprada de IEC 62443-4-2:2019.PHASED_ROLLOUT.md (Fase 0 detener la hemorragia · 1 segmentar · 2 controles compensatorios · 3 CIP Security/PKI, si el hardware lo permite · 4 operar). Dimensionado correctamente para una pequeña empresa de servicios públicos; honesto en que CIP Security está restringido por hardware, por lo que las Fases 0–2 asumen la reducción de riesgo de todos modos.Cada identificador externo aquí fue extraído de una fuente en vivo el 2026-07-31, no recordado del entrenamiento: AA26-097A (multifuente, incl. WaterISAC / Tenable / SecurityWeek), Braham como una de las cuatro víctimas divulgadas, CyberAv3ngers/IRGC, PN1550 confirmado como el aviso real de Rockwell con su cita de la Fila 2 verificada verbatim ("When properly deployed, CIP Security remediates this vulnerability" + "does not make use of any hardcoded keys"), "cannot be mitigated with a patch" verbatim, CVSS 10.0 / CRÍTICO (v3.1), seguimiento de CISA ICSA-21-056-03, y 62443-4-2 CR 1.8 (PKI) + CR 3.1 (integridad de comunicaciones) confirmados exactos.
Disciplina para el paquete: re-extraer cada identificador de fuentes primarias en el momento del envío. Los avisos se renumeran, amplían y sustituyen — AA26-097A ya muestra una ampliación — por lo que "verificado el 2026-07-31" no es "verificado al enviar". El mapeo formal completo CR por CR de 62443-4-2 ya está escrito (62443-4-2_SL2_MAPPING.md) — lo que queda es re-extraer su texto normativo citado contra una copia comprada del estándar antes del envío, no escribir el mapeo en sí.
l0gic — Patrick Crosby · 2026-07-31.
Registro de endurecimiento: la Prueba 3 se reforzó para incluir el control negativo (caso 4, que demuestra la necesidad y no solo que se dispara), el caso de dirección inversa (caso 5, vinculación mutua) y la identidad basada en SAN (no CN), y luego se re-verificó re-ejecutando los cinco casos; se agregó la Prueba 4 (revocación por CRL). Los epígrafes de las Pruebas 1/2 se ajustaron para mantener las tres clases de fallas distintas; la Prueba 2 se degradó de "prueba" a puente narrativo; se agregaron los límites de alcance de revocación y tiempo constante. La cadena de citas se recuperó de fuentes primarias y se marcó para re-extraerla en el envío.
| Afirmación | Nivel | Por qué |
|---|
| El principio arquitectónico | "un secreto compartido único en una flota se ve comprometido en toda la flota por una sola fuga; la autenticación vinculada a la identidad por dispositivo cierra esa brecha" | PROBADO | demostrado con código real en ejecución, incluido el control negativo que demuestra que la verificación es necesaria, no solo que se dispara: en un endpoint estricto, el certificado genuinamente válido para la CA del Dispositivo B es rechazado por identidad (Prueba 3 · caso 3), pero en un endpoint de solo validez de CA el mismo certificado es aceptado (caso 4 — el control) → "la firma CA válida por sí sola == acceso a toda la flota == Prueba 2 con ropaje TLS". La vinculación también se sostiene en sentido inverso: un servidor rogue que presenta un certificado de flota válido es rechazado por el cliente (caso 5). La Prueba 1 muestra por separado la línea base más amplia sin autenticación. |
| La implementación específica de CIP Security de Rockwell se comporta de manera idéntica | "habilitar CIP Security en hardware real de Rockwell remedia CVE-2021-22681 exactamente de esta manera" | HIPÓTESIS LÍDER, con fuente pero no verificada | este es el lenguaje del propio aviso de Rockwell (PN1550) — "When properly deployed, CIP Security remediates this vulnerability... does not make use of any hardcoded keys" — no es algo que hayamos confirmado de manera independiente contra hardware Logix real. Probamos el principio que describe su aviso, no su implementación exacta a nivel de wire. |