Skip to content

Je hack un cluster Kubernetes – Partie 2

Reeeee ! 😄

On continue notre aventure pour venir à bout de ce cluster kube!! Si vous vous demandez de quoi je parle. C’est sûrement parce que vous n’avez pas encore lu la partie 1. 

Allez, session de rattrapage juste ici

Maintenant que tout le monde est à jour, on est reparti ! 🚀

Task 3 : Powerhouse of Pod’s Storage

N’ayant toujours pas accès au cluster, on va aller voir dans /var/lib/k0s. Il y a un répertoire  containerd. Vu que la task parle de pod, de containers, je pense que l’on peut aller voir ce qu’il y a là-dedans !

root@johnny:~# ls -la /var/lib/k0s/containerd/
total 48
drwx--x--x 12 root root 4096 Feb 10  2022 .
drwxr-xr-x  9 root root 4096 Feb 10  2022 ..
drwxr-xr-x  4 root root 4096 Feb 10  2022 io.containerd.content.v1.content
drwxr-xr-x  4 root root 4096 Feb 10  2022 io.containerd.grpc.v1.cri
drwx--x--x  2 root root 4096 Feb 10  2022 io.containerd.metadata.v1.bolt
drwx--x--x  2 root root 4096 Feb 10  2022 io.containerd.runtime.v1.linux
drwx--x--x  3 root root 4096 Feb 10  2022 io.containerd.runtime.v2.task
drwx------  3 root root 4096 Feb 10  2022 io.containerd.snapshotter.v1.aufs
drwx------  2 root root 4096 Feb 10  2022 io.containerd.snapshotter.v1.btrfs
drwx------  3 root root 4096 Feb 10  2022 io.containerd.snapshotter.v1.native
drwx------  3 root root 4096 Feb 10  2022 io.containerd.snapshotter.v1.overlayfs
drwx------  2 root root 4096 Feb 10  2022 tmpmounts

Ne sachant pas vraiment où regarder, on va faire un grep sur tous les fichiers, en cherchant le mot « password »

root@johnny:/var/lib/k0s/containerd# grep -iR "password"
io.containerd.snapshotter.v1.overlayfs/snapshots/31/fs/usr/share/common-licenses/GPL-3:source code form), and must require no special password or key for
io.containerd.snapshotter.v1.overlayfs/snapshots/31/fs/usr/share/common-licenses/GPL:source code form), and must require no special password or key for
io.containerd.snapshotter.v1.overlayfs/snapshots/31/fs/etc/services:shell               514/tcp         cmd syslog      # no passwords used
[..SNIP..]

Rien de bien intéressant à première vue, mais on va quand même aller voir de plus prêt ce qu’il y a dans io.containerd.snapshotter.v1.overlayfs/snapshots/31/fs

root@johnny:/var/lib/k0s/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/31/fs# ls -la home/
total 12
drwxr-xr-x  3 65532 65532 4096 Jan  1  1970 .
drwxr-xr-x 16 root  root  4096 Feb 10  2022 ..
drwx------  2 65532 65532 4096 Jan  1  1970 nonroot

root@johnny:/var/lib/k0s/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/31/fs# ls -la home/nonroot/
total 8
drwx------ 2 65532 65532 4096 Jan  1  1970 .
drwxr-xr-x 3 65532 65532 4096 Jan  1  1970 ..

M’ouais, pas ouf… 😒

J’ai l’impression qu’il y a un filesystem pour chaque snapshot. Je ne vais pas me farcir toute l’énumération à la main, on va se faire un bon vieux script bash !

#!/bin/bash

# Boucle sur les répertoires de 1 à 44
for i in {1..44}; do
    if [[ -d "$i" ]]; then
        echo "Contenu du répertoire $i :"
        ls -la "$i/fs/home"
        echo "-----------------------------"
    else
        echo "Le répertoire $i n'existe pas."
        echo "-----------------------------"
    fi
done

Suite à l’exécution on obtient :

-----------------------------
Contenu du répertoire 31 :
total 12
drwxr-xr-x  3 65532 65532 4096 Jan  1  1970 .
drwxr-xr-x 16 root  root  4096 Feb 10  2022 ..
drwx------  2 65532 65532 4096 Jan  1  1970 nonroot
-----------------------------
Contenu du répertoire 37 :
total 12
drwxr-xr-x 3 root root 4096 Feb  7  2022 .
drwxr-xr-x 3 root root 4096 Feb 10  2022 ..
drwxr-xr-x 2 root root 4096 Feb  7  2022 ubuntu
-----------------------------
Contenu du répertoire 38 :
total 12
drwxr-xr-x 3 root root 4096 Feb  7  2022 .
drwxr-xr-x 3 root root 4096 Feb 10  2022 ..
drwxr-xr-x 3 root root 4096 Feb  7  2022 ubuntu
-----------------------------

