dCTF 2021: Very Secure Website
Resolviendo un reto de comparación débil en PHP con un magic hash.
Writeup original del reto: Very Secure Website.md

El código fuente provisto era:
<?php
if (isset($_GET['username']) and isset($_GET['password'])) {
if (hash("tiger128,4", $_GET['username']) != "51c3f5f5d8a8830bc5d8b7ebcb5717df") {
echo "Invalid username";
}
else if (hash("tiger128,4", $_GET['password']) == "0e132798983807237937411964085731") {
$flag = fopen("flag.txt", "r") or die("Cannot open file");
echo fread($flag, filesize("flag.txt"));
fclose($flag);
}
else {
echo "Try harder";
}
}
else {
echo "Invalid parameters";
}
?>
Buscar el hash del username mostró resultados online diciendo que ya había sido crackeado 1000 veces. El valor era admin.
Este fue difícil, especialmente porque fue el primer reto que intenté y no sabía PHP.
Me quedé mirando el source por lo que se sintió como 20 minutos. El chequeo del username era directo, y no podía encontrar nada que inyectar para hacer que la rama de password evaluara a true.
El hash de la contraseña era la única parte extraña.
En un string tan largo, ver solo una letra resaltaba mucho.
Solución
Eventualmente encontré el problema: comparación débil de PHP con ==.
El chequeo de password usaba == en vez de ===:
hash("tiger128,4", $_GET['password']) == "0e132798983807237937411964085731"
Con comparación débil, PHP trata 0e132798983807237937411964085731 como notación científica. Cuando compara ese valor numéricamente, evalúa a 0.
Entonces el objetivo era enviar una contraseña cuyo hash también fuera tratado por PHP como 0.
Por suerte, otras personas ya habían recopilado magic hashes para tiger128,4:
https://github.com/spaze/hashes/blob/master/tiger128%2C4.md
Un valor que funcionaba era LnFwjYqB.
Eso hacía que el chequeo se viera así:
else if (hash("tiger128,4", "LnFwjYqB") == "0e132798983807237937411964085731")
El hash se convierte en:
"0e087005190940152635463034029558" == "0e132798983807237937411964085731"
PHP entonces compara ambos como números:
"0" == "0"
Eso evalúa a true.
Usar admin como username y LnFwjYqB como password dio la flag:
dctf{It's_magic._I_ain't_gotta_explain_shit.}