Blog

  • 100% Noticies

Un fallo crítico en un plugin para WordPress conduce a borrado de base de datos y omisión de autenticación

themegrill-demo-importer

Un fallo crítico en un plugin para WordPress conduce a borrado de base de datos y omisión de autenticación

El plugin ThemeGrill Demo Importer tiene más de 200,000 instalaciones activas y se puede usar para importar contenido de demostración de temas oficiales de ThemeGrill, widgets y configuraciones de temas con solo un clic.

el recuento de instalaciones se ha reducido a 100K +. Indica que muchas personas han comenzado a desinstalar el complemento según las estadísticas proporcionadas por el repositorio de complementos de WordPress. Aquí está la caché de Google que muestra más de 200.000 instalaciones el 15 de febrero.

En las versiones 1.3.4 y posteriores y en las versiones 1.6.1 y posteriores, existe una vulnerabilidad que permite a cualquier usuario no autenticado borrar toda la base de datos a su estado predeterminado, luego de lo cual se registra automáticamente como administrador.

El requisito previo es que debe haber un tema instalado y activado que fue publicado por ThemeGrill. Para iniciar sesión automáticamente como administrador, debe haber un usuario llamado «admin» en la base de datos. Independientemente de esta condición, la base de datos se borrará a su estado predeterminado.

Según el historial de confirmación de SVN, este problema ha existido en el código durante aproximadamente 3 años, desde la versión 1.3.4.

Detalles técnicos

Una vez que el complemento detecta que un tema ThemeGrill está instalado y activado, carga el archivo /includes/class-demo-importer.php que engancha reset_wizard_actions en admin_init en la línea 44.

El enlace admin_init se ejecuta no solo en el entorno de administración sino también en llamadas a /wp-admin/admin-ajax.php que no requieren que un usuario se autentique.

La función reset_wizard_actions se parece un poco a la siguiente (código irrelevante eliminado):

public function reset_wizard_actions() {
		global $wpdb, $current_user;

		if ( ! empty( $_GET['do_reset_wordpress'] ) ) {

			///

			if ( 'admin' != $current_user->user_login ) {
				$user = get_user_by( 'login', 'admin' );
			}

			if ( empty( $user->user_level ) || $user->user_level < 10 ) {
				$user = $current_user;
			}

			// Drop tables.
			$drop_tables = $wpdb->get_col( sprintf( "SHOW TABLES LIKE '%s%%'", str_replace( '_', '\_', $wpdb->prefix ) ) );
			foreach ( $drop_tables as $table ) {
				$wpdb->query( "DROP TABLE IF EXISTS $table" );
			}

			// Installs the site.
			$result = wp_install( $blogname, $user->user_login, $user->user_email, $blog_public );

			// Updates the user password with a old one.
			$wpdb->update(
				$wpdb->users,
				array(
					'user_pass'           => $user->user_pass,
					'user_activation_key' => '',
				),
				array( 'ID' => $result['user_id'] )
			);

			// Set up the Password change nag.
			$default_password_nag = get_user_option( 'default_password_nag', $result['user_id'] );
			if ( $default_password_nag ) {
				update_user_option( $result['user_id'], 'default_password_nag', false, true );
			}

			///

			// Update the cookies.
			wp_clear_auth_cookie();
			wp_set_auth_cookie( $result['user_id'] );

			// Redirect to demo importer page to display reset success notice.
			wp_safe_redirect( admin_url( 'themes.php?page=demo-importer&browse=all&reset=true' ) );
			exit();
		}
	}

Aquí vemos que no hay verificación de autenticación y solo el parámetro do_reset_wordpress debe estar presente en la URL en cualquier página basada en «admin» de WordPress, incluyendo /wp-admin/admin-ajax.php.

Si actualmente no hemos iniciado sesión, recuperará el objeto de usuario «admin» de WordPress y luego eliminará todas las tablas de WordPress que comiencen con el prefijo de base de datos de WordPress definido.

Una vez que se hayan eliminado todas las tablas, rellenará la base de datos con la configuración y los datos predeterminados, después de lo cual establecerá la contraseña del usuario «admin» en su contraseña previamente conocida.

Sin embargo, esto no importa ya que iniciamos sesión automáticamente como «admin» cerca del final de la función. Si el usuario «admin» no existe en la base de datos, la tabla de usuarios permanecerá vacía y no se iniciará sesión automáticamente como cualquier usuario.

El parche

El parche se puede encontrar aquí, que muestra que agregaron una verificación current_user_can (‘manage_options’) al método reset_wizard_actions.

Esta es una vulnerabilidad grave y puede causar una cantidad significativa de daños. Dado que no requiere una carga útil de aspecto sospechoso al igual que nuestro hallazgo anterior en InfiniteWP , no se espera que ningún firewall bloquee esto de manera predeterminada y es necesario crear una regla especial para bloquear esta vulnerabilidad.

Cronograma

06-02-2020 – Descubrimiento del problema y lanzamiento de un parche para todos los clientes de WebARX.
06-02-2020 : informó el problema al desarrollador del complemento.
11-02-2020 – Segundo intento de contactar al desarrollador.
14-02-2020 : correo electrónico recibido del desarrollador, reenviado el problema.
16-02-2020 – El desarrollador publicó una nueva versión que soluciona el problema.

Indicadores de compromiso

Los atacantes a menudo supervisan los registros de cambios de complementos para detectar correcciones de errores de seguridad y comparar diferentes versiones para ver qué se corrigió. Esto permite que los atacantes actúen antes de que los usuarios hayan actualizado el complemento. Por eso es muy importante actualizar los complementos lo más rápido posible.

Hemos estado monitoreando de cerca la vulnerabilidad de ThemeGrill Demo Importer y hemos visto esta vulnerabilidad explotada desde el lanzamiento del parche.

WebARX ha bloqueado más de 16,000 ataques contra esta vulnerabilidad desde el 16 de febrero.