Starting Nmap 7.80 ( https://nmap.org ) at 2021-07-29 07:28 EET
Nmap scan report for 10.10.11.100
Host is up (0.16s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Bounty Hunters
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Launching firefox and visiting http://10.10.11.100.
![[Pasted image 20210729095006.png]]
There is portal.php so lets check it. But first lets run gobuster to find any hidden directories while we are enumerating the web application.
gobuster dir -u http://10.10.11.100/ -w /opt/SecLists/Discovery/Web-Content/raft-medium-words.txt -t 80 -x php -b 404,403
There is db.php which contains database credentials that may help us if we get LFI.
![[Pasted image 20210729095743.png]]
The portal is under development so lets click on "here".
![[Pasted image 20210729095248.png]]
It takes us to Bounty report system page and it is still in beta.
![[Pasted image 20210729101051.png]]
Looking at the source code i noticed there is no form to be submitted but there is onlick="bountySubmit()" and i think this function is inside bountylog.js.
![[Pasted image 20210729101410.png]]
Looking at bountylog.js, bountySubmit() function is sending the user input data to tracker_diRbPr00f314.php in base64 encoded XML form and getting the response on the page.
So i think it may be XXE injection.
![[Pasted image 20210729101717.png]]
Lets put some data and intercept the request with burpsuite and send to Repeater to play with it.
The data being sent is base64 encoded then URL encoded and the user input is reflecting on the page.
![[Pasted image 20210729103056.png]]
So to be able to inject XML data we need to decode this string and inject our data then encoding it again.
First we URL decode it (CTRL+SHIFT+U) and then base64 decode it (CTRL+SHIFT+B).
![[Pasted image 20210729103557.png]]
Lets see if we can declare a new XML entity as following.
![[Pasted image 20210729103936.png]]
https://book.hacktricks.xyz/pentesting-web/xxe-xee-xml-external-entity
By base64 encoding (CTRL+B) then URL encoding (CTRL+U) it we get the number 3 in the response. Now we know we have XXE injection. ![[Pasted image 20210729104145.png]] Now lets try Reading /etc/passwd. There is a user on the box called "development" ![[Pasted image 20210729094300.png]] Remember db.php file we got from gobuster earlier? lets read it and get the creds. Reading db.php using PHP filter wrapper which converts a text to base64 string to avoid executing PHP scripts. ![[Pasted image 20210729094420.png]] Then lets decode the string to get the credentials of the database.
<?php
// TODO -> Implement login system with the database.
$dbserver = "localhost";
$dbname = "bounty";
$dbusername = "admin";
$dbpassword = "m19RoAU0hP41A1sTsq6K";
$testuser = "test";
?>
![[Pasted image 20210729094824.png]]
We didn't see any login page on the web app but we have SSH port open and development user on the box, lets try SSHing to development user using this password. And successfully logged in! ![[Pasted image 20210729104856.png]] Reading user flag
cf8a830e415b3f8943af3ca4b9a5493c
There is contract.txt that says
I set up the permissions for you to test this. Good luck.
![[Pasted image 20210729110552.png]]
Lets check what we can do with sudo -l
, we can run Skytrain internal tool as root.
![[Pasted image 20210729135402.png]]
Lets take a look at this script
#Skytrain Inc Ticket Validation System 0.1
#Do not distribute this file.
def load_file(loc):
if loc.endswith(".md"):
return open(loc, 'r')
else:
print("Wrong file type.")
exit()
def evaluate(ticketFile):
#Evaluates a ticket to check for ireggularities.
code_line = None
for i,x in enumerate(ticketFile.readlines()):
if i == 0:
if not x.startswith("# Skytrain Inc"):
return False
continue
if i == 1:
if not x.startswith("## Ticket to "):
return False
print(f"Destination: {' '.join(x.strip().split(' ')[3:])}")
continue
if x.startswith("__Ticket Code:__"):
code_line = i+1
continue
if code_line and i == code_line:
if not x.startswith("**"):
return False
ticketCode = x.replace("**", "").split("+")[0]
if int(ticketCode) % 7 == 4:
validationNumber = eval(x.replace("**", ""))
if validationNumber > 100:
return True
else:
return False
return False
def main():
fileName = input("Please enter the path to the ticket file.\n")
ticket = load_file(fileName)
#DEBUG print(ticket)
result = evaluate(ticket)
if (result):
print("Valid ticket.")
else:
print("Invalid ticket.")
ticket.close
main()
The tool uses eval on one line of the opened file which we can abuse this to get a shell on the box, but there are some conditions we must satisfy.
- The file name must end with .md.
- The first line in the file starts with # Skytrain Inc.
- The second line starts with ** ## Ticket to **.
- The third line starts with Ticket Code:.
- The last line starts with ** followed by a number % 7 = 4 followed by a + ( The number can be 7+4 or 14+4 or 21+4 or ....) so 11 will be fine. After satisfying all the condition we reach the eval function where it will evaluate this line. ![[Pasted image 20210729141230.png]] Our file will look like this one but on the fourth line we will add our command to be executed. ![[Pasted image 20210729145814.png]] Now lets create the file, as you can see the first three lines satisfy the conditions and the first number is 11, means 11%7=4 is true so it executes the eval command. ![[Pasted image 20210729145953.png]] Run the tool with sudo. sudo python3.8 /opt/skytrain_inc/ticketValidator.py and enter the path to the .md file. As you can see it executes whoami as root. ![[Pasted image 20210729150441.png]] Now for the root shell we only need to change whoami to bash. ![[Pasted image 20210729150658.png]] And we have rooted the box :D ![[Pasted image 20210729150753.png]] Reading root flag
92d1b412e1879ec13d41d29d436f4952