# Registros de auditoría encadenados mediante hashes: qué demuestran y qué dejan fuera

Una cadena de hashes puede darte evidencia sólida de que un conjunto de registros de auditoría no se ha editado, reordenado ni insertado discretamente en medio después de crear la cadena. No demuestra que la aplicación haya registrado todos los eventos relevantes, que una marca de tiempo coincida con la hora real ni que una persona identificada haya realizado una acción. Tratarla como una prueba de todas esas cosas es la forma en que los equipos construyen una evidencia de aspecto impresionante que se desmorona ante la primera pregunta seria.

He visto investigaciones de incidentes estancarse porque se pedía a un registro responder preguntas para las que nunca fue diseñado. La cadena se verificaba correctamente, pero nadie podía determinar si el servicio había registrado la solicitud rechazada, si la identidad del operador era auténtica o si el reloj del sistema se había desviado. La criptografía estaba bien. El paquete de evidencias estaba incompleto.

Para quienes desarrollan agentes con acceso a API y SSH, esta diferencia importa más de lo habitual. Un agente puede realizar muchas acciones rápidamente, y la pregunta útil suele ser precisa: ¿qué proceso solicitó esta llamada, bajo qué autoridad, qué solicitud exacta envió el ejecutor, qué respuesta recibió y alguien la aprobó? Una cadena de hashes protege una parte de esa historia. El resto tienes que registrarlo tú.

## Una cadena válida demuestra continuidad de los registros, no la realidad

Una cadena de hashes válida demuestra que cada registro disponible se compromete con el registro anterior y que la secuencia se ha mantenido coherente desde el punto de partida elegido. Si alguien cambia un evento antiguo, intercambia dos eventos o inserta un registro entre otros dos, la verificación falla, a menos que pueda recalcular todos los enlaces posteriores y sustituir cada punto de control confiable.

Es una evidencia útil. Permite decir a un investigador: «Estos registros forman la misma secuencia que produjo esta cabecera de cadena conocida». La formulación importa. La afirmación depende de una cabecera de cadena conocida o de otra referencia confiable. Si la única copia de la cadena y de su resumen final está en el mismo equipo que controlaba el atacante, este puede reescribir ambas.

Una cadena de hashes no demuestra lo siguiente:

- Que la aplicación haya observado todos los eventos que debían registrarse.
- Que la carga útil del evento describa con precisión lo ocurrido fuera del registrador.
- Que la hora del evento coincida con un reloj confiable.
- Que la acción la haya realizado una persona y no un proceso comprometido que usara sus credenciales.
- Que la cadena comenzara antes de que un atacante obtuviera el control del sistema.

Son proposiciones distintas y requieren evidencias distintas. No llames a un registro «a prueba de manipulaciones». El software no recibe ese estatus por usar SHA-256. Una cadena hace que los cambios sean detectables bajo ciertas condiciones. Esa es la propiedad útil y defendible.

Hay que distinguir con cuidado entre **integridad** y **completitud**. La integridad pregunta si se alteraron los registros que tienes. La completitud pregunta si faltan registros. Una cadena responde bien a la primera pregunta. Solo responde a la segunda cuando una evidencia externa fija tanto los puntos de control esperados como el alcance de los eventos que el registrador debía emitir.

## El formato del registro determina qué cubre realmente el hash

Una cadena solo protege los bytes que entran en el resumen. Antes de debatir algoritmos, define un formato de evento canónico e incluye todos los campos que un investigador necesitará para interpretar la acción.

Un registro mínimo podría verse así:

```json
{
  "sequence": 1842,
  "event_id": "7b2ea6de-9c3f-4bb4-b1d7-8b13fbb1c5b9",
  "recorded_at": "2025-03-08T17:14:22.481Z",
  "actor": {"kind": "agent_process", "process_id": "p-91f"},
  "action": "http.request",
  "target": "api.example.internal/v1/releases",
  "request_digest": "sha256:...",
  "result": {"status": 201, "response_digest": "sha256:..."},
  "previous_hash": "sha256:..."
}
```