Ok ok, maintenant, il faudrait voir ce que ces répertoires contiennent :

root@johnny:/var/lib/k0s/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots# ls -la 31/fs/home/nonroot/
total 8
drwx------ 2 65532 65532 4096 Jan  1  1970 .
drwxr-xr-x 3 65532 65532 4096 Jan  1  1970 ..

root@johnny:/var/lib/k0s/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots# ls -la 37/fs/home/ubuntu/
total 8
drwxr-xr-x 2 root root 4096 Feb  7  2022 .
drwxr-xr-x 3 root root 4096 Feb  7  2022 ..

root@johnny:/var/lib/k0s/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots# ls -la 38/fs/home/ubuntu/
total 12
drwxr-xr-x 3 root root 4096 Feb  7  2022 .
drwxr-xr-x 3 root root 4096 Feb  7  2022 ..
drwxr-xr-x 3 root root 4096 Feb  7  2022 jokes

Ahhhhh, le répertoire 38 contient un élément intéressant ! Continuons notre énumération :

root@johnny:/var/lib/k0s/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots# ls -la 38/fs/home/ubuntu/jokes/
total 28
drwxr-xr-x 3 root root 4096 Feb  7  2022 .
drwxr-xr-x 3 root root 4096 Feb  7  2022 ..
-rw-r--r-- 1 root root 1284 Feb  7  2022 crush.jokes
-rw-r--r-- 1 root root  718 Feb  7  2022 dad.jokes
drwxr-xr-x 8 root root 4096 Feb  7  2022 .git
-rw-r--r-- 1 root root  997 Feb  7  2022 mom.jokes
-rw-r--r-- 1 root root 1160 Feb  7  2022 programming.jokes

Je connais un petit tool bien pratique pour analyser un répertoire contenant un répertoire .git : https://github.com/internetwache/GitTools/tree/master/Extractor

Une fois le script extractor.sh téléchargé et placé sur la machine de la victime, nous pouvons exécuter tout ça :

# bash extractor.sh /var/lib/k0s/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/38/fs/home/ubuntu/jokes jokesdump
###########
# Extractor is part of https://github.com/internetwache/GitTools
#
# Developed and maintained by @gehaxelt from @internetwache
#
# Use at your own risk. Usage might be illegal in certain circumstances. 
# Only for educational purposes!
###########
[*] Destination folder does not exist
[*] Creating...
[+] Found commit: 4b2c2d74b31d922252368c112a3907c5c1cf1ba3
[+] Found file: /tmp/jokesdump/0-4b2c2d74b31d922252368c112a3907c5c1cf1ba3/dad.jokes
[+] Found file: /tmp/jokesdump/0-4b2c2d74b31d922252368c112a3907c5c1cf1ba3/king.jokes
[+] Found file: /tmp/jokesdump/0-4b2c2d74b31d922252368c112a3907c5c1cf1ba3/mom.jokes
[+] Found commit: 2be20457c290fa1e8cc8d18cd5b546cec474691c
[+] Found file: /tmp/jokesdump/1-2be20457c290fa1e8cc8d18cd5b546cec474691c/dad.jokes
[+] Found file: /tmp/jokesdump/1-2be20457c290fa1e8cc8d18cd5b546cec474691c/mom.jokes
[+] Found commit: 224b741fa904ee98c75913eafbefa12ac820659f
[+] Found file: /tmp/jokesdump/2-224b741fa904ee98c75913eafbefa12ac820659f/crush.jokes
[+] Found file: /tmp/jokesdump/2-224b741fa904ee98c75913eafbefa12ac820659f/dad.jokes
[+] Found file: /tmp/jokesdump/2-224b741fa904ee98c75913eafbefa12ac820659f/mom.jokes
[+] Found file: /tmp/jokesdump/2-224b741fa904ee98c75913eafbefa12ac820659f/programming.jokes
[+] Found commit: 22cd540f3df22a2f373d95e145056d5370c058f5
[+] Found file: /tmp/jokesdump/3-22cd540f3df22a2f373d95e145056d5370c058f5/crush.jokes
[+] Found file: /tmp/jokesdump/3-22cd540f3df22a2f373d95e145056d5370c058f5/dad.jokes
[+] Found file: /tmp/jokesdump/3-22cd540f3df22a2f373d95e145056d5370c058f5/mom.jokes
[+] Found commit: cc342469e2a4894e34a3e6cf3c7e63603bd4753e
[+] Found file: /tmp/jokesdump/4-cc342469e2a4894e34a3e6cf3c7e63603bd4753e/dad.jokes

Ok déjà, il y a eu plusieurs commits, regardons ça de plus près :

root@johnny:/tmp/jokesdump# cat 04b2c2d74b31d922252368c112a3907c5c1cf1ba3/*

