Expertise
sectorielle
Chaque secteur impose ses propres contraintes réglementaires, ses certifications spécifiques et ses standards de sécurité. ACCEIS maîtrise chaque écosystème.
Sécurité offensive
& audit technique
Identifier les failles réelles, mesurer leur impact et fournir des recommandations actionnables, par l'attaque (sécurité offensive) et par la revue (audit technique).
Gouverner, évaluer
& conformer
Organiser la sécurité dans la durée et répondre à vos exigences réglementaires avec une approche pragmatique, adaptée à votre maturité et à vos enjeux métiers.
Évaluer
Préparer, structurer et piloter vos démarches de certification et de qualification pour maximiser vos chances de succès.
À propos
Une équipe d'experts techniques passionnés que vous pourrez croiser en CTF, colloques et salons cybersécurité.
← Tous les articles

Write-up BreizhCTF 2k23 – Web – Bonjour Ondine!

Un petit coup de ffuf permet d’identifier le fichier robots.txt.

User-agent: *
Disallow : /ondine_secrets.html

Sur la page https://ondine.ctf.bzh/ondine_secrets.html, on retrouve un tableau, sur la vue utilisateur, on ne voit que des cellules blanches, mais en regardant les sources, on voit des classes white et black.

<table>
    <tr><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td></tr>
...
    <tr><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='black'></td><td class='black'></td><td class='black'></td><td class='black'></td><td class='black'></td><td class='black'></td><td class='black'></td><td class='white'></td><td class='black'></td><td class='black'></td><td class='white'></td><td class='white'></td><td class='black'></td><td class='white'></td><td class='black'></td><td class='black'></td><td class='white'></td><td class='white'></td><td class='black'></td><td class='black'></td><td class='black'></td><td class='black'></td><td class='black'></td><td class='black'></td><td class='black'></td><td class='white'></td><td class='white'></td><td class='white'></td><td class='white'></td></tr>
...

Il était possible d’éditer la classe .black dans l’inspecteur CSS pour lui ajouter un fond noir et ainsi voir le QR code s’afficher quasi instantanément. Cependant, sur le coup, je n’y ai pas du tout pensé. J’ai donc fait un rapide script Ruby pour parser le fichier HTML, convertir les white et black en 0 et 1 et transformer ce tableau de bits (bitmap) en image afin d’afficher le QR code à l’aide de mon outil PixelChart.

data = []

File.readlines('ondine_secrets.html').each do |line|
  if /<tr>/.match?(line)
    data << line.split('</td>').map { |x| /white/.match?(x) ? 1 : 0 }[..-2]
  end
end

inline_data = data.flatten

require 'pixelchart' # https://github.com/noraj/pixelchart

options = {
  scale: 10
}
im = PixelChart.new(inline_data, 33, 33, options)
im.draw('ondine.png')

Le QR code contient le chemin vers la page /poke_hidden_form.html.

La page https://ondine.ctf.bzh/poke_hidden_form.html contient un script pour le moins étrange.

<script>
    [][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[]) ...

Cela ressemble à du Brainfuck mais un peu différent, purement compatible en JavaScript. Ce “langage” s’appelle le JSFuck.

On peut alors utiliser un décompileur JSFuck en ligne https://www.dcode.fr/jsfuck-language afin d’y voir plus clair.

var a = prompt("Entrez le mot de passe."); if (a == atob('cGlLYS1waUthIQ==')){ window.location = "/"+a+".html";}

Si l’on décode la chaîne de caractères qui est en base64, on obtient la valeur suivante :

➜ ctf-party cGlLYS1waUthIQ== from_b64
piKa-piKa!

En contactant l’URL https://ondine.ctf.bzh/piKa-piKa!.html on obtient le flag BZHCTF{piKa-piKa!}.

Solution de l’auteur du challenge.

À propos de l’auteur

Article écrit par Alexandre ZANNI alias noraj, Ingénieur en Test d’Intrusion chez ACCEIS.