29/04/25
SSTI,SQLiiPathTraversal
5 reptes web | CIT CTF 2025
Thanks for sharing!
بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ

I know your browser history
Hola i benvinguts de nou a una altra guia! El bolet és aquí i avui cobriré tots els reptes web de CIT CTF 2025 que vaig jugar amb l'equip Lil L3ak. Hem pogut aconseguir el 2n lloc amb tots els reptes resolts, excepte un repte criptogràfic. També assegurant +13k$ en premis!💰💎


Comencem de seguida 🚀
Reptes
- Trencant l'autenticació
- Commit & Order: Version Control Unit
- Com he analitzat el vostre JSON
- Mantenir-se al dia amb les credencials
- Sr. Chatbot
Trencant l'autenticació

En visitar l'URL, he rebut un formulari d'inici de sessió

Primer va pensar en injecció SQL i, de fet, ho va ser. Simplement vaig iniciar sessió amb
admin' -- i em van redirigir al Tauler d'administració però la bandera no hi eraCom que hi ha una vulnerabilitat d'injecció SQL, la marca pot ser emmagatzemada a la base de dades. Tanmateix, ens enfrontem a un repte: no hi ha cap sortida visible, només una redirecció. Això indica una injecció SQL cega, ja sigui basada en errors o basada en temps, ambdues explotables.
Per accelerar les coses, vaig utilitzar SQLMap, una eina automatitzada per a l'explotació d'injecció SQL
No m'aprofundiré en explicar l'eina, podeu buscar-la
Vaig veure una taula anomenada
secrets, així que a continuació deixem les dades:
CIT{36b0efd6c2ec7132}
Unitat de control de versions de confirmació i comanda

A partir del nom... això té alguna cosa a veure amb git que s'utilitza sovint per al control de versions. De vegades, els desenvolupadors el deixen obert per error a la natura i hi podeu accedir mitjançant
/.git/Accedir-hi em va fer Prohibit

Però l'accés a altres camins de fitxer bàsics com
/.git/HEAD em va donar resposta
Per tant, sembla que el desenvolupador impedeix l'accés als directoris però no als fitxers en si.
Ara, sempre que tingueu un git exposat com aquest, podeu bolcar-lo amb eines com git-dumper. Simplement executeu:
Ara inspeccionant aquest repo podem veure 2 fitxers:
admin.php i index.php. index.php em va aconseguir una contrasenya:
Alerta de spoiler: aquesta passada9f3IC3uj9^zZs'utilitzarà en un altre repte
No he pogut iniciar sessió amb aquesta contrasenya en aquest repte.
Si esteu familiaritzat amb Git (que realment hauríeu de ser), sabríeu sobre les confirmacions, bàsicament instantànies de la vostra base de codi en diferents moments del temps. Podeu navegar a qualsevol d'aquests compromisos per veure el codi tal com estava abans de qualsevol actualització o supressió. En el nostre cas, això és genial, vol dir que podem recuperar el contingut suprimit d'aquesta manera!
Podeu veure les commits anteriors juntament amb els seus missatges mitjançant:

Per anar a una confirmació específica, executeu:
i veureu els fitxers tal com estaven en aquell moment.
Extra: per tornar a l'últim commit, només cal que executeu:
Vaig utilitzar una altra opció per accelerar les coses:
Això mostrarà les diferències entre la vostra versió i la versió anterior, que també us revelarà el codi anterior.
Finalment, vaig obtenir la bandera a la 4a commit base64 codificada:
Q0lUezVkODFmNzc0M2Y0YmMyYWJ9
CIT{5d81f7743f4bc2ab}
Com he analitzat el vostre JSON

Ara bé!
Tenim aquesta pàgina

Per resumir les coses, actua com una base de dades, però obté dades dels fitxers json! I controlem aquest nom de fitxer (aquí ve a la ment un recorregut de camí ✨)
Vaig provar
* i vaig obtenir el següent:
L'URL semblava:
/select?record=*&container=employeesVaig comprovar la font de la pàgina però no vaig trobar res útil, ni el recorregut del camí va funcionar, hi havia algun filtratge al backend
Una de les coses que li agrada a un atacant és un Error! Els errors poden revelar informació sobre el backend i, si la depuració està activada, fins i tot poden filtrar el codi font.
Afegiu això a les vostres notes: intenteu trencar coses i desencadenar errors.
Després de mirar una mica, vaig eliminar el segon paràmetre (contenidor) i vaig obtenir el meu bonic TypeError!

Passant-ho, em vaig sortir amb un codi sucós


El codi és senzill: pren la vostra consulta
container i la passa a la funció clean_container_name(). Aquesta funció extreu la part abans de l'extensió del fitxer i elimina qualsevol ../. El valor retornat es passa directament a la funció os.path.join() i aquest camí s'utilitza per llegir un fitxer.Per exemple, si heu passat
../secrets.txt, es filtrarà a secrets i el camí final serà containers/secretsAra aquí... vas detectar la vulnerabilitat? el codi bàsicament elimina
../, però no ho fa de manera recursiva. Què passa si poseu ../ en un altre ../ perquè sigui ....//, de manera que quan s'elimini ../ el resultat final serà ../Versió més senzilla: suposem que es filtraMush→ PassoMuMushsh→ s'eliminaMush→ el resultat ésMush
Això és tot! Ara passa
....//secrets.txt i... Consulta no vàlidaPer què és això? recordeu el
os.path.splitext(n)[0], això només obté la primera part abans de l'extensió i es converteix en containers/../secrets → secretsPodeu gestionar-ho de dues maneres:
- 1 - Fes servir la mateixa tècnica que acabem d'utilitzar i passa un
../abans de l'extensió, de manera que quan es filtra, acabes correctament:....//secrets.../txt→../secrets.txt - 2 - L'altra manera és només codificar l'URL
.:....//secrets%2Etxt