tree c6cda34805f659e3ed7e9a3f6fdcca15dd1cb8a7
parent 2be20457c290fa1e8cc8d18cd5b546cec474691c
author Aju100 <ajutamang10@outlook.com> 1644252733 +0545
committer Aju100 <ajutamang10@outlook.com> 1644252733 +0545

feat: add cold.joke

"I'm afraid for the calendar. Its days are numbered."
"My wife said I should do lunges to stay in shape. That would be a big step forward."
"Why do fathers take an extra pair of socks when they go golfing?" "In case they get a hole in one!"
"Singing in the shower is fun until you get soap in your mouth. Then it's a soap opera."
"What do a tick and the Eiffel Tower have in common?" "They're both Paris sites."
"What do you call a fish wearing a bowtie?" "Sofishticated."
"How do you follow Will Smith in the snow?" "You follow the fresh prints."
"If April showers bring May flowers, what do May flowers bring?" "Pilgrims."
"I thought the dryer was shrinking my clothes. Turns out it was the refrigerator all along."THM{this_joke_is_cold_joke}"Motherhood: Because going to the bathroom in private is over-rated."
[..SNIP..]

Bingo, on a notre flaaaag ! 🥳

Task 4 : Hack a job at FANG

Bon, j’avoue, queeeeee je n’avais pas fait le rapprochement tout de suite avec le titre de la task : Hack a Job at FANG. On est dans une room sur Kube et ça parle de jobs si vous voyez ce que je veux dire. Oui j’ai perdu un peu de temps 😅

Juste pour rappel, on n’a toujours pas accès au cluster 🥲

Il va falloir refaire notre technique de pirate pour inspecter les jobs :

# strings /var/lib/k0s/db/state.db | grep registry/job
/registry/jobs/internship/internship-jobk8s
/registry/jobs/internship/internship-job
/registry/jobs/internship/internship-job
/registry/jobs/internship/internship-job
/registry/jobs/internship/internship-job
b/registry/jobs/internship/internship-job
/registry/jobs/internship/internship-job
/registry/jobs/internship/internship-job
/registry/jobs/internship/internship-job
/registry/jobs/internship/internship-job
/registry/jobs/internship/internship-job
/registry/jobs/internship/internship-job
/registry/jobs/internship/internship-job
/registry/jobs/internship/internship-job
X/registry/jobs/internship/internship-job
&/registry/jobs/internship/internship-job

Allez, on ne change pas une équipe qui gagne, on énumère… encore… (c’est cool le hacking hein ? 😅)

# strings /var/lib/k0s/db/state.db | grep -A30 /registry/jobs/internship/internship-jobk8s
/registry/jobs/internship/internship-jobk8s
batch/v1
internship-job
internship"
*$11cf55dc-7903-4b78-b9d3-62cf241ad26d2
 batch.kubernetes.io/job-tracking
kubectl-create
Update
batch/v1"
FieldsV1:
{"f:spec":{"f:backoffLimit":{},"f:completionMode":{},"f:completions":{},"f:parallelism":{},"f:suspend":{},"f:template":{"f:spec":{"f:containers":{"k:{\"name\":\"internship-job\"}":{".":{},"f:command":{},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}}}B
controller-uid
$11cf55dc-7903-4b78-b9d3-62cf241ad26d2
controller-uid
$11cf55dc-7903-4b78-b9d3-62cf241ad26dZ
job-name
internship-jobz
internship-job
busybox
echo
(26c3d1c068e7e01599c3612447410b5e56c779f1*
/dev/termination-logr
Always
File
Never
ClusterFirstB
default-scheduler
NonIndexedP
/registry/rolebindings/kube-system/system::extension-apiserver-authentication-readerk8s
rbac.authorization.k8s.io/v1
RoleBinding

On fait un petit saut dans le temps. Je vous passe les longues heures à tourner en rond avec mes grep mdr. J’avoue, j’ai péché mon père… Je suis allé voir le write-up… Maiiiiis je n’étais vraiment pas loin de la solution pour ma défense 😅. D’ailleurs, on voit le flag encodé dans ma commande précédente 

Ça ressemble fortement à du MD5 ça non ? 26c3d1c068e7e01599c3612447410b5e56c779f1. Essayons de le décoder avec  Crackstation

Et youhouuuuuu, c’était bel et bien le flag 🥳

Conclusion

Si vous êtes arrivé jusqu’ici, j’espère que vous avez pu découvrir quelques techniques de hackeeerz ahah. 😈

Blague à part, on le sait tous, Kubernetes est ultra populaire, mais il ne suffit pas de lancer quelques commandes kubectl ou de déployer des charts Helm pour en maîtriser tous les aspects. La sécurité est un pilier essentiel ! Si ces deux articles ont pu attirer votre attention sur ce sujet, alors mon objectif est atteint. 😄

Je sais que cet article est un peu différent de ce que je fais habituellement. N’hésitez pas à me dire si vous aimeriez en voir plus dans ce style !

Published inNon classé

Be First to Comment

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *