Docker e Kubernetes em ambientes que exigem segurança

Nota perev. : O artigo original foi escrito por um engenheiro da Suécia, Christian Abdelmassih, apaixonado por arquitetura corporativa, segurança de TI e computação em nuvem. Recentemente, ele fez mestrado em Ciência da Computação e tem pressa em compartilhar seu trabalho - uma tese de mestrado, ou melhor, parte dela, dedicada aos problemas de isolar um aplicativo em contêineres [e lançado no Kubernetes]. Como o "cliente" para quem essa pesquisa foi preparada, atua não menos que a polícia de sua terra natal.



A orquestração de contêineres e a computação nativa da nuvem se tornaram muito populares nos últimos anos. Sua adaptação atingiu um nível tal que até empresas financeiras, bancos e o setor público demonstram interesse neles. Comparados a outras empresas, eles se distinguem por extensos requisitos no campo da segurança da informação e da TI.

Um dos aspectos importantes é como os contêineres podem ser usados ​​em ambientes de produção e, ao mesmo tempo, a separação do sistema entre aplicativos pode ser mantida. Como essas organizações usam ambientes de nuvem privada baseados na virtualização em cima do bare metal, a perda desse isolamento ao migrar para um ambiente com contêineres orquestrados é inaceitável. Dadas essas limitações, minha dissertação foi escrita e a polícia sueca é considerada um cliente-alvo.

A questão específica do estudo considerado na tese é:

Como a demarcação de aplicativo é suportada no Docker e no Kubernetes em comparação com as máquinas virtuais executadas no hipervisor ESXi em execução no bare metal?

Esse problema requer um estudo cuidadoso. Para começar, observe o denominador comum - aplicativos.

Aplicativos da Web são confusos


Vulnerabilidades em aplicativos da Web - um verdadeiro zoológico de vetores de ataque. Os riscos mais significativos são apresentados no OWASP Top 10 ( 2013 , 2017 ). Esses recursos ajudam a educar os desenvolvedores na redução de riscos típicos. No entanto, mesmo que os desenvolvedores escrevam códigos sem falhas, o aplicativo ainda pode estar vulnerável - por exemplo, por meio de dependências de pacotes.

David Gilbertson escreveu uma história maravilhosa sobre como você pode injetar código por meio de um pacote malicioso distribuído, por exemplo, como parte do NPM para aplicativos baseados em Node.js. Para detectar vulnerabilidades, você pode usar scanners de dependência, mas eles apenas reduzem o risco, mas não o eliminam completamente.

Mesmo se você criar aplicativos sem dependências de terceiros, ainda não é realista acreditar que o aplicativo nunca se tornará vulnerável.

Devido a esses riscos, não podemos dizer que os aplicativos da web são seguros.

Em vez disso, siga uma estratégia de defesa em profundidade (DID). Vamos dar uma olhada no próximo nível: contêineres e máquinas virtuais.

Contêineres versus máquinas virtuais - um conto de isolamento


Um contêiner é um ambiente isolado do espaço do usuário que geralmente é implementado usando os recursos do kernel. Por exemplo, o Docker usa os namespaces, cgroups e recursos do Linux para isso. Nesse sentido, o isolamento dos contêineres do Docker é muito diferente das máquinas virtuais lançadas pelos hipervisores do tipo 1 (ou seja, trabalhando diretamente no hardware; hipervisores bare-metal) .

A diferenciação para essas máquinas virtuais pode ser implementada em um nível tão baixo como no hardware real, por exemplo, através do Intel VT . Os contêineres do Docker, por sua vez, contam com o kernel do Linux para demarcação. Essa diferença é muito importante a considerar quando se trata de ataques abaixo da camada .

Se um invasor conseguir executar o código em uma máquina ou contêiner virtual, ele poderá potencialmente chegar a um nível inferior executando um ataque de escape .


dependendo de contêineres ou máquinas virtuais serem usadas no hardware, a diferenciação é implementada em diferentes níveis de infraestrutura.

A possibilidade de tais ataques foi comprovada para o hipervisor VMware ESXi durante o concurso de hackers Pwn2Own 2017, bem como o GeekPwn2018. O resultado foi um par de CVEs ( CVE-2017–4902 , CVE-2018–6981 ) que podem ser usados ​​em ataques abaixo da camada para sair de máquinas virtuais ( escape de máquina virtual ) . Máquinas virtuais em servidores de ferro não garantem segurança absoluta, mesmo que usem tecnologia para diferenciar o nível de ferro.

