Alerta de seguridad
Nivel de peligrosidad: Alto
CVE-2022–21661
Descripción
El núcleo de wordpress proporciona funciones para que los complementos (plugins) llamen y usen las funciones nativas de wordpress, como: formato de datos, consultas a la BD, etc. Entre las clases que proporciona wordpress, se ha encontrado que la clase utlizada para realizar consultas a la base de datos (WP_Query) es vulnerable a inyección SQL.
Análisis de errores
En la versión 5.8.3, wordpress ha corregido este error, en la comparación de cambios se puede ver que en la función `clean_query` se ha agregado una verificación `$query['field']` antes de procesar la variable `$query['terms']`.
La función `clean_query` se llama desde `get_sql_for_clause`. Al verificar el código de la función, se puede ver que el rol de esta función es crear cláusulas para la condición en una consulta SQL, específicamente su rol será procesar los datos recibidos, combinar esos datos en una condición en la consulta SQL y devolverla a la función principal. Por tanto, se pueden controlar los datos de retorno de esta función, lo que significa que podemos controlar la consulta SQL y realizar la inyección SQL.
Volviendo a la función `clean_query`, cuando no se ha realizado este cambio, por defecto los valores en `$query['terms']` solo se borrarán y luego se llamará a `$this->transform_query( $query, 'term_taxonomy_id');` .
Para evitar caer en `if` (fila 561 en el gráfico), `$query['taxonomy']` debe estar vacío o se debe ingresar un valor para que al comparar en `is_taxonomy_hierarchical` devuelva `false`.
La función `transform_query` verificará si `$query['field'] == $resulting_field`, en caso afirmativo, regresará y no hará más procesamiento, por lo que si la variable `$query['field']` es igual a `term_taxonomy_id`, podemos salir de la función sin cambiar el valor de la variable `$query['terms']`.
Después de salir de la función, el flujo de código de regreso a la posición llamará a `clean_query` una función `get_sql_for_clause`. El valor de la variable `$query['terms']` se usará directamente como condición de consulta SQL y conducirá a la inyección SQL.
Entonces, en resumen, para que ocurra la inyección SQL, se deben cumplir dos condiciones:
- Que `$query['field']` sea igual a `term_taxonomy_id`
- Que `$query['taxonomy']` sea vacío o `is_taxonomy_hierarchical($query['taxonomy']) === false`
El flujo da como resultado el siguiente error:
Explotación
Aunque este error es del núcleo de wordpress, la forma en que el núcleo de wordpress lo usa no desencadena el error, por lo que el error se presenta en complementos (plugins) que realicen llamadas a la clase `WP_Query`, es decir cuando se realicen consultas a la base de datos. La forma de identificar el error es cuando el complemento usa `WP_Query($data)` y el parámetro `$data` se puede controlar.
Por ejemplo, `new WP_Query(json_decode($_POST['query_vars']))`, la carga útil (Payload) sería de la siguiente forma:
`query_vars = {"tax_query": {"0": {"field": "term_taxonomy_id", "terms": ["<inject>"]}}}
o
query_vars = {"tax_query": {"0": {"taxonomy": "nav_menu", "field": true, "terms": ["<inject>"]}}}`
La manera más sencilla de identificar la vulnerabilidad es cuando el modo de depuración (modo debug) está habilitado.
Recursos afectados
WP_Query, core de wordpress anteriores a 5.8.3
Solución/Mitigación
Actualizar WordPress a la versión 5.8.3.
Recomendaciones
Debido a que muchos complementos realizan consultas a la base de datos, se recomienda actualizar WordPress de manera urgente a la versión 5.8.3, también es recomendable mantener activa las actualizaciones automáticas.
Referencias
SQL Injection in Wordpress core (CVE-2022–21661)
WordPress Core WP_Query SQL Injection Information Disclosure Vulnerability