I obtens la teva bandera (amb la mateixa contrasenya que hem trobat anteriorment, sabràs el seu ús a la propera sessió)
CIT{235da65aa6444e27}
Mantenir-se al dia amb les credencials

Aquest repte, juntament amb el següent, tenia les taxes de resolució més baixes (Això em va fer suposar que implicaria alguna tècnica complicada o avançada i vaig perdre molt de temps repensant-ho)
La configuració era un formulari d'inici de sessió senzill, i tenint en compte que el repte es titulava "Mantenir-se al dia amb les credencials", vaig provar d'utilitzar les credencials que havia trobat anteriorment:
9f3IC3uj9^zZ. Van treballar, i jo estava connectat... però no hi havia cap bandera.Mentre inspeccionava la sol·licitud d'inici de sessió a Burp Suite, em vaig adonar d'alguna cosa estranya:

En lloc d'utilitzar una sol·licitud
POST típica, el formulari va enviar una sol·licitud GET amb les credencials de la cadena de consulta d'URL. Al principi ho vaig descartar, pensant que potser el desenvolupador acabava d'implementar l'inici de sessió d'aquesta manera.Més tard, vaig trobar un camí interessant:
/admin.php. Quan vaig intentar accedir-hi, em van redirigir immediatament a la pàgina d'inici de sessió, així que vaig suposar que l'accés estava restringit. Vaig començar a provar diverses tècniques, inclòs el contraban de sol·licituds HTTP, tot basant-me en el supòsit que el repte havia de ser difícil a causa del seu baix nombre de solucions.Resulta que... la solució va ser estúpidament senzilla: Només vaig haver de canviar la sol·licitud d'inici de sessió de
GET a POST, i em van redirigir a /admin.php, on vaig trobar la bandera.No estic segur de si aquest repte era provar pràctiques de codificació segura o simplement trobar-me una mica 🙂, però de qualsevol manera:
CIT{7bf610e96ade83db}
I ara amb l'últim repte: aquest és bo
Senyor Chatbot

En visitar l'URL, et demana el teu nom:

M'han redirigit a una pàgina de xat:

No hi ha moltes funcionalitats, vaig inspeccionar la font de la pàgina, tenia l'script següent
És només un script senzill que fa que el bot doni algunes respostes, però el més interessant... reflecteix el meu nom! SSTI? Anem a provar-ho
Vaig passar
{{7*7}} i vaig recuperar 7*7, així que estava filtrant. S'han provat diverses càrregues útils, però totes han fallat.A les vostres galetes, se us dóna un testimoni de sessió, concretament un testimoni de sessió de Flask. És similar a un JWT (JSON Web Token), però té algunes diferències clau.
Podeu descodificar-lo fàcilment amb Flask-Unsign
Tens el teu valor
name i admin establerts a 0. Encàrrec massiu?He enviat una altra sol·licitud amb
admin establert a 1. Aquesta vegada he rebut una fitxa més llargaHe pogut establir correctament
admin a 1. He intentat tornar a accedir a la pàgina però no hi ha diferències.Observem un altre valor afegit quan vam explotar l'assignació massiva:
uid, que té el que sembla un valor codificat en base64.Després de la descodificació

Té el nom que vaig passar i alguns bytes:
mushroomb'^\xf2\xc3 ... \xd7\x05'. Vaig provar de descodificar-ho amb hexadecimal però no em va donar res. Al costat positiu tenim una reflexió! el meu name hi ésAfegiu això a les vostres notes: les reflexions són bones!
La reflexió ajuda a identificar els punts d'injecció, on flueixen les dades controlades per l'usuari, que és fonamental per explotar coses com SQLi, injecció d'ordres o injecció de plantilles.
Per provar que he passat
{{7*7}} a name i he definit admin a 1
Bingo! És vulnerable, tinc
49. Aquesta és la nostra manera d'entrar!Vaig utilitzar
{{''.__class__.__mro__[1].__subclasses__()}} a name i vaig obtenir un testimoni enorme
descodificant-lo

A continuació, vaig utilitzar
{{''.__class__.__mro__[1].__subclasses__()[399]('secrets.txt').read()}}
I aquesta és la nostra bandera!
CIT{18a7fbedb4f3548f}
Finalment, aquest escrit s'ha acabat, va trigar +4 hores home lol. 😮💨
Tant de bo això us hagi estat beneficiós. No us oblideu de fer una ullada a la meva X i si teniu cap pregunta, no dubteu a posar-vos en contacte amb mi a Discord.
Ens veiem la propera 🚀! Pau.
Etiquetes:

