◇ OpenCyber Academy
Técnico · Capítulo 9 · Español

Capítulo 9 — Infraestructura crítica y seguridad sectorial: herramientas y métodos

Aprendizaje gratuito y abierto para quienes desean proteger a las personas y la tecnología. No se necesita una cuenta para estudiar ni consultar las respuestas.

Capítulo 9 — Infraestructura crítica y seguridad sectorial: herramientas y métodos

Mapa de la lección

Lección 09 publicada. Mapa, ejemplo, EX033.

flowchart TD
  N0["Resultados de aprendizaje y conexión"]
  N1["9.1 Elegir un método"]
  N2["9.2 DNP3 en la capa de enlace"]
  N3["9.3 Valide primero la herramienta"]
  N4["9.6 Actividad práctica"]
  N5["Síntesis del capítulo"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5
  N5 --> EX["Ejemplo resuelto"]
  EX --> Q["Ejercicio EX033"]

Dibujo lógico

flowchart LR
  N0["Resultados de aprendizaje y conexión"]
  N1["9.1 Elegir un método"]
  N2["9.2 DNP3 en la capa de enlace"]
  N3["9.3 Valide primero la herramienta"]
  N4["9.6 Actividad práctica"]
  N5["Síntesis del capítulo"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX033"]
[Resultados de aprendizaje y conexión]
    |
    v
[9.1 Elegir un método]
    |
    v
[9.2 DNP3 en la capa de enlace]
    |
    v
[9.3 Valide primero la herramienta]
    |
    v
[9.6 Actividad práctica]
    |
    v
[Síntesis del capítulo]
    |
    v
[Ejemplo resuelto] --> [Ejercicio EX033]

Resultados de aprendizaje y conexión

Al terminar este capítulo debería ser capaz de:

Los capítulos 7 y 8 usaron la telemetría. Este capítulo trata de los propios instrumentos: cómo elegirlos, cómo construir bien los pequeños y cómo saber cuándo mienten.

9.1 Elegir un método

Pregunta Preferir Evitar salvo con alcance definido
¿Qué está configurado? Exportación de configuración, vista de solo lectura de la herramienta del fabricante Sondear puertos para deducir la configuración
¿Quién habla con quién? Registros de flujos, captura pasiva en un puerto SPAN o un derivador (tap) Escaneo activo
¿Qué ejecuta un dispositivo? Registros de activos, inventario de la herramienta de ingeniería durante una sesión aprobada Identificación de huellas mediante sondeo
¿Funciona una regla de denegación? Registros del cortafuegos más una prueba de conexión delimitada Escaneos amplios
¿Está bien formada una trama? Decodificador con comprobaciones del protocolo (capítulo 2, este capítulo) Mirar el hexadecimal a ojo

La guía de seguridad de TO NIST SP 800-82 Rev. 3 trata la supervisión pasiva y los riesgos de las técnicas activas (SP 800-82 Rev. 3). Los analizadores de paquetes como Wireshark incluyen disectores para Modbus y DNP3; sus propios scripts sirven para las comprobaciones que esas herramientas no hacen por usted y para una automatización repetible y revisable.

9.2 DNP3 en la capa de enlace

DNP3 se usa ampliamente en el telecontrol eléctrico y del agua. Cada trama de la capa de enlace empieza con una cabecera de 10 bytes: los bytes de inicio 05 64, un byte de longitud, un byte de control, una dirección de destino de 2 bytes y una de origen de 2 bytes (little-endian), y un CRC de 2 bytes. Los datos de usuario siguen en bloques de hasta 16 bytes, cada uno con su propio CRC. En el byte de control, el bit 7 (DIR) está activado en las tramas que envía la maestra, el bit 6 (PRM) en las tramas primarias (iniciadoras), y los cuatro bits bajos son el código de función del enlace; por ejemplo, primaria 0 «reiniciar los estados del enlace», primaria 4 «datos de usuario no confirmados», secundaria 11 «estado del enlace». El DNP Users Group publica una visión general; la norma completa es IEEE 1815 (DNP3 overview).

El CRC es CRC-16/DNP: polinomio 0x3D65, valor inicial 0, entrada y salida reflejadas, XOR final 0xFFFF, con el valor de comprobación del catálogo 0xEA82 para la cadena ASCII 123456789 (CRC catalogue). Reflejado, el polinomio es 0xA6BC, que es la constante que se usa en una implementación bit a bit.

9.3 Valide primero la herramienta

Una rutina de CRC sutilmente errónea sigue produciendo números. Antes de usarla, ejecute una prueba de respuesta conocida: calcule el CRC de 123456789 y compárelo con 0xEA82. Después, una prueba negativa: cambie un bit de una trama válida y confirme que la comprobación falla. El Lab 9 hace ambas (la línea assert es la prueba de respuesta conocida), y anote la versión de Python, porque el resultado de cualquier herramienta solo es evidencia si la herramienta está identificada. Mantenga en el script el assert que comprueba el valor del catálogo y haga fallar la tarea si deja de cumplirse tras un cambio en la función de CRC. Anote la versión de Python junto a cada resultado que vaya a usarse como evidencia. Ejecute la prueba negativa sobre una trama que haya corrompido usted mismo, para saber que el comprobador rechaza los CRC erróneos antes de confiar en él sobre una captura.

9.4 Detectar errores no es autenticar

Un CRC se calcula a partir de parámetros públicos; cualquiera que pueda enviar una trama puede calcular un CRC válido. Detecta la corrupción accidental, no la falsificación. El Lab 9 lo muestra directamente: una trama de una dirección de origen desconocida (77) tiene un CRC válido. Distinguir lo auténtico de lo falsificado exige autenticación criptográfica (DNP3 Secure Authentication o un túnel protegido) o contexto: direcciones de origen conocidas, rutas conocidas, tiempos esperados. Compárelo con el capítulo 15 del libro de tecnólogo, que usa HMAC (RFC 2104) para la autenticidad (RFC 2104).

9.5 Ejemplo resuelto: comprobación de las cabeceras de SS-3 (sintético)

La maestra de Kestrel Grid (dirección DNP3 1) sondea la estación remota de la subestación SS-3 (dirección 10) a través de fep-01. Un técnico capturó seis cabeceras de enlace. Lab 9 (guárdelo como lab09.py y ejecútelo con python3 lab09.py):

# Lab 9 - check DNP3 link-layer headers and their CRC (offline, standard library only)
# CRC-16/DNP: poly 0x3D65 (reflected 0xA6BC), init 0x0000, reflected in/out, xorout 0xFFFF.
# Synthetic frames between the Kestrel Grid master (address 1) and substation SS-3 outstation (address 10).
import struct
def crc_dnp(data: bytes) -> int:
    crc = 0
    for byte in data:
        crc ^= byte
        for _ in range(8):
            crc = (crc >> 1) ^ 0xA6BC if crc & 1 else crc >> 1
    return crc ^ 0xFFFF
assert crc_dnp(b"123456789") == 0xEA82          # catalogue check value
def header(length, ctrl, dest, src):
    h = bytes([0x05, 0x64, length, ctrl]) + struct.pack("<HH", dest, src)
    return h + struct.pack("<H", crc_dnp(h))
capture = [
    ("master->SS-3", header(0x05, 0xC0, 10, 1).hex()),     # primary function 0: reset link states
    ("SS-3->master", header(0x05, 0x0B, 1, 10).hex()),     # secondary function 11: link status
    ("master->SS-3", header(0x11, 0xC4, 10, 1).hex()),     # primary function 4: unconfirmed user data
    ("master->SS-3", "056411c40a000100" + "ffff"),          # wrong CRC
    ("unknown->SS-3", header(0x11, 0xC4, 10, 77).hex()),   # source not in station table
    ("master->SS-3", "0565" + header(0x05, 0xC0, 10, 1).hex()[4:]),  # bad start bytes
]
KNOWN_SOURCES = {1}
for label, hx in capture:
    b = bytes.fromhex(hx)
    if b[:2] != b"\x05\x64": print(f"{label:<14} {hx}  REJECT start bytes {b[:2].hex()}"); continue
    got = struct.unpack("<H", b[8:10])[0]; want = crc_dnp(b[:8])
    length, ctrl, dest, src = b[2], b[3], *struct.unpack("<HH", b[4:8])
    if got != want: print(f"{label:<14} {hx}  REJECT crc {got:04x} != {want:04x}"); continue
    direction = "from master" if ctrl & 0x80 else "from outstation"
    note = "" if src in KNOWN_SOURCES or src == 10 else "  ALERT unknown source address"
    print(f"{label:<14} {hx}  ok len={length} ctrl=0x{ctrl:02x} ({direction}, fc={ctrl & 0x0F}) dest={dest} src={src}{note}")

Salida esperada (Python 3.13.5):

master->SS-3   056405c00a000100b1ac  ok len=5 ctrl=0xc0 (from master, fc=0) dest=10 src=1
SS-3->master   0564050b01000a006ded  ok len=5 ctrl=0x0b (from outstation, fc=11) dest=1 src=10
master->SS-3   056411c40a0001000615  ok len=17 ctrl=0xc4 (from master, fc=4) dest=10 src=1
master->SS-3   056411c40a000100ffff  REJECT crc ffff != 1506
unknown->SS-3  056411c40a004d0073e6  ok len=17 ctrl=0xc4 (from master, fc=4) dest=10 src=77  ALERT unknown source address
master->SS-3   056505c00a000100b1ac  REJECT start bytes 0565

Tres tramas son válidas y esperadas. Una tiene el CRC ffff donde se esperaba 1506: corrupción o una trama fabricada; en un enlace ruidoso, una racha de fallos de CRC es un hallazgo de calidad del enlace para el proveedor de telecomunicaciones. Otra tiene bytes de inicio erróneos y se rechaza antes de leer nada más. La línea más importante es la que supera el CRC: la dirección de origen 77 no está en la tabla de estaciones. El CRC dice que los bytes llegaron intactos; solo la comprobación de la dirección dice que procedían de un lugar inesperado.

9.6 Actividad práctica

Amplíe el Lab 9 para verificar el CRC de cada bloque de datos de usuario de 16 bytes que sigue a la cabecera. Construya una trama con 17 bytes de datos de usuario (un bloque completo y un bloque de 1 byte), calcule los CRC de ambos bloques y corrompa un byte del segundo bloque para mostrar que la comprobación lo detecta. Corrompa un byte del segundo bloque y confirme que solo falla la comprobación de ese bloque. Guarde los pasos de construcción en las notas del laboratorio para que un revisor pueda reconstruir la misma trama, y anote qué byte corrompió y el CRC esperado y el calculado de ese bloque.

9.7 Errores comunes y límites

Ejercicios — capítulo 9

EX033 — Prueba de respuesta conocida. Objetivo: validar una herramienta. Entradas: la función crc_dnp del Lab 9. Pasos: (1) sustituya 0xA6BC por 0x3D65 y ejecute; (2) explique el resultado. Evidencia esperada: salida y explicación. Rúbrica: 3 = el assert falla porque un algoritmo con desplazamiento a la derecha (reflejado) necesita el polinomio reflejado; la prueba de respuesta conocida detectó un error verosímil antes de juzgar ninguna trama; 2 = observa el fallo sin explicarlo; 1 = intentado; 0 = nada.

EX034 — Decodifique el byte de control. Objetivo: leer los campos de enlace de DNP3. Entradas: los bytes de control 0xC9, 0x44 y 0x0B. Pasos: dé DIR, PRM y el código de función de cada uno y nombre la función. Evidencia esperada: tres filas. Rúbrica: 3 = 0xC9: DIR 1, PRM 1, fc 9 solicitar el estado del enlace; 0x44: DIR 0, PRM 1, fc 4 datos de usuario no confirmados desde una estación remota (por ejemplo, una respuesta no solicitada); 0x0B: DIR 0, PRM 0, fc 11 estado del enlace; 2 = uno erróneo; 1 = solo los bits; 0 = nada.

EX035 — Experimento mental de falsificación. Objetivo: separar integridad y autenticidad. Entradas: una trama con CRC válido, dirección de origen 1 y destino 10, que llega a la estación remota desde una dirección de la red MPLS que no es fep-01. Pasos: explique lo que muestra el CRC, lo que muestra la dirección y lo que establecería realmente la autenticidad. Evidencia esperada: explicación breve. Rúbrica: 3 = el CRC muestra que no hubo corrupción accidental; la dirección DNP3 1 la declara el propio emisor; la autenticidad requiere Secure Authentication o un túnel criptográfico que termine en extremos conocidos, más la aplicación de la ruta en la red; 2 = parcial; 1 = «CRC válido, luego auténtica»; 0 = nada.

EX036 — Selección del método. Objetivo: elegir el método menos intrusivo. Entradas: preguntas: (a) qué direcciones de maestra DNP3 ha visto SS-3 este mes; (b) si el cortafuegos de fep-01 solo permite la estación remota; (c) la versión de firmware de la estación remota. Pasos: elija un método para cada una y justifíquelo. Evidencia esperada: tres elecciones. Rúbrica: 3 = (a) captura pasiva o registros de fep-01 analizados con un decodificador; (b) exportación de configuración más registros y, después, una prueba delimitada si hace falta; (c) registro de activos o herramienta del fabricante durante una sesión aprobada con el acuerdo del ingeniero de protecciones; 2 = una elección intrusiva; 1 = escaneo; 0 = nada.

Síntesis del capítulo

Elija el método menos intrusivo que responda a la pregunta y valide toda herramienta antes de confiar en ella: pruebas de respuesta conocida, pruebas negativas, versiones registradas. El CRC de la capa de enlace de DNP3 muestra esta disciplina en miniatura (implementarlo a partir de los parámetros publicados, comprobarlo con el valor del catálogo) y también su límite: la detección de errores demuestra que los bytes llegaron intactos, nunca quién los envió.

Siga estudiando — capítulo 09 de 18

← Capítulo 08 · Índice de capítulos del curso · Capítulo 10 →

Continúe con la siguiente lección escrita.

Respuestas desarrolladas

EX033 — Prueba de respuesta conocida. Con 0x3D65 en el bucle con desplazamiento a la derecha, el assert falla (AssertionError) y el programa se detiene antes de juzgar ninguna trama. Una implementación con bits reflejados (primero el menos significativo) debe usar el polinomio reflejado 0xA6BC; la forma normal 0x3D65 corresponde a las implementaciones que empiezan por el bit más significativo. La prueba de respuesta conocida convirtió un error silencioso y verosímil en un fallo inmediato.

EX034 — Decodifique el byte de control. 0xC9 = 1100 1001: DIR 1 (desde la maestra), PRM 1, función 9, solicitar el estado del enlace. 0x44 = 0100 0100: DIR 0 (desde la estación remota), PRM 1 (primaria), función 4, datos de usuario no confirmados, como los que usa, por ejemplo, la respuesta no solicitada de una estación remota. 0x0B = 0000 1011: DIR 0, PRM 0, función 11, estado del enlace (secundaria).

EX035 — Experimento mental de falsificación. El CRC solo muestra que los bytes no se corrompieron accidentalmente. La dirección de origen DNP3 1 es un campo que escribe el emisor; cualquier equipo puede atribuírsela. La autenticidad requiere protección criptográfica (DNP3 Secure Authentication, o un túnel cuyos extremos estén autenticados, por ejemplo TLS que termine en fep-01 y en la estación remota o su pasarela), más la aplicación en la red de que solo la ruta de fep-01 alcanza la estación remota. El origen de red inesperado es en sí mismo el hallazgo.

EX036 — Selección del método. (a) Pasivo: decodificar una captura en fep-01 o sus registros a lo largo del mes y enumerar las direcciones de origen. (b) Exportación de la configuración del cortafuegos de fep-01 y sus registros; una única prueba de conexión delimitada solo si la exportación es ambigua. (c) Registro de activos; si no, la herramienta del fabricante en modo de solo lectura durante una sesión aprobada y organizada con el ingeniero de protecciones o de telecontrol de Kestrel Grid; nunca sondeando la estación remota.