Skip to content

Fix: timing side-channel en login + validación de estado de autor/instancia en comentarios

Qué

Corrige dos hallazgos de la auditoría de backend (2026-08-27):

  • #5 (Medio) — timing side-channel en AuthService.login().
  • #7 (Medio) — falta de validación de estado ACTIVO en
    ComentarioNormalInstanciaService/ComentarioConfidencialInstanciaService.

Por qué

#5: cuando el email no existe, login() lanza la excepción antes de
llegar a authManager.authenticate() (que ejecuta BCrypt, deliberadamente
lento). Cuando el email sí existe, BCrypt corre igual. Esa diferencia de
tiempo permite a un atacante distinguir "email registrado" de "email no
registrado" sin necesidad de acertar ninguna contraseña — justo el tipo
de fuga que el resto del flujo de login se esfuerza en evitar (mismo
status/mensaje en todos los casos).

#7: ComentarioNormalEstudianteService/ComentarioConfidencialEstudianteService
ya validaban que el Estudiante y el Funcionario autor estuvieran
ACTIVO antes de crear un comentario. Sus pares de Instancia no lo
hacían — solo verificaban que ambos existieran. Esto permitía que un
funcionario desactivado (con JWT todavía vigente, ya que no hay
revocación activa de tokens) siguiera comentando instancias, y que se
comentara sobre una instancia inactiva.

Cambios

  • AuthService.java: constante HASH_DUMMY_TIMING (hash BCrypt válido
    de una contraseña que no corresponde a nadie) + passwordEncoder.matches()
    dummy en la rama "email no existe" de login().
  • ComentarioNormalInstanciaService.java / ComentarioConfidencialInstanciaService.java:
    en crear(), se agregan las validaciones instancia.getEstado() != ACTIVO
    y autor.getEstado() != ACTIVO (422), mismo criterio y mensajes que ya
    usan los servicios de comentarios de Estudiante.

Testing

  • Nuevo test en AuthServiceTest: verifica que el camino "email no
    existe" llama a passwordEncoder.matches() (mitigación de timing) y
    no llama a authManager.
  • Nuevos tests en ComentarioNormalInstanciaServiceTest y
    ComentarioConfidencialInstanciaServiceTest: instancia no activa (422)
    y autor no activo (422), sin persistir el comentario en ningún caso.
  • Suite completa: 521 tests, 0 failures, 0 errors (516 previos + 5 nuevos).

Merge request reports

Loading