Sorgenti
Sorgenti, assets e script di supporto per le seguenti challenges sono disponibili su GitHub: https://github.com/born2scan/dantectf-21
Web
Beatrice
Descrivere Inferno, Purgatorio e Paradiso è sicuramente un compito arduo. Chissà a quali fonti di ispirazione si potrebbe attingere… Posto che siano tutte valide.
Autore:
ionno
La descrizione della challenge evidenzia la parola fonti. Aprendo la prima pagina, vediamo subito una galleria con tre immagini. La seconda immagine non viene caricata correttamente. Usando Ctrl+U
possiamo vedere le sorgenti della pagina web.
<!DOCTYPE html>
<html>
<head>
<title>Inferno</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="main.css">
</head>
<body>
<h2 class="w3-center"><u>Cerca in profondità</u></h2>
<div class="w3-content w3-display-container">
<img class="mySlides" src="images/img1.jpg" style="width:100%">
<img class="mySlides" src="images/DANTE{0r_53_7u_qU3l_v1RG1l10_3_" style="width:100%"> <!-- <== Part 1 -->
<img class="mySlides" src="images/img3.jpg" style="width:100%">
<button class="w3-button w3-black w3-display-left" onclick="plusDivs(-1)">❮</button>
<button class="w3-button w3-black w3-display-right" onclick="plusDivs(1)">❯</button>
</div>
<script src="main.js"></script>
</body>
</html>
Dal codice si nota subito che l’url della seconda immagine non è valido (linea 16) e più precisamente che si tratta della prima parte della flag. Controllando anche i file sorgenti main.css
e main.js
avremo rispettivamente anche la seconda e la terza parte della flag:
html {
height: 100vh;
background: #707070;
}
.mySlides {
height: 640px;
display:none;
}
body {
margin-top: 3rem;
}
.w3-content {
border: 2px solid #c9c9c9;
}
/* Part 2: qu3LL4_f0N73_Ch3_5p4ND1_d1_ */
var slideIndex = 1;
showDivs(slideIndex);
function plusDivs(n) {
showDivs(slideIndex += n);
}
function showDivs(n) {
var i;
var x = document.getElementsByClassName("mySlides");
if (n > x.length) {slideIndex = 1}
if (n < 1) {slideIndex = x.length}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[slideIndex-1].style.display = "block";
}
// Part 3: P4Rl4R_51_L4rG0_F1uM3}
🏁 DANTE{0r_53_7u_qU3l_v1RG1l10_3_qu3LL4_f0N73_Ch3_5p4ND1_d1_P4Rl4R_51_L4rG0_F1uM3}
Guido Guinizzelli
Drizza la testa, drizza, e vedi a cui s’aperse a li occhi d’i Teban la terra;
Autore:
ionno
Aprendo la pagina web vediamo un canto preso dalla Divina Commedia. Scorrendo (o leggendo) i versi, verso la metà del canto possiamo notare un link bizzarro “Get the flag”. Premendoci sopra veniamo reindirizzati ad una pagina di errore contenente il messaggio Try hEarder. Alludendo la parola hEarder a header, andiamo a controllare quali header HTTP vengono restituiti dal server quando premiamo il link nella pagina iniziale. Per far ciò possiamo usare gli strumenti per sviluppatori del browser. In particolare, usando il tasto F12
possiamo aprire la scheda “Network” per vedere come vengono fatte le richieste HTTP (spuntando “Preserve log” per non perdere le richieste intermedie).
Dai log del browser si nota subito che prima di essere reindirizzati sulla pagina di errore nope.html
, il browser esegue una richiesta a getflag.php
ed il server risponde con uno status code 302 (redirect) ma non prima di fornirci anche un header FLAG contenente la flag.
🏁 DANTE{s0n_GuId0_GuiniZz3lli_e_g1a_m1_pUrg0per_b3N_dol3rM1_pRima_ch_A_l0_sTr3m0}
Virgilio
Chissà quali ricette moderne sono state influenzate dai Lebkuchen di Norimberga, preparati sin dal medioevo.
Autore:
ionno
Dalla descrizione della challenge possiamo dedurre che i cookies (Lebkuchen) del browser siano in qualche modo coinvolti. La prima pagina non è altro che una form di login. Non avendo a disposizione delle credenziali di accesso, non rimane altro che controllare le sorgenti della pagina (CTRL+U
).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Paradiso</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="container">
<div class="card">
<form action="login.php" method="POST">
<div class="label">Username</div>
<input type="text" name="username" id="username" class="form-control"/>
<div class="label">Password</div>
<input type="password" name="password" id="password" class="form-control"/>
<input type="submit" value="Login"/>
</form>
</div>
</div>
<!--TODO remove user guest:guest in production -->
</body>
</html>
Nel codice HTML abbiamo un commento bizzarro che ci fornisce delle possibili credenziali di accesso. Usando guest:guest rispettivamente come username e password possiamo accedere al sistema.
Dal messaggio di benvenuto capiamo che non possiamo ottenere la flag eseguendo l’accesso come guest. Ricaricando la pagina (F5
) vediamo che l’applicazione non ci rimanda alla pagina di login. Ciò significa che in qualche modo il server riesce ad identificarci. Controlliamo se l’applicazione usa dei cookies di autenticazione.
Aprendo gli strumenti sviluppatori (F12
) -> Application -> Cookies osserviamo il seguente cookie:
In particolare il valore Z3Vlc3Q%3D viene decodificato dal base64 come guest. Dovendo identificarci come admin proviamo a modificare il cookie inserendo YWRtaW4= (admin in base64) come valore del cookie. Ricaricando la pagina otteniamo la flag.
🏁 DANTE{b347R1c3_L0D4_d1_D10_v3R4}
Crypto
Cangrande della scala
Ragiono, ragiono, ma Ohibò! Tutto questo Ancora non mi porta a nessuna rivelaZIONE.
Vb ivqv cvh' sbytb'e iviv r ivapragv sne qv abv prageb r qv fr' sne pbeban, cvh' qbypv va ibpr pur va ivfgn yhpragv: pbfv' pvatre yn svtyvn qv Yngban irqrz gnyibygn, dhnaqb y'nrer r' certab, fì pur evgratn vy svy pur sn yn mban. Ar yn pbegr qry pvryb, baq' vb evirtab, QNAGR{fv_gebina_zbygr_tvbvr_pner_r_oryyr} gnagb pur aba fv cbffba gene qry ertab; r 'y pnagb qv dhrv yhzv ren qv dhryyr; puv aba f'vzcraan fì pur yn' fh' ibyv, qny zhgb nfcrggv dhvaqv yr abiryyr.
Autore:
beryxz
Come suggeriscono le lettere in maiuscolo nella descrizione, il testo ha subito una ROTAZIONE.
Effettuando un ROT13 del testo, in mezzo ai versi troviamo la flag.
🏁 DANTE{si_trovan_molte_gioie_care_e_belle}
Catone
Che freddo in cima al Purgatorio… Forse dovrei sbrigarmi a fare questi ultimi
122-91+33
scalini dalla base larga prima che mi comincino a battere i denti.LS4tLiAuLi4uIC4gLi4tLS4tIC4tLS4gLiAuLS4gLS4uIC4gLi0uIC4uLS0uLSAtIC4gLS0gLi0tLiAtLS0gLi4tLS4tIC4tIC4uLS0uLSAtLi0uIC4uLi4gLi4gLi4tLS4tIC4tLS4gLi4gLi4tIC4uLS0uLSAuLi4gLi0gLi4tLS4tIC4tLS4gLi4gLi4tIC4uLS0uLSAuLi4gLi0tLiAuLiAuLSAtLi0uIC4=
Autore:
beryxz
Il testo della challenge è inizialmente codificato in Base64. Questo veniva anche suggerito dalla descrizione.
Decodificato il testo, otteniamo una serie di punti, linee e spazi tipici della codifica Morse.
Effettuando quest’ulteriore decodifica, si ottiene il messaggio da poi inserire all’interno del formato: DANTE{ ... }
.
La codifica del simbolo _
, o ..--.-
, non è propria dello standard Morse. Per questo motivo, al posto del carattere _
era accettato anche il carattere #
🏁 DANTE{che_perder_tempo_a_chi_piu_sa_piu_spiace}
Paolo e Francesca
La matematica si è evoluta molto dal 1300 ad oggi, ma per fortuna è ancora necessario scriverla chiaramente.
Autore:
beryxz
#TODO: switch to getSecurePrime
from Crypto.Util.number import getPrime
FLAG = b"[REDACTED]"
# thanks to Rivest, Shamir and Adleman
m = int.from_bytes(FLAG,'big')
p = getPrime(333)
q = 13555951496777604631139270237917994748488574297776756734164338349749523288010729072351577528529826741
n = p*q
e = 65537
d = pow(e,-1,(p-1)*(q-1))
c = pow(m,e,n)
print("n =",n)
print("e =",e)
print("c =",c)
n = 175785929752996462178434258345343575846309727654642778549721777710133155101066155524234234832005665285890177335737047830024845479693160488020016421557387725264753427132622500860510496841993610209824541
e = 65537
c = 56436323842770213708488806649213159341609690590668828518007196230614202020971388121766028690294024159615280729637193915329424396896043182709647550033626899827367761977429109799023489815880544463491163
In quest’ultima challenge per la serie Crypto, abbiamo un messaggio crittografato con l’algoritmo RSA (textbook). Questo viene anche suggerito alla linea 6, dove vengono elencati gli autori dell’algoritmo.
Il problema si trova alla linea 9 dove viene usato un numero statico al posto di un numero random.
Questo ci permette di trovare l’altro primo generatore $p = n / q$
Possiamo quindi calcolare la chiave privata d
come mostrato alla linea 12 e decrittare il messaggio.
m = pow(c, d, n).to_bytes(64, 'big')
🏁 DANTE{l4sc1at3_0gn3_sp3r4nz4_v01_ch_1ntr4t3}
Misc
Orlando
Non era lunga ancor la nostra via di qua dal sonno, quand’ io vidi un foco ch’emisperio di tenebre vincia.
Autore:
synack
Connettendosi alla porta indicata tramite netcat
o strumenti analoghi venivano proposte casualmente delle terzine da completare:
Su' mi levai, e tutti eran gia' pieni
de l'alto di' i ________ del sacro monte,
e andavam col sol novo a le reni.
-> giron
Una volta completatene tre veniva restituita la flag.
🏁 DANTE{3cc0_l4_f13r4_c0n_l4_c0d4_46uzz4}
Giotto
Guelfi e Ghibellini si sono combattuti per quasi due secoli - che le loro discussioni nascondessero una bandiera segreta dopo tutto?
Autore:
synack
Veniva fornito un lungo file contenente solamente le parole GUELFI e GHIBELLINI, una per riga.
Sostituendo GUELFI
con 0
e GHIBELLINI
con 1
si otteneva la codifica binaria dei caratteri ASCII che compongono la flag. Ogni carattere era rappresentato da 8 bit, aggiungendo zeri a sinistra fino a raggiungere la lunghezza necessaria.
Ecco un link diretto ad una ricetta CyberChef di esempio.
🏁 DANTE{c0m3_qu31_ch3_v4_d1_n0tt3}
Oderisi
C’è chi sostiene che la Divina Commedia contenga dei messaggi nascosti, ma non è detto che il testo originale sia il luogo giusto dove cercarli.
Autore:
synack
La flag era nascosta nel canale alfa (trasparenza) dell’immagine fornita, analizzabile con stegsolve o altri strumenti come StegOnline.
🏁 DANTE{4pr1_l4_m3n73_4_qu3l_ch3_10_71_p4l350}
Farinata
Cosa c’è di meglio di un’allegra melodia per rallegrar d’un cibernetico avventuriero le gloriose avventure? Ma attenzione ai fantasmi in agguato…
Autore:
synack
Il file audio fornito conteneva delle frequenze evidentemente estranee al brano, e l’analisi dello spettro mostrava la flag:
🏁 DANTE{s0tt0_d4ll4_lun4}
Binary
Cacciaguida
Per nostra fortuna il testo della Divina Commedia è chiaramente leggibile. E se delle importanti parole si potessero nascondere anche altrove?
Autore:
beryxz
Viene fornito un binario che sembra mostrare solo una parte della flag.
Utilizzando l’utility strings
, o una corrispettiva anche trovabile online, possiamo vedere tutte le stringhe leggibili all’interno del binario.
Filtrando per la parte iniziale della flag che ci viene data 53m...
, possiamo vedere che dal binario non è stata rimossa la flag per intero.
strings cacciaguida | grep "53m"
🏁 DANTE{53mpr3_14_c0nfu510n_d3_13_p3r50n3_pr1nc1p10_fu_d31_m41_d3_14_c1774d3}
Casella
Dante Alighieri ha senza dubbio lasciato una profonda impronta nella nostra cultura - anzi, quale era il sinonimo giusto…? Traccia?
Autore:
beryxz
Questa volta ci viene chiesta una parola segreta per procedere. Sfortunatamente l’utility strings
non ci è sufficiente, in quanto la flag è inizialmente offuscata tramite delle operazioni XOR.
Senza avviare debugger o decompiler vari, è comunque possibile utilizzare le utility di debug come ltrace
ed strace
per rispettivamente visualizzare le chiamate effettuate alle librerie ed al sistema.
Utilizzando ltrace
possiamo vedere come il nostro input passi dalla funzione strncmp
, la quale controlla l’uguaglianza del nostro input con giust’appunto la flag. Flag che internamente è stata de-offuscata durante l’esecuzione.
ltrace -s 128 ./casella
🏁 DANTE{Ahi_quanto_son_diverse_quelle_foci_da_l_infernali}
Ciacco
Le anime dannate vengono poste innanzi ad un infinito numero di ostacoli insormontabili, ma per fortuna qui ce ne sono solo 4 e ben definiti.
Autore:
beryxz
Per quest’ultima sfida della serie Binary era necessario un debugger come gdb o un decompilatore come Ghidra. Qui di seguito useremo ghidra.
Nella funzione main, viene presa come input una stringa che viene poi passata alla funzione check_input
(riga 17) la quale si presuma effettuerà dei controlli per verificarne la validità.
Possiamo anche vedere una chiamata alla funzione print_flag
(riga 20), la quale però ci mostra una flag redatta. Infatti la flag è salvata solo sul server e viene mostrata inserendo l’input corretto una volta collegati al server indicato nella descrizione.
La funzione check_input
si suddivide in 4 controlli separati.
- Il primo controlla che la lunghezza della stringa sia 21
- Il secondo, terzo e quarto controllano in ordine sparso che tutti i caratteri siano uguali ad alcuni ben definiti.
Segnandosi tutti i caratteri e la loro posizione, otteniamo la parola D1vin4_daN7e_c0MM3d1a
. Inserendo questa parola sul server, vengono effettivamente passati tutti i controlli ed otteniamo la flag.
🏁 DANTE{v01_c1774d1n1_m1_ch14m4573_c14cc0_p32_14_d4nn054_c01p4_d3114_9014_c0m3_7u_v3d1_4114_p109914_m1_f14cc0}
Hardware
Puccio
Circa 500 anni dopo la prima pubblicazione del poema dantesco venne inventato un tanto basilare quanto utile codice.
Autore:
synack
Venivano forniti dei binari da caricare su un Arduino, un ESP32, un ESP8266 o un Raspberry Pico (RP2040).
Una volta programmata la scheda o il simulatore veniva ciclicamente attivato un pin di output (D4 per Arduino ed ESP8266, GPIO27 per ESP32, GP15 per RP2040) che scandiva la flag in codice Morse.
Per facilitarne l’estrazione, i caratteri del codice (.
,_
) venivano contemporaneamente stampati a 9600 baud anche sulla porta seriale predefinita della scheda e quindi, nella maggior parte dei casi, leggibili direttamente da un monitor seriale USB.
La flag era quindi decodificabile dal Morse: VECCHIAFAMA
→ ...- . -.-. -.-. .... .. .- ..-. .- -- .-
🏁 DANTE{VECCHIAFAMA}