FCSC 2023 - Salty Auth

Enonce

Le lien nous redirige directement ici:

On va devoir vérifier les 2 conditions afin de pouvoir afficher le flag.
Conditions
Nous devons:
- Trouver la longueur du mot de passe
- Générer une collision entre fnv164(password) == fn16v4(hostname+salt)
Longueur du password
Si l’on fournit en GET un parametre ?password=test les comparaisons échouent et le même code source est affiché.
Voici un petit script pour trouver la longueur:
| |
Nous trouvons une longueur de 36.
Bien, toutefois le salt inconnu est bien embêtant …
On pourrait bruteforcer pendant des heures avec ce genre de script mais c’est interdit:
| |
Leak du hostname via phpinfo() ?
Le principal souci pour vérifier la 2nde condition est que nous ne connaissons ni hostname, ni salt.
Nous allons trouver hostname, vous verrez l’utilité dans la partie suivante.
En me repenchant dessus j’ai trouvé une vulnérabilité: on peut appeler une certaine fonction log_attack lors de l’exit():
| |

Et récupérer le hostname:

Réinitialisation du salt via extract()
Une fonction saute au yeux dans ce code, à quoi sert-elle?
| |
Ici réside ce qui nous permettra d’outrepasser la 2nde condition. On trouve rapidement quelques ressources sur extract:
- https://github.com/HackThisSite/CTF-Writeups/blob/master/2016/SCTF/Ducks/README.md
- https://davidnoren.com/post/php-extract-vulnerability/
PHP has a function named extract() to take all provided GET and POST requests and assign them to internal variables. Developers will, at times, use this function instead of manually assigning $_POST[var1] to $var1. This function will overwrite any previously defined variables, including server variables.
Ici nous allons par la register global $SERVER.
En échouant la vérification nous allons pouvoir écraser le variable salt.
Grâce à extract on peut:
- préciser notre password
- écraser le salt afin de contrôler la loose comparison.

On remarque tout de suite la 2nde condition if (hash('fnv164', $password) == hash('fnv164', $secret)):
Voici un script permettant de trouver un password de 36 caractères pour forcer une Loose comparison
| |

Résumons:
| |
Tada!!