Por outro lado, se olharmos para os vetores de ataque em um hipervisor bare-metal versus o kernel Linux, é óbvio que este último possui uma superfície de ataque muito maior - devido ao seu tamanho [kernel Linux] e à variedade de recursos. Uma superfície de ataque maior implica mais vetores de ataque em potencial para ambientes em nuvem usando isolamento de contêiner. Isso se manifesta na crescente atenção aos ataques de fuga de contêineres , que foram possíveis graças a explorações do kernel (por exemplo, CVE-2016–5195 [ie Dirty COW - approx. Transl.] , CVE-2017–1000405 )

Módulos como SELinux ou AppArmor podem ser usados ​​para aumentar o isolamento dentro do contêiner. Infelizmente, esses mecanismos de segurança no kernel não impedem ataques de escape no próprio kernel. Eles limitarão as ações possíveis do atacante se não for possível ultrapassar os limites. Se quisermos lidar com saídas fora do contêiner, é necessário um mecanismo de isolamento fora do contêiner ou mesmo o núcleo. Por exemplo, uma caixa de areia (sandbox) !

O gVisor é uma caixa de proteção para o tempo de execução do contêiner, cujo código foi aberto pelo Google e que adiciona um kernel adicional entre o contêiner e o kernel do sistema operacional. Esse tipo de sandbox pode melhorar a situação com ataques de contêineres fora do limite que ocorrem no nível do kernel . No entanto, as explorações principais são apenas uma das ferramentas do invasor.

Para ver como outros ataques podem levar a resultados semelhantes, é necessário ter uma visão mais geral de como os contêineres são usados ​​na era nativa da nuvem.

O efeito da orquestração de contêiner no isolamento


Para gerenciar contêineres em execução em ambientes com muitos nós, eles introduzem a orquestração, na qual o Kubernetes assume o papel principal. Acontece que os erros do orquestrador também podem afetar o isolamento do contêiner.

Tim Allclair fez uma apresentação maravilhosa no KubeCon 2018, na qual observou algumas superfícies de ataque. Em seu relatório, ele menciona um exemplo ( CVE-2017-1002101 ), de como os erros de orquestração podem afetar o isolamento - nesse caso, através da capacidade de montar espaço em disco fora do pod. Vulnerabilidades desse tipo são muito problemáticas, porque pode ignorar a caixa de areia na qual o contêiner está embrulhado.

Com a introdução do Kubernetes, expandimos a superfície de ataque. Inclui sistemas hospedados no mestre Kubernetes. Um deles é o servidor da API Kubernetes, onde eles descobriram recentemente uma vulnerabilidade que poderia permitir privilégios excessivos ( CVE-2018–1002105 ). Como a superfície de ataque do mestre Kubernetes está além do escopo da minha dissertação, essa vulnerabilidade específica não é levada em consideração.

Por que os ataques de fuga são tão importantes? Os contêineres forneceram a capacidade de executar muitos aplicativos co-hospedados no mesmo sistema operacional. Portanto, havia um risco associado ao isolamento de aplicativos. Se um aplicativo crítico para os negócios e outro aplicativo vulnerável estiverem em execução no mesmo host, um invasor poderá obter acesso a um aplicativo crítico por meio de um ataque a um aplicativo vulnerável.

Dependendo do tipo de dados com o qual a organização está trabalhando, o vazamento pode prejudicar não apenas a própria organização, mas também indivíduos e todo o país. Como você se lembra, estamos falando sobre o setor público, finanças, bancos ... - um vazamento pode afetar seriamente a vida das pessoas.

Então, a orquestração de contêineres pode até ser usada nesses ambientes? Antes de iniciar uma reflexão mais aprofundada, uma avaliação de risco deve ser realizada.

Que risco é aceitável?


Antes de introduzir medidas de segurança, é importante pensar sobre que tipo de informação a organização está realmente tentando proteger. A decisão sobre se são necessárias etapas adicionais para evitar possíveis ataques de escape em contêineres depende dos dados com os quais a organização está trabalhando e dos serviços que fornece.

