¿Error de Lógica o Programación Insegura?
En algunas aplicaciones, los fallos de lógica o prácticas de programación insegura pueden conducir a una situación donde las partes críticas de la aplicación pueden ser accedidas sin completar de forma total el proceso de autentificación. Específicamente, un atacante puede ser capaz de bypassear los mecanismos 2FA de forma total y ganar acceso a áreas sensibles del usuario sin introducir la OTP. Esto suele deberse a manejo de sesiones inadecuado, controles de acceso pobres o implementación de lógica que no consigue reforzar el requerimiento 2FA.
Explotación
Vamos a http://mfa.thm/labs/second/ y nos registramos con las mismas credenciales que antes.

Típicamente, el atacante necesita entender cómo el login y el proceso 2FA de la aplicación funcionan. En este caso, después de introducir las credenciales, al usuario se le pide que introduzca un OTP.

En lugar de introducir el OTP, el atacante puede intentar manipular la URL o bypassear el paso OTP todo junto. Por ejemplo, el atacante puede buscar acceder directamente a la URL del dashboard (http://mfa.thm/labs/second/dashboard) sin completar los pasos de autentificación requeridos.
Si la aplicación no comprueba correctamente el estado de la sesión u obligación de 2FA o la lógica de la aplicación es errónea o débil, el atacante puede ganar acceso al dashboard.

Profundizando en el Código
El código de abajo es parte del código usado en la página /mfa. Como puedes ver, el $_SESSION['authenticated'] es emitido después de completar el proceso 2FA.
# Function that verifies the submitted 2FA token function verify_2fa_code($code) { if (!isset($_SESSION['token'])) return false; return $code === $_SESSION['token']; } # Function called in the /mfa page if (verify_2fa_code($_POST['code'])) { #If successful, the user will be redirected to the dashboard. $_SESSION['authenticated'] = true; # Session that is used to check if the user completed the 2FA header('Location: ' . ROOT_DIR . '/dashboard'); return; }
Considerando que la implementación de arriba es segura, algunas instancias de emisión de $_SESSION['authenticated'] después del primer paso de autentificación, omitirán el código anterior como se muestra a continuación.
function authenticate($email, $password){ $pdo = get_db_connection(); $stmt = $pdo->prepare("SELECT `password` FROM users WHERE email = :email"); $stmt->execute(['email' => $email]); $user = $stmt->fetch(PDO::FETCH_ASSOC); return $user && password_verify($password, $user['password']); } if (authenticate($email, $password)) { $_SESSION['authenticated'] = true; # This flag should only be issued after the MFA completion $_SESSION['email'] = $_POST['email']; header('Location: ' . ROOT_DIR . '/mfa'); return; }
Como el dashboard de la aplicación sólo comprueba el valor de $_SESSION['authenticated'], sin importar si es true o false, el atacante puede sobrepasarlo fácilmente considerando que tiene conocimiento previo de los endpoints de la aplicación.
Para remediar esto podría partirse la cookie en dos, usando la primera parte para verificar las credenciales correctas y la segunda para el 2FA.
