Durante una auditoría interna del plugin de Patreon para WordPress, el equipo de Jetpack Scan detectó varios puntos débiles que permitirían a alguien tomar el control de un sitio web.
Estas vulnerabilidades se comunicaron a los autores del plugin, que publicaron rápidamente la versión 1.7.2, la cual soluciona todos estos problemas. Si utilizas una versión anterior del plugin, ¡actualízalo hoy mismo!
Sigue leyendo para conocer todos los detalles técnicos. Si esto te supera, no te preocupes. Te ofrecemos Jetpack Scan para que se encargue del análisis de malware y de las actualizaciones o eliminaciones automáticas por ti.
Nuestro equipo identificó varios vectores de ataque, entre ellos las vulnerabilidades de Divulgación de archivos locales, Falsificación de solicitudes entre sitios (CSRF) y Secuencias de comandos entre sitios reflejadas (XSS).
Las vulnerabilidades de divulgación de archivos locales son errores que los actores maliciosos pueden utilizar para acceder a información crítica, como las claves secretas de un sitio web y las credenciales de la base de datos. Las vulnerabilidades de secuencias de comandos entre sitios (XSS) reflejadas y de falsificación de solicitudes entre sitios (CSRF) permiten a los atacantes realizar acciones específicas en nombre de usuarios desprevenidos, engañándolos para que hagan clic en enlaces maliciosos cuidadosamente diseñados.
Si se explotan, algunas de ellas podrían permitir que personas maliciosas se hagan con el control de sitios web vulnerables.
Vulnerabilidad de divulgación de archivos locales
Versiones afectadas: < 1.7.0
ID de CVE: CVE-2021-24227
CVSSv3: 7.5
CWSS: 83.6
public static function servePatronOnlyImage( $image=false ) {
if ( ( !isset( $image ) OR !$image ) AND isset( $_REQUEST['patron_only_image'] ) ) {
$image = $_REQUEST['patron_only_image'];
}
if ( !$image OR $image == '') {
// This is not a rewritten image request. Exit.
return;
}
if ( !( isset( $_REQUEST['patreon_action'] ) AND $_REQUEST['patreon_action'] == 'serve_patron_only_image' ) ) {
return;
}
$upload_locations = wp_upload_dir();
// We want the base upload location so we can account for any changes to date based subfolders in case there are
$upload_dir = substr( wp_make_link_relative( $upload_locations['baseurl'] ) , 1 );
$image = get_site_url() . '/' . $upload_dir . '/' . $image;
if ( current_user_can( 'manage_options' ) ) {
Patreon_Protect::readAndServeImage( $image );
}
// Below define can be defined in any plugin to bypass core locking function and use a custom one from plugin
// It is independent of the plugin load order since it checks if it is defined.
// It can be defined by any plugin until right before the_content filter is run.
if ( apply_filters( 'ptrn/bypass_image_filtering', defined( 'PATREON_BYPASS_IMAGE_FILTERING' ) ) ) {
Patreon_Protect::readAndServeImage( $image );
}
// Check if the image is protected:
$attachment_id = attachment_url_to_postid( $image );
// attachment_url_to_postid returns 0 if it cant find the attachment post id
if ( $attachment_id == 0 ) {
// Couldnt determine attachment post id. Try to get id from thumbnail
$attachment_id = Patreon_Protect::getAttachmentIDfromThumbnailURL( $image );
//No go. Have to get out and serve the image normally
if ( $attachment_id == 0 OR !$attachment_id ) {
Patreon_Protect::readAndServeImage( $image );
Patreon-Connect contenía una vulnerabilidad de divulgación de archivos locales que cualquiera que visitara el sitio podía aprovechar. Mediante este vector de ataque, un atacante podía filtrar archivos internos importantes como wp-config.php, que contiene las credenciales de la base de datos y las claves criptográficas utilizadas para generar nonces y cookies.
Si se explotaba con éxito, este fallo de seguridad podía permitir que actores maliciosos se hicieran completamente con el control del sitio.
XSS reflejado en el formulario de inicio de sesión
Versiones afectadas: < 1.7.2
ID de CVE: CVE-2021-24228
CVSSv3: 8.8
CWSS: 80.6
public static function processPatreonMessages() {
$patreon_error = '';
if ( isset( $_REQUEST['patreon_error'] ) ) {
// If any specific error message is sent from Patreon, prepare it
$patreon_error = ' - Patreon returned: ' . $_REQUEST['patreon_error'];
}
if ( isset( $_REQUEST['patreon_message'] ) ) {
return '<p class="patreon_message">' . apply_filters( 'ptrn/error_message', self::$messages_map[ $_REQUEST['patreon_message'] ] . $patreon_error ) . '</p>';
Patreon-Connect se integra en el formulario de inicio de sesión de WordPress (wp-login.php) y permite a los usuarios autenticarse en el sitio utilizando su cuenta de Patreon. Por desgracia, parte de la lógica de registro de errores que funcionaba entre bastidores permitía que la entrada controlada por el usuario se reflejara sin sanitizar en la página de inicio de sesión.
Para explotar correctamente esta vulnerabilidad, un atacante debe engañar a su víctima para que visite un enlace trampa que contenga código malicioso de JavaScript. Como JavaScript se ejecuta en el contexto del navegador de la víctima, un atacante puede modificar el código oculto en ese enlace para hacer cualquier cosa que permitan los privilegios de ese usuario.
Si este ataque tiene éxito contra un administrador, el script puede hacerse completamente con el control del sitio.
XSS reflejado en la acción AJAX «patreon_save_attachment_patreon_level»
Versiones afectadas: < 1.7.2
ID de CVE: CVE-2021-24229
CVSSv3: 8.8
CWSS: 80.6
$args = array (
'attachment_id' => $attachment_id,
'patreon_level' => $_REQUEST['patreon_attachment_patreon_level'],
'message' => $message,
);
echo self::make_image_lock_interface( $args );
public function make_image_lock_interface( $args = array() ) {
$interface = '';
$interface .= '<div class="patreon_image_lock_modal_content">';
$interface .= '<span class="patreon_image_lock_modal_close">×</span>';
$interface .= ' <form id="patreon_attachment_patreon_level_form" action="/wp-admin/admin-ajax.php" method="post">';
$interface .= '<h1 class="patreon_image_locking_interface_heading">Lock Image</h1>';
$interface .= '<div class="patreon_image_locking_interface_level">';
$interface .= '<span class="patreon_image_locking_interface_input_prefix">$<input id="patreon_attachment_patreon_level" type="text" name="patreon_attachment_patreon_level" value="' . $args['patreon_level'] . '" / ></span>';
El plugin también utiliza un hook AJAX para actualizar el nivel de aportación que los suscriptores de Patreon necesitan para acceder a un archivo adjunto. Esta acción está disponible para las cuentas de usuario con el privilegio «manage_options» (es decir, únicamente para los administradores).
Por desgracia, uno de los parámetros utilizados en este endpoint AJAX no se sanitiza antes de volver a mostrarse al usuario, por lo que el riesgo que representa es el mismo que el de la vulnerabilidad XSS anterior que hemos descrito.
CSRF que permite a los atacantes sobrescribir o crear metadatos de usuario
Versiones afectadas: < 1.7.0
ID de CVE: CVE-2021-24230
CVSSv3: 6.5
CWSS: 42
public function toggle_option() {
if( !( is_admin() && current_user_can( 'manage_options' ) ) ) {
return;
}
$current_user = wp_get_current_user();
$option_to_toggle = $_REQUEST['toggle_id'];
$current_value = get_user_meta( $current_user->ID, $option_to_toggle, true );
$new_value = 'off';
if( !$current_value OR $current_value == 'off' ) {
$new_value = 'on';
}
update_user_meta( $current_user->ID, $option_to_toggle, $new_value );
}
Algunos endpoints no validaban que la solicitud recibida se hubiera enviado como consecuencia de una acción legítima del usuario, algo que puedes hacer mediante nonces. Uno de estos endpoints sin protección permitía a personas maliciosas crear un enlace trampa que, al visitarlo, sobrescribiera o creara metadatos de usuario arbitrarios en la cuenta de la víctima.
Si se explota, este fallo puede utilizarse para sobrescribir el metadato «wp_capabilities», que contiene los roles y privilegios de la cuenta de usuario afectada. Esto prácticamente les impediría acceder al sitio y bloquearía su acceso al contenido de pago.
CSRF que permite a los atacantes desconectar sitios de Patreon
Versiones afectadas: < 1.7.0
ID de CVE: CVE-2021-24231
CVSSv3: 6.5
CWSS: 26.1
if ( isset( $_REQUEST['patreon_wordpress_action'] ) AND $_REQUEST['patreon_wordpress_action'] == 'disconnect_site_from_patreon' AND is_admin() AND current_user_can( 'manage_options' ) ) {
// Admin side, user is admin level. Perform action:
// To disconnect the site from a particular creator account, we will delete all options related to creator account, but we will leave other plugin settings and post gating values untouched
$options_to_delete = array(
'patreon-custom-page-name',
'patreon-fetch-creator-id',
'patreon-creator-tiers',
'patreon-creator-last-name',
'patreon-creator-first-name',
'patreon-creator-full-name',
'patreon-creator-url',
'patreon-campaign-id',
'patreon-creators-refresh-token-expiration',
'patreon-creator-id',
'patreon-setup-wizard-last-call-result',
'patreon-creators-refresh-token',
'patreon-creators-access-token',
'patreon-client-secret',
'patreon-client-id',
'patreon-setup_is_being_done',
'patreon-setup-done',
'patreon-currency-sign',
);
// Ask the API to delete this client:
$creator_access_token = get_option( 'patreon-creators-access-token', false );
$client_id = get_option( 'patreon-client-id', false );
// Exceptions until v1 v2 transition is complete
$api_version = get_option( 'patreon-installation-api-version' );
if ( $api_version == '1' ) {
// Delete override - proceed with deleting local options
foreach ( $options_to_delete as $key => $value ) {
delete_option( $options_to_delete[$key] );
}
update_option( 'patreon-installation-api-version', '2' );
update_option( 'patreon-can-use-api-v2', true );
wp_redirect( admin_url( 'admin.php?page=patreon_wordpress_setup_wizard&setup_stage=reconnect_0') );
exit;
}
Esta vulnerabilidad es similar a la anterior, ya que se trata del mismo tipo de ataque (CSRF), pero dirigido a administradores. Este vector de ataque concreto funciona como el anterior. Un atacante debe conseguir que un administrador que haya iniciado sesión visite un enlace especialmente diseñado.
Como este endpoint específico puede desconectar un sitio de Patreon, los atacantes que se dirijan a este vector de ataque también pueden hacerlo, lo que impediría que el contenido nuevo se sincronizara con el sitio.
Cronología
- Primer intento de contacto (sin éxito) – 4 de diciembre
- Segundo intento de contacto – 11 de diciembre
- Los autores reconocen el informe – 15 de diciembre
- Se publica la versión 1.7.0 – 5 de enero
- Informamos de dos problemas adicionales de XSS – 9 de marzo
- Los autores reconocen el segundo informe – 9 de marzo
- Se publica la versión 1.7.2 – 11 de marzo
Conclusión
Te recomendamos que compruebes la versión actual del plugin Patreon-Connect que utilizas en tu sitio y, si no es la 1.7.2, ¡lo actualices lo antes posible!
En Jetpack, nos esforzamos para asegurarnos de que tus sitios web estén protegidos frente a este tipo de vulnerabilidades. Para ir un paso por delante de las nuevas amenazas, descubre Jetpack Scan, que incluye análisis de seguridad y eliminación automática de malware.
Créditos
Esta divulgación de seguridad ha sido posible gracias a George Stephanis, Fioravante Souza, Miguel Neto, Benedict Singer y Marc Montpas.



