Currently working as a Senior Consultant at Netcompany spending my full-time job solving the SharePoint riddles. In the free time I'm expanding my understanding of cybersecurity through hacking activities. Git fanboy.
cURL As A Service or CAAS is a brand new Alien application, built so that humans can test the status of their websites. However, it seems that the Aliens have not quite got the hang of Human programming and the application is riddled with issues.
Complete write up for the CAAS challenge at Cyber Apocalypse 2021 CTF hosted by HackTheBox.eu. This article is a part of a CTF: Cyber Apocalypse 2021 series. You can fork all my writeups directly from the GitHub.
Learn more from additional readings found at the end of the article. I would be thankful if you mention me when using parts of this article in your work. Enjoy!
We are given the IP and a port as a target of evaluation:
138.68.178.56:32236
And web application source code dump.
Recon
Initial scan with nmap:
$ sudo nmap -A -p 32236 138.68.178.56
Starting Nmap 7.91 ( https://nmap.org ) at 2021-04-23 07:40 CEST
Nmap scan report for 138.68.178.56
Host is up (0.0050s latency).
PORT STATE SERVICE VERSION
32236/tcp open http nginx
|_http-title: Web Threat Blocked
|_http-trane-info: Problem with XML parsing of /evox/about
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: bridge
Running: Oracle Virtualbox
OS CPE: cpe:/o:oracle:virtualbox
OS details: Oracle Virtualbox
Network Distance: 2 hops
TRACEROUTE (using port 80/tcp)
HOP RTT ADDRESS
1 0.22 ms XXX.XXX.XXX.XXX
2 0.28 ms 138.68.178.56
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 39.10 seconds
Port 32236 is an TCP open port serving a nginx web applications. So lets look it up.
Website
Site presents itself as some service using presumably curl to query IP addresses. But providing it an IP address ends with the error message.
This one is utmost interesting as it show how the request parameter is parsed and used. Controller takes the ip POST data value, creates CommandModel from it (I'll look at this class later) and executes the command. The result is returned from the controller as a JSON.
Ok, we have a main point of interest. We can see that constructor builds the curl command from the input parameter (remember, that this is the value that is being passed in the POST). From the man curl:
-s, silent or quiet mode. Don't show progress meter or error messages.
-L, (HTTP) If the server reports that the requested page has moved to a different location (indicated with
a Location: header and a 3XX response code), this option will make curl redo the request on the new
place.
Ok, so we have a red flag here - the value that is being passed in the request is used to build a shell command that is executed. Ok, but what about escapeshellcmd?
escapeshellcmd ( string $command ) : string
Let's start from the official PHP Manual escapeshellcmd page.
Escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands. This function should be
used to make sure that any data coming from user input is escaped before this data is passed to the exec() or system() functions, or to the backtick operator.
Following characters are preceded by a backslash: &#;`|*?~<>^()[]{}$\, \x0A and \xFF. ' and " are escaped only if they are not paired.
Ok, so this function prevents from executing multiple commands by escaping ex. pipe and semicolon characters (commands like ls; rm -rf; won't work).
But what it doesn't do and what can be exploited (and will be in this box) is passing an arbitrary number of arguments. We can read about further down.
Warning: escapeshellcmd() should be used on the whole command string, and it still allows the attacker to pass arbitrary number of arguments.
For escaping a single argument escapeshellarg() should be used instead.
Ok, so we have a vulnerability we're going to exploit.