A longo prazo, isso significa que, para obter a possibilidade de sair do contêiner em um host configurado corretamente protegido pela sandbox do contêiner, o invasor deve:

  1. executar código em um contêiner, por exemplo, por injeção de código ou usando vulnerabilidades no código do aplicativo;
  2. tire vantagem de outra vulnerabilidade, dia zero, ou para a qual um patch ainda não foi aplicado para sair do contêiner, mesmo que haja uma caixa de proteção .

Como você pode imaginar, uma organização que não considera esse cenário válido deve trabalhar com dados ou oferecer serviços muito exigentes quanto à confidencialidade , integridade e / ou acessibilidade .

Como a dissertação é dedicada apenas a esses clientes, a perda do isolamento do sistema saindo do contêiner não é permitida, pois suas consequências são muito significativas. Que medidas podem ser tomadas para melhorar o isolamento? Para subir de nível na escada de isolamento, observe também as caixas de proteção nas quais o kernel do sistema operacional está agrupado, ou seja, máquinas virtuais!

As tecnologias de virtualização que usam hipervisores hospedados melhorarão a situação, mas queremos limitar ainda mais a superfície de ataque. Portanto, vamos examinar os hipervisores instalados no ferro e ver o que eles nos levarão.

Hipervisores em ferro


Um estudo da Agência Sueca de Pesquisa de Defesa Sueca examinou os riscos da virtualização em relação às Forças Armadas Suecas. Sua conclusão falou dos benefícios dessas tecnologias para os militares, mesmo com os rigorosos requisitos de segurança e riscos que a virtualização traz.

Nesse sentido, podemos dizer que a virtualização é usada (até certo ponto) na indústria de defesa, pois carrega riscos aceitáveis . Como as agências e empresas do setor de defesa são um dos clientes mais exigentes em segurança de TI, também podemos argumentar que o risco aceitável para eles significa que é aceitável para os clientes considerados na dissertação. E tudo isso - apesar das saídas potenciais além da máquina virtual, discutidas acima.

Se decidirmos usar esse tipo de sandbox para contêineres, há algumas coisas a considerar no contexto de detalhes nativos da nuvem.

Nós de sandbox para máquinas virtuais


A ideia é que os nós do cluster Kubernetes sejam máquinas virtuais que usam virtualização de hardware. Como as máquinas virtuais desempenharão o papel de caixas de proteção de contêiner que são executadas em pods, cada nó pode ser considerado um ambiente protegido por caixa de proteção.

Uma observação importante sobre essas caixas de proteção no contexto das caixas de proteção de contêineres já mencionadas: essa abordagem permite colocar muitos contêineres em uma caixa de proteção. Essa flexibilidade permite reduzir a sobrecarga quando comparada com o caso em que cada contêiner possui sua própria caixa de proteção. Como cada sandbox traz seu próprio sistema operacional, queremos reduzir seu número enquanto mantém o isolamento.


Máquinas virtuais instaladas no hardware - nós do cluster - atuam como caixas de proteção para contêineres. Os contêineres executados em diferentes VMs são delimitados com um nível de risco aceitável. No entanto, isso não se aplica a contêineres em execução na mesma VM.

No entanto, como o Kubernetes é capaz de alterar a localização dos pods por vários motivos, o que pode arruinar a ideia de usar caixas de areia , será necessário adicionar restrições ao mecanismo de posicionamento conjunto dos pods. Você pode alcançar o desejado de várias maneiras.

No momento da redação deste artigo, o Kubernetes ( v1.13 ) suporta três métodos principais para controlar o planejamento e / ou o lançamento de pods:


Quais métodos usar dependem da aplicação da organização. No entanto, é importante observar que os métodos diferem em sua capacidade de descartar os pods depois que eles entram no estágio de execução. Agora, apenas manchas são capazes disso - através da ação NoExecute . Se você não processar esse momento de maneira alguma e alguns rótulos mudarem, tudo poderá levar a uma localização indesejável.

Conformidade com os requisitos de co-localização


A dissertação propõe a idéia de usar um sistema de classificação que mostre como a sensibilidade é refletida na co-localização. A idéia é usar o relacionamento 1: 1 entre o contêiner e o pod e determinar a localização dos pods com base na classificação de aplicativos em contêiner.