El escritor serializa el registro de una única forma definida, calcula el hash de esos bytes y almacena el resumen resultante como referencia del predecesor en el registro siguiente. Conceptualmente:

```text
record_hash[n] = SHA-256(canonical_record[n])
canonical_record[n+1].previous_hash = record_hash[n]
```

El campo `previous_hash` debe estar dentro de los bytes que cubre `record_hash[n]`. Omitirlo es un error de implementación vergonzoso, pero real. Con ese diseño, los registros llevan adornos con forma de resumen sin vincular la secuencia.

La canonicalización no es un detalle. Dos serializadores JSON pueden ordenar los campos de los objetos de forma diferente, escapar Unicode de manera distinta o dar formato diferente a los números. Un verificador que reconstruya el JSON en lugar de verificar los bytes almacenados exactos puede rechazar registros legítimos o, peor aún, generar desacuerdos sobre el significado del registro. Conserva la representación original en bytes, especifica la codificación y prueba la verificación con implementaciones independientes.

La cadena debe cubrir el contexto, no solo el cuerpo de la solicitud. Un registro que dice «desplegado» ofrece poca evidencia. Un registro que vincula la versión del ejecutor, el tipo de acción, el identificador del objetivo, la identidad autenticada del proceso, la decisión de autorización, el resumen de la solicitud, el resumen de la respuesta, el número de secuencia y la hora registrada da al revisor algo que evaluar. Aun así, no demuestra que cada campo sea verdadero, pero impide que un editor posterior cambie la historia campo por campo.

La publicación especial 800-92 de NIST, *Guide to Computer Security Log Management*, plantea lo mismo en términos operativos más sencillos: los registros necesitan suficiente información sobre el evento, el origen, el usuario, el estado y la hora para permitir el análisis, y las organizaciones necesitan proteger los datos de los registros. Una cadena perfecta alrededor de registros vagos conserva los registros vagos a la perfección. Eso no es un diseño de auditoría.

## El primer registro y la cola que falta siguen expuestos

Toda cadena tiene un primer registro, a menudo llamado registro génesis. Su valor predecesor se fija por convención, por ejemplo, como el resumen de una cadena de bytes vacía, o hace referencia a un punto de control anterior. La cadena puede establecer continuidad después de ese punto. No puede establecer por qué ese punto es el comienzo de la historia.

Imagina un servicio que escribe los registros del 1 al 10.000 en almacenamiento local. Un atacante obtiene el control completo, elimina los registros del 1 al 7.000, cambia el campo de secuencia de los registros conservados y construye una cadena nueva que empieza en lo que antes era el registro 7.001. La cadena falsificada se verifica correctamente. Un revisor que no tenga un punto de control anterior no verá ningún defecto criptográfico.

El mismo problema existe en la cola. Un fallo, un corte de energía o un atacante pueden impedir que los últimos eventos lleguen al almacenamiento persistente. El último registro conservado puede verificarse correctamente aunque una acción haya ocurrido unos instantes después. La cadena demuestra que el final conservado no se modificó posteriormente. No demuestra que sea el evento final verdadero.

Puedes reducir ambas brechas emitiendo puntos de control fuera del control del escritor. Un punto de control contiene como mínimo el identificador de la cadena, el número de secuencia, el hash del registro y la hora del punto de control. Envíalo a otra cuenta, a un almacenamiento de escritura única, a un servicio externo de sellado de tiempo o a un colector administrado de forma independiente. Un punto de control firmado es mejor que uno sin firmar porque vincula la afirmación con una identidad de firma.

RFC 3161 describe un protocolo de sellado de tiempo en el que una autoridad firma la evidencia de que observó una huella de mensaje en una hora determinada. Esto puede respaldar una afirmación limitada y útil: la autoridad tenía este resumen en ese momento. No puede decirte si la carga útil del evento era honesta, si se omitieron eventos anteriores al punto de control enviado ni si el actor estaba autorizado. Úsalo como evidencia de hora y existencia, no como sustituto de los registros operativos.

La frecuencia de los puntos de control es una decisión de riesgo. Los puntos de control frecuentes reducen el intervalo en el que alguien puede eliminar una cola aún no anclada. También crean más registros externos que conservar y reconciliar. No finjas que los puntos de control horarios protegen una reconstrucción de incidentes con precisión de minutos. Indica el intervalo máximo sin anclaje en tu procedimiento operativo.

## Un hash no convierte una marca de tiempo en una hora confiable

Una marca de tiempo de un registro indica lo que decía el reloj del registrador cuando creó el registro. Puede bastar para la depuración habitual. Es una evidencia débil para preguntas relacionadas con plazos, ventanas de negociación, accesos posteriores a una terminación o el orden de eventos entre máquinas.

Un administrador puede cambiar el reloj local. Una máquina virtual puede reanudarse con una hora antigua. La sincronización de la hora de red puede fallar. Incluso un equipo correctamente sincronizado registra cuándo su aplicación escribió el evento, lo que puede diferir del momento en que un servicio remoto recibió la solicitud o confirmó el cambio.

Cuando la diferencia importa, conserva estas horas por separado:

- `observed_at`: cuándo observó el evento el componente de origen.
- `recorded_at`: cuándo creó el registro el escritor de auditoría.
- `remote_at`: una hora devuelta por el sistema remoto, si este ofrece una.
- `checkpoint_at`: cuándo aceptó una cabecera de cadena un testigo independiente.

No las sobrescribas en un único campo `timestamp` tranquilizador. Cada una tiene un origen y un modo de fallo diferentes. Así, el investigador puede razonar sobre un intervalo en lugar de confiar en una precisión falsa.

Si necesitas evidencia temporal, registra cómo sincroniza la hora el equipo, conserva las alertas de estado de la sincronización y guarda los recibos firmados de los puntos de control. En operaciones de alto impacto, compara el registro local con la propia entrada de auditoría del servicio remoto. Una solicitud registrada a las 10:02:01 y un cambio remoto registrado a las 10:02:05 pueden describir la misma acción. La cadena protege tu registro frente a ediciones; la corroboración lo conecta con el sistema externo.

Una recomendación habitual dice: «Usa una base de datos de solo anexado y marcas de tiempo, y el problema de auditoría quedará resuelto». Es popular porque suena sencilla desde el punto de vista operativo. Es incorrecta porque el comportamiento de solo anexado dentro de un servicio dice poco sobre la confiabilidad del reloj, los eventos que faltan, la identidad o los efectos externos. Usa almacenamiento de solo anexado si encaja, pero indica qué evidencia sigue faltando.

## La atribución requiere una traza de identidad fuera del resumen

Una cadena de hashes puede conservar una afirmación de atribución como `actor = alice@example.com`. No puede demostrar que Alice proporcionara la credencial, que el proveedor de identidad la autenticara correctamente ni que un atacante no usara su sesión activa. El resumen protege la frase, no su veracidad.

Para las acciones de agentes, la identidad del proceso suele ser más útil que un campo de usuario impreciso. Registra el identificador del proceso del agente, el proceso padre cuando esté disponible, la autoridad que firmó el ejecutable, la hora de lanzamiento, el identificador de sesión y la cuenta humana o de servicio que autorizó la sesión. El nombre del proceso por sí solo ofrece poca evidencia. Cualquier programa puede elegir un nombre conocido.

La firma de código permite hacer una afirmación limitada: el sistema operativo puede identificar que un ejecutable tiene una firma asociada con una autoridad de firma y que la firma es válida según las reglas de la plataforma. No demuestra que el operador del ejecutable tuviera buenas intenciones. Sí ayuda a distinguir una compilación conocida de un binario arbitrario con el mismo nombre de archivo.

La autenticación y la autorización también necesitan registros separados. La autenticación indica qué credencial o principal aceptó el sistema. La autorización indica por qué el sistema permitió esa acción en ese momento. Un cuadro de aprobación, una asignación de rol, el alcance de un token o un ticket de cambio pueden servir como evidencia de autorización. Incluye en el registro de acción una referencia estable o el resumen de esa decisión y conserva el registro de decisión subyacente con controles de acceso.

Las firmas digitales mejoran esta capa cuando se usan correctamente. Si un escritor de auditoría firma periódicamente las cabeceras de la cadena, un verificador puede comprobar que quien tenía una clave privada produjo esas firmas. Eso añade una afirmación sobre el origen que no ofrece un hash sin clave. Sigue dependiendo de la custodia de la clave privada, el estado del certificado, los registros de rotación y la relación entre el titular del certificado y una identidad operativa real.

No escondas todo esto en una única cadena de texto `user`. Durante un incidente, las personas necesitan distinguir al humano que aprobó una ejecución, el proceso que solicitó la acción, el servicio que la ejecutó y la autoridad de credenciales que la aceptó. Pueden ser cuatro actores diferentes.

## La evidencia de autorización responde a una pregunta distinta de la actividad

Un registro de actividad responde: «¿Qué hizo el ejecutor?». Un registro de autorización responde: «¿Por qué se le permitió hacerlo?». Los equipos suelen mezclarlos porque ambos aparecen durante la misma solicitud. Esa mezcla dificulta las investigaciones.

Supón que un agente solicita un comando SSH. El ejecutor registra el host solicitado, el resumen del comando, el resultado, la identidad del proceso y la hora. Por separado, la capa de autorización registra que un proceso nuevo recibió aprobación, quién lo aprobó, qué cubría la aprobación y cuándo caducaba. Si el comando SSH se ejecuta después, el evento de actividad debe hacer referencia al registro de autorización aplicable.

Ese diseño permite al revisor hacer las preguntas correctas. ¿Se emitió el comando? Comprueba el registro de actividad. ¿La sesión tenía permiso? Comprueba el registro de autorización. ¿La pantalla de aprobación mostraba una identidad correcta? Comprueba los registros de la interfaz y de la identidad del proceso. ¿El host remoto ejecutó el comando? Comprueba sus registros de servidor o el estado resultante.

La aprobación de una sesión y la aprobación de cada uso de una credencial sensible aportan evidencias diferentes. La aprobación de sesión establece que una persona permitió que un proceso concreto operara durante su vida útil. La aprobación por acción establece una decisión más limitada, cercana a una operación específica. Ninguna es automáticamente superior. La elección depende de la frecuencia de las acciones, sus consecuencias y de si una persona puede evaluar de forma realista solicitudes repetidas.

La fatiga causada por las aprobaciones es un fallo de diseño, no una razón para dejar de registrarlas. Si una persona ve cientos de solicitudes indistinguibles, los clics resultantes ofrecen poca evidencia de una autorización meditada. Agrupa el trabajo de bajo riesgo bajo una decisión de sesión con límites claros, reserva la confirmación repetida para credenciales o acciones cuyo objetivo y consecuencia pueda evaluar la persona, y registra el alcance con palabras sencillas.

Un evento de aprobación tampoco puede demostrar por sí solo que hubiera consentimiento informado. Demuestra que el mecanismo de aprobación registró una decisión. Los detalles del proceso mostrados al usuario, la relación entre esa pantalla y el proceso que ejecuta la acción y el propio registro de auditoría determinan si la decisión puede tener peso más adelante.

## La completitud depende de dónde pueden escapar las acciones del registrador

No puedes obtener un registro completo de las acciones de un agente añadiendo una cadena de hashes a un archivo después de que el agente ya tenga las credenciales sin procesar. Cuando un agente recibe un token de API o una clave privada SSH, puede llamar a otro cliente, copiar el secreto o hacer una solicitud sin usar tu ruta auditada. La cadena puede conservar fielmente las solicitudes que vio y no registrar las que importan.

La completitud empieza por controlar el límite de la acción. El componente que posee la credencial debe ejecutar por sí mismo la solicitud de red o la operación SSH y registrar la decisión y el resultado antes de devolver una respuesta. El agente debe recibir el resultado, no el secreto. Así, la afirmación pasa de «pedimos al agente que registrara su trabajo» a «el titular de la credencial observó cada uso a través de este canal».

Aun así, el alcance debe quedar explícito. Si un desarrollador también puede usar la misma credencial en un terminal, la traza cubre el uso mediado por el agente, pero no todos los usos de la credencial. Si un agente puede acceder a una segunda ruta de red que evita el ejecutor, la traza no cubre esa ruta. Una afirmación de completitud debe indicar el canal, el principal y el periodo que cubre.

Sallyport aplica este límite a sus canales HTTP y SSH compatibles: la bóveda cifrada mantiene las credenciales de API y SSH fuera del agente, mientras la aplicación ejecuta la acción y la registra. Eso da a su traza de auditoría un alcance más sólido que un registro de actividad del lado del agente, pero no permite afirmar nada sobre acciones realizadas mediante una ruta de credenciales no relacionada.

Una prueba de fallos útil consiste en dibujar todas las rutas desde un agente hasta un efecto externo. Incluye clientes HTTP directos, herramientas de shell, archivos locales que contengan tokens, sesiones de navegador, servicios de metadatos en la nube, variables de CI y configuración SSH. Cada ruta que quede fuera del ejecutor registrado es una excepción a cualquier afirmación de completitud. Ciérrala, aísla esa ruta o registra la excepción con honestidad.

## La confidencialidad, el acceso y la conservación necesitan controles propios

Las cadenas de hashes no revelan nada por sí mismas, pero los registros de auditoría suelen contener información que no pondrías en un registro de aplicación normal. Las URL de las solicitudes pueden revelar identificadores de clientes. Las líneas de comandos pueden contener secretos. Las respuestas pueden incluir datos personales. Una cadena que dificulta alterar estos registros también puede hacer difícil deshacer una divulgación imprudente.

Cifra el almacenamiento de auditoría y limita quién puede leerlo. Cuando sea posible, separa la capacidad de verificar la integridad de la capacidad de descifrar el contenido. Un verificador puede recalcular los hashes sobre los bytes cifrados de los registros y comparar las referencias a los predecesores sin ver la carga útil protegida. Esto resulta útil cuando un revisor necesita establecer que un archivo sellado sigue intacto antes de que un investigador autorizado lo abra.

La redacción debe producirse antes de que el registro entre en la cadena. Sustituir un secreto después de escribirlo cambia los bytes y rompe la cadena. En su lugar, registra el resumen del cuerpo de una solicitud sensible, una referencia estable al token, la longitud cuando corresponda o una declaración estructurada que indique que se omitió un campo. Documenta la regla de redacción. De lo contrario, dos registros parecidos podrían haberse redactado con lógicas diferentes.

La conservación también afecta al valor probatorio. Si un proceso de conservación elimina registros antiguos, debe producir su propio registro con el intervalo eliminado, la regla de conservación aplicable, la hora de eliminación y el último punto de control anterior. Conserva el punto de control en un archivo independiente. Una cadena no puede hacer reaparecer el material eliminado, pero la evidencia conservada puede demostrar que la eliminación se hizo conforme a un proceso definido y no de forma silenciosa.

El registro de accesos también importa. Registra quién exportó un archivo de auditoría, quién lo descifró y quién cambió la configuración de conservación. Los registros de auditoría atraen atención durante un incidente. La cadena protege los registros anteriores frente a ediciones discretas, pero un grupo amplio de lectores aún puede copiar contenidos sensibles o presionar a un operador para que suprima registros futuros.

## Verifica el archivo antes de necesitarlo

La verificación debe ser una operación rutinaria con un resultado guardado, no un comando que alguien pruebe por primera vez durante una interrupción. Tu procedimiento debe identificar el intervalo exacto del archivo, la versión del verificador, el origen del punto de control esperado, la hora de verificación, el operador y el resultado.

Un verificador debe detectar como mínimo cuatro fallos: registros con formato incorrecto, una referencia al predecesor incorrecta, un registro cuyo resumen no coincide con sus bytes almacenados y una diferencia entre la cabecera calculada y el punto de control esperado. Su salida debe ser fácil de conservar. Por ejemplo:

```text
$ audit verify --archive agent-actions-2025-03-08.log --checkpoint checkpoints/2025-03-08.json
chain_id: agent-actions-prod-a
records_checked: 1842
first_sequence: 1
last_sequence: 1842
computed_head: sha256:4e7c...a912
checkpoint_head: sha256:4e7c...a912
result: VALID
```

Un resultado `VALID` significa que el verificador comprobó los bytes proporcionados frente al punto de control proporcionado. No significa «todas las acciones de producción están presentes» ni «los eventos son verdaderos». Escribe esa limitación directamente en el procedimiento. De lo contrario, quienes lean un resultado verde bajo presión le atribuirán más significado del que tiene.

Prueba los casos destructivos en un archivo que no sea de producción. Cambia un byte del cuerpo de un registro. Mueve dos registros. Elimina un registro intermedio. Sustituye la cabecera del punto de control. Trunca la cola. El verificador debe rechazar cada caso, salvo el truncamiento normal de la cola sin un punto de control final esperado, en cuyo caso puede informar de un prefijo válido. Ese informe es correcto y debería preocuparte por la razón adecuada.

Sallyport ofrece verificación de la cadena sin conexión mediante `sp audit verify`, y su verificador puede comprobar la cadena de auditoría cifrada sin una clave de la bóveda. Ejecuta esa comprobación después de las exportaciones y practica la reconciliación con las vistas separadas de sesiones y actividad antes de que una investigación te obligue a hacerlo.

## Un paquete de evidencias necesita registros que discrepen de forma útil

Una investigación defendible utiliza varios registros con modos de fallo diferentes. La coincidencia entre fuentes independientes tiene más peso que un único registro que repite sus propias suposiciones.

Para una acción sensible de un agente, conserva el registro de actividad encadenado mediante hashes, el registro de sesión o aprobación, la identidad autenticada del proceso, la versión de configuración pertinente, el recibo del punto de control externo y el registro propio del sistema objetivo o el resultado observable. No necesitas todas las fuentes para cada solicitud normal. Sí necesitas suficientes fuentes según las consecuencias de equivocarte.

Espera que las fuentes discrepen en ocasiones. El registro de actividad local puede preceder a la marca de tiempo del servicio remoto porque la entrega de red tardó un tiempo. Una solicitud puede recibir una respuesta correcta mientras el sistema remoto revierte después la operación. Un registro de sesión puede mostrar una aprobación, mientras el registro de acción no muestra ningún uso de la autoridad concedida. Estas diferencias son evidencias que deben investigarse, no defectos que haya que suavizar.

Escribe las afirmaciones exactas que tu sistema puede respaldar. Por ejemplo: «Este archivo contiene una secuencia sin modificaciones de registros del ejecutor hasta el punto de control X». Después escribe las afirmaciones que no puede respaldar sin otros registros: «Este archivo por sí solo no demuestra que no se usara la credencial directamente». Los límites claros hacen creíbles las afirmaciones sólidas.

La primera acción práctica consiste en elegir una operación de agente de alto impacto y reconstruirla de principio a fin. Identifica el límite de la acción, los campos escritos antes de la ejecución, los campos escritos después, la evidencia de aprobación, el destino del punto de control, la corroboración remota y todas las rutas alternativas. Si alguna parte depende de que alguien recuerde lo ocurrido, todavía no tienes una traza de auditoría. Tienes una historia que quizá no sobreviva al contacto con un incidente.
