All your Kube are belong to us

Andy Repton, Mission Critical Engineer @ Schuberg Philis

@SethKarlo

arepton@schubergphilis.com

Agenda

  • Kubernetes Admin Best Practises
  • CVE-2018-1002105 anonymous auth via aggregated API Servers
  • Manipulating the Kubelet for privilege escalation
  • CVE-2018-1002105 privilege escalation
  • Manipulating Cloud Providers metadata for privilege escalation

Kubernetes Best Practises for Cluster admins (not creators)

Wait. What's the difference?

Today, with managed Kubernetes becoming more common, your cluster creator could be a public cloud provider, a third party company or, indeed, perhaps you. As time goes on, I believe these roles will continue to diverge as Kubernetes becomes more commoditised. 

Authentication, Authorization and Admission Control

AuthN

  • AuthN and AuthZ are strictly separated in K8S. It's only who you are and the groups you're in.
  • Types of Authentication include:
    • Client Certificates
    • Bearer Tokens
    • Basic Auth
    • OpenID Tokens
    • Webhook Authenticators
  • AuthN has a username, UID and Groups that are passed to AuthZ

AuthZ

  • AuthZ defines what you're allowed to do in the cluster, either cluster wide or namespace restricted
  • RBAC is the default authorization system today, replacing ABAC
  • There are also third party webhooks you can use for AuthZ with Open Source projects allowing you more complex control over your resources

Admission Controllers

  • Admission controllers intercept incoming requests and can make decisions on them
  • Special Admission Controllers are the mutating and validating webhook controllers, which allows for controllers not compiled into the apiserver

Recommended Controllers to enable

Controller Purpose
NamespaceLifecycle Can't delete default, kube-system, kube-public.
Can't create in Terminating namespaces.
LimitRanger Enforces LimitRanges inside the cluster.
ServiceAccount Enables automation of ServiceAccounts.
DefaultStorageClass Allows users to not have to specify a StorageClass for PvCs.
DefaultTolerationSeconds Sets the default toleration to 5 mins if not set for pods.
MutatingAdmissionWebhook Enables calling of a mutating webhook for new requests
ValidatingAdmissionWebhook Enables calling of a validating webhook for new requests
Priority Enforces the use of priority for new pods
ResourceQuota Enforces ResourceQuotas inside the cluster.
kube-apiserver --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,Priority,ResourceQuota

Note: all of these are default, but v1.13 also adds PersistentVolumeClaimResize to the default

Pod Security Policies

  • Allows for fine grained control over what pods can and cannot do
  • For example, they can restrict things like:
    • Which host paths can be mounted, if any
    • If a pod is allowed to be privileged
    • Which hostPorts are allowed to be used
    • Which volume types are allowed to be used
    • Plus more

Network Policies

  • Allows for fine grained control over what pods are allowed to talk to
  • Effectively an ACL and allows specification of source, destination, ingress, egress, port numbers and protocols
  • Requires a network provider that supports them, which include (alphabetically)
    • Calico
    • Canal
    • Kube-Router
    • Romana
    • Weave Net 

Ok great! You've done everything possible as an admin to secure with best practises

Why, that's a lovely cluster you have there. Sure would be a shame if something were to... happen to it

CVE-2018-1002105

Pretty much every Kubernetes admin on Dec. 3rd

It comes in two flavours, using the same underlying exploit

  • Anonymous Information leak via aggregated API Servers (metrics server or service catalog are prime targets here)
  • Privilege escalation to the Kubelet API

It's a 9.8 out of 10 on the severity score for a CVE

Demo time!

How do I fix it?

Option 1: disable anonymous-auth on the kube-apiserver. The default is true:

Option 2: ACL your ApiServer

Option 3 (the best): Upgrade!

Privilege escalation via the Kubelet API

Communication from Kubelet to ApiServer is almost always Kubelet -> Apiserver

For example, creating a pod:

But if you need to exec to a pod, the apiserver needs to talk to the Kubelet. Usually via port 10250

We can abuse this port to gain access if Kubelet Authentication has not been set up

Demo time number 2!

How do I fix it?

Option 1: disable anonymous-auth on the kubelet. Once again, the default is true:

Option 2: Add authentication and authorization to your kubelets using either Certs or Tokens by following the steps here: https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-authentication-authorization/

Privilege escalation to the Kubelet via the second version of CVE-2018-1002105

Similar to our first exploit, we are using the open upgraded connection to escalate privileges

Demo time!

Come on WiFi and Demo Gods, don't let me down now

How do I fix it?

Option 1: disallow your users to use exec, attach etc. privileges

Option 2: upgrade ASAP!

Privilege escalation via the cloud provider

IAM in public clouds is provided via the metadata server, so your pods appear to the metadata server as the nodes

Demo time!

Yes, I'm crazy enough to attempt 4 demos in 45 minutes

How do I fix it?

Ensure that your nodes are created with read only permissions to your cloud provider

Review your permissions! If someone accidentally downloaded a docker image with this kind of code inside it you could face a hefty bill

Questions?

Thank you!

Thanks and acknowledgments for great writing, examples and write ups which helped me make the demos:

  • https://gravitational.com/blog/kubernetes-websocket-upgrade-security-vulnerability/
  • https://blog.appsecco.com/analysing-and-exploiting-kubernetes-apiserver-vulnerability-cve-2018-1002105-3150d97b24bb
  • https://github.com/evict/poc_CVE-2018-1002105

All your Kube are belong to us

By Andy Repton

All your Kube are belong to us

Exploits in Kubernetes and how to fix them

  • 1,552