Investigar y Prevenir una Regresión de Seguridad

CiberseguridadBeginner
Practicar Ahora

Introducción

Un ajuste temporal de depuración ha reaparecido en una nueva versión del servicio de DeskLite. Las solicitudes siguen teniendo éxito, pero los registros operativos ahora incluyen una credencial falsa. Una comprobación de éxito funcional por sí sola no detectó esta regresión.

Seguirás pruebas de solicitudes reales, detendrás nuevas filtraciones, reemplazarás la credencial expuesta y añadirás una aserción que bloquee un candidato que realmente filtre datos. Los registros históricos se conservan como pruebas; no se requiere un documento de investigación. El emisor local, el cliente, el servicio, los controles comparativos y las herramientas auxiliares de artefactos están preparados.

Localizar el Evento Real del Incidente

En este paso relacionarás una solicitud con la versión y la configuración actuales del registro.

cd /srv/ticket-regression

tail -n 5 lee las últimas cinco líneas para mantener una vista pequeña. Usa tu lectura de administrador autorizada para el registro del servicio preparado:

sudo tail -n 5 /opt/labex-ticket-regression/requests.log

Busca request_id=initial-001, version=logging-v2, path=/tickets y status=200. Esta solicitud histórica tuvo éxito, pero la misma línea incluye Authorization y el token ficticio anterior. Todos los valores pertenecen únicamente a este laboratorio aislado.

grep imprime las líneas que contienen un patrón de texto proporcionado. Las comillas simples mantienen unido este patrón literal:

sudo grep 'request_id=initial-001' /opt/labex-ticket-regression/requests.log
cat logging.conf

include_authorization = true explica el campo sensible. La hora, el ID de solicitud, la versión y el estado del evento relacionan el comportamiento observado con la configuración activa. Conserva el registro original; borrarlo eliminaría pruebas, no impediría futuras filtraciones.

Evitar los Campos Sensibles en Nuevos Eventos

En este paso cambiarás la política de registro y conservarás campos útiles de auditoría.

nano logging.conf

Usa:

[logging]
include_authorization = false

Guarda con Ctrl+O, Enter y Ctrl+X. Aplica la configuración guardada usando el punto de entrada de reinicio preparado:

bash restart.sh

Asigna un ID conocido a una nueva solicitud de salud. X-Request-ID es una cabecera de solicitud usada para relacionarla con su nuevo evento:

curl -H 'X-Request-ID: after-policy-fix' http://127.0.0.1:8080/health
sudo grep 'request_id=after-policy-fix' /opt/labex-ticket-regression/requests.log

Espera la hora, la versión, el ID, la ruta y status=200, sin campo Authorization. El evento anterior initial-001 se conserva. Evalúa los nuevos eventos por sus propios ID en lugar de exigir que todas las líneas históricas estén libres de secretos.

Revocar y Reemplazar la Credencial Expuesta

En este paso eliminarás la autoridad del token anterior usando el flujo del emisor ya aprendido.

Cambiar la política de registro no invalida un valor expuesto. Revoca su ID de gestión:

course-token revoke legacy
curl -i -H 'Authorization: Bearer labex_012345abcdefghijklmnopqrstuvwxyz' http://127.0.0.1:8080/tickets

Espera 401. Ahora emite la credencial de reemplazo sin imprimirla:

course-token issue /srv/ticket-regression/api.token

Protégela usando el patrón de administrador/grupo del cliente de los laboratorios de permisos y tokens:

sudo chown root:deskclient api.token
sudo chmod 640 api.token

El emisor creó el valor; tú solo estableciste su acceso. No lo copies en el código de prueba, el script del cliente ni un informe escrito.

Restablecer el Cliente que Lee el Archivo

En este paso harás que el cliente existente use la credencial de reemplazo protegida.

nano sender.sh

Guarda la misma forma de lectura de archivo aprendida anteriormente:

#!/bin/bash
exec sudo -u deskclient /usr/bin/python3 /opt/labex-ticket-regression/send.py --token-file /srv/ticket-regression/api.token

Usa Ctrl+O, Enter, Ctrl+X.

bash sender.sh

Espera HTTP 200 y el ticket original Printer offline. Lee los eventos operativos recientes:

sudo tail -n 5 /opt/labex-ticket-regression/requests.log

La nueva solicitud correcta conserva campos de auditoría sin un valor de credencial. Un valor anterior filtrado puede permanecer en el historial del incidente conservado mientras su autoridad ya se ha eliminado. Esa distinción evita tanto borrar pruebas como tratar la exposición anterior como una vía de autenticación que sigue funcionando.

Ver Por Qué la Prueba Existente No Detectó la Filtración

En este paso inspeccionarás la pequeña plantilla de pruebas antes de añadir el nuevo requisito.

cat test_security.py

La prueba positiva usa la plantilla de solicitudes del laboratorio de escritura de pruebas. La herramienta auxiliar preparada api proporciona token desde la fuente de credenciales del destino y devuelve el estado HTTP real, el cuerpo y el evento real de registro de esa solicitud. "Bearer " + token une dos cadenas para formar un valor de cabecera; el valor no se copia en el código fuente.

Dos controles separados usan el token público y falso de prueba: good omite los campos sensibles del registro, mientras que logging-regression registra deliberadamente el token de prueba. No usan ni exponen tu nueva credencial operativa de reemplazo.

course-regression-tests good
course-regression-tests logging-regression

Ambos superan actualmente test_valid_token: el estado y los datos de negocio siguen siendo correctos en cualquiera de las dos implementaciones. El requisito que falta se refiere al evento real en response["log"]. Cada solicitud de la herramienta auxiliar usa un ID único, de modo que el registro devuelto pertenece a esa nueva solicitud y no a un evento histórico ajeno.

Añadir una Aserción Real de Ocultación de Datos del Registro

En este paso ampliarás la prueba con requisitos de ausencia y de presencia para el nuevo evento.

En Python, in comprueba si una cadena aparece dentro de otra. not in exige que esté ausente. Estas son aserciones sobre el texto real del registro devuelto, no sobre un archivo de pruebas de ejecución proporcionado manualmente.

nano test_security.py

Conserva la prueba positiva y usa este archivo completo:

from api import request, token

def test_valid_token():
    response = request("/tickets", {"Authorization": "Bearer " + token})
    assert response["status"] == 200
    assert response["body"] == {"tickets": [{"id": 1, "title": "Printer offline"}]}

def test_log_is_redacted():
    response = request("/tickets", {"Authorization": "Bearer " + token})
    assert response["status"] == 200
    assert "Authorization" not in response["log"]
    assert token not in response["log"]
    assert "request_id=" in response["log"]
    assert "path=/tickets" in response["log"]
    assert "status=200" in response["log"]

Guarda con Ctrl+O, Enter, Ctrl+X. La nueva prueba rechaza el campo sensible y el valor de credencial a la vez que exige el ID de solicitud, la ruta de negocio y el estado correcto. Vaciar el registro incumpliría esos requisitos positivos.

La herramienta auxiliar proporciona internamente un token específico del destino. Las pruebas normales del servicio leen la credencial de reemplazo protegida; los controles comparativos usan el dato público y falso de prueba. Ninguno de esos valores debe estar en este archivo de pruebas.

Demostrar que la Prueba Detecta la Regresión Conocida

En este paso validarás la nueva aserción con un comportamiento seguro y otro que filtra datos deliberadamente.

course-regression-tests good

Espera que ambas pruebas pasen.

course-regression-tests logging-regression

Espera que falle únicamente test_log_is_redacted con AssertionError, devolviendo el código de salida 1. Es una detección intencionada, no una petición de debilitar la aserción. La prueba positiva de negocio debe seguir pasando.

course-regression-tests live

Ambas deberían pasar con tu servicio real corregido. Estas pruebas solo inspeccionan los eventos de sus nuevas solicitudes; el evento histórico original filtrado se conserva intencionadamente. Un error de sintaxis, un error de conexión o un fallo incondicional no demostraría una cobertura eficaz de ocultación de datos sensibles.

Conectar la Nueva Prueba con la Entrega del Candidato

En este paso impedirás que se entregue un futuro candidato cuando falle la nueva aserción.

El control preparado usa la misma estructura de comprobación/construcción/pruebas/despliegue del laboratorio anterior de controles. build.sh empaqueta el servidor original y la política de registro actual, y después inicia ese candidato real en un puerto local separado. El test.sh existente comprueba su comportamiento con token válido, ausente e incorrecto; no comprueba los registros.

nano gate.sh

Añade la llamada de regresión después de la construcción y antes de las pruebas funcionales existentes. Usa:

#!/bin/bash
bash checks.sh
status=$?
if [ "$status" -eq 1 ]; then
    exit 1
fi
if [ "$status" -ne 0 ]; then
    exit 2
fi
bash build.sh || exit 2
bash regression.sh candidate || exit 2
bash test.sh || exit 2
bash deploy.sh

Guarda con Ctrl+O, Enter, Ctrl+X. candidate selecciona la aplicación real recién construida, por lo que la aserción añadida protege el artefacto que está a punto de desplegarse. || exit 2 detiene la entrega si fallan sus pruebas.

bash gate.sh

Espera la comprobación previa de credenciales, la construcción del candidato real, las nuevas pruebas de regresión y las pruebas funcionales superadas, y el despliegue de ese candidato en el puerto local operativo. Dejar simplemente un archivo de pruebas sin usar no proporcionaría esta prevención.

Confirmar los Nuevos Eventos y el Historial Conservado

En este paso verificarás el comportamiento entregado y reflexionarás sobre las pruebas sin escribir un archivo de informe.

bash sender.sh
sudo tail -n 5 /opt/labex-ticket-regression/requests.log

Los nuevos eventos operativos deben conservar la hora, la versión real entregada, los ID de solicitud, las rutas y los estados sin credenciales. La versión entregada ahora es un hash de artefacto en lugar de la etiqueta original logging-v2.

sudo grep 'request_id=initial-001' /opt/labex-ticket-regression/requests.log

El evento original del incidente sigue existiendo. Su token anterior está revocado; la credencial de reemplazo protegida funciona. El control separado de regresión deliberada es una comparación didáctica, no el servicio desplegado.

Explícate qué evento reveló el problema, qué ajuste lo causó, por qué corregir solo la política era insuficiente y cómo la nueva aserción del candidato impide que se repita. La comprobación del curso prueba un candidato con una regresión real, confirma que el control lo bloquea y verifica que sobreviva el artefacto seguro que estaba en ejecución. No se requiere un documento de investigación con formato fijo.

Resumen

Relacionaste un evento real de incidente con su política de registro, detuviste nuevas filtraciones, revocaste y reemplazaste la credencial expuesta y conservaste las pruebas históricas. Una nueva aserción detecta la regresión deliberada y se ejecuta sobre el candidato real dentro del control de entrega, conservando el comportamiento seguro en ejecución cuando falla un futuro candidato.