Para simplificar e reutilizar, o seguinte sistema de classificação em três etapas é usado:

  • Classe O : O aplicativo não é sensível e não possui requisitos de isolamento. Pode ser colocado em qualquer nó que não pertença a outras classes.
  • Classe PG (grupo privado) : um aplicativo, juntamente com um conjunto de outros aplicativos, forma um grupo privado para o qual um nó dedicado é necessário. Um aplicativo pode ser hospedado apenas em nós da classe PG que possuem o identificador de grupo privado correspondente.
  • Classe P (privada) : um aplicativo requer um nó privado e separado e só pode ser colocado em nós vazios de sua classe (P).

Para atender aos requisitos de co-localização para muitos aplicativos classificados, são utilizadas restrições e tolerâncias, com as quais cada nó recebe uma classe, e o PodAffinity para aplicar restrições adicionais para pods com aplicativos da classe P ou PG.

Este exemplo simplificado mostra como restrições e tolerâncias podem ser usadas para implementar o controle de co-localização:



Os pods 2 e 3 contêm aplicativos de um grupo privado, e o aplicativo no pod 1 é mais sensível e requer um nó dedicado.

No entanto, as classes P e PG exigirão regras adicionais de afinidade para garantir que as solicitações de demarcação sejam executadas à medida que o cluster e os aplicativos hospedados crescem. Vamos ver como você pode implementar essas regras para diferentes classes:

 # Class P affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - topologyKey: "kubernetes.io/hostname" namespaces: ["default"] labelSelector: matchExpressions: - key: non-existing-key operator: DoesNotExist 

As regras de afinidade para aplicativos de classe P requerem nós dedicados. Nesse caso, o pod não será agendado se o pod sair sem a chave non-existing-key . Tudo funcionará até que um único pod tenha essa chave.

 # Class PG affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - topologyKey: "kubernetes.io/hostname" labelSelector: matchLabels: class-pg-group-1: foobar podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - topologyKey: "kubernetes.io/hostname" labelSelector: matchExpressions: - key: class-pg-group-1 operator: DoesNotExist 

Para aplicativos de classe PG, as regras de afinidade irão hospedar pods com um identificador de class-pg-group-1 e em nós que possuem pods sem um identificador.

Essa abordagem nos permitirá usar um sistema de classificação para delimitar contêineres com base nos requisitos relevantes de um aplicativo em contêiner.

O que conseguimos?

Conclusão


Consideramos uma maneira de implementar sandboxes com base no hipervisor tipo 1 (ou seja, lançado no bare metal) para criar nós nos clusters Kubernetes e apresentamos um sistema de classificação que define os requisitos para a delimitação de aplicativos em contêiner. Se compararmos essa abordagem com as outras soluções consideradas, ela apresenta vantagens em termos de garantir o isolamento do sistema.

Uma conclusão importante é que a estratégia de isolamento restringe a propagação de ataques de escape para o contêiner. Em outras palavras, deixar o contêiner por si só não é impedido, mas seus efeitos são mitigados. Obviamente, junto com isso, surgem dificuldades adicionais que devem ser levadas em consideração ao fazer comparações semelhantes.

Para usar o método especificado em um ambiente de nuvem e fornecer escalabilidade, requisitos adicionais serão impostos à automação. Por exemplo, para automatizar a criação de máquinas virtuais e seu uso no cluster Kubernetes. O mais importante será a implementação e verificação da ampla classificação de aplicativos.

Isso faz parte da minha dissertação sobre o isolamento de um aplicativo em contêiner .

Para evitar a possibilidade de um invasor que saiu do contêiner em um nó atacar os serviços de outros nós, é necessário considerar ataques propagados pela rede . Para levar esses riscos em consideração, minha dissertação propõe a segmentação da rede de cluster e apresenta arquiteturas de nuvem, uma das quais com firewall de hardware .

Quem desejar pode se familiarizar com o documento completo - o texto da dissertação é de acesso público: “ Orquestração de contêineres em ambientes exigentes de segurança na Autoridade Policial Sueca ”.

PS do tradutor


Leia também em nosso blog:

Source: https://habr.com/ru/post/pt440504/


All Articles