Sandbox seguro mais simples possível (recursos limitados necessários)

13

Estou trabalhando em um projeto que implementa simulações distribuídas: o código arbitrário é executado em vários nós e os resultados são coletados e agregados posteriormente.

Cada nó é uma instância de uma máquina virtual Ubuntu Linux e executa um processo mestre que cuida do encaminhamento do código a ser executado para um número de processos de trabalho (1 para cada núcleo).

Esta questão é sobre como se certificar de que cada trabalhador opera em um ambiente de área restrita sem recorrer ao uso de uma instância de máquina virtual para cada um deles. Os requisitos exatos para os trabalhadores são:

  • fs : sem permissão de gravação, permissão somente leitura limitada a um único diretório (e subpastas)
  • net : somente as comunicações locais são permitidas (IPC, TCP, etc.)
  • mem : limite ao uso de memória (sem memória swap) kill if over mem limit
  • cpu : apenas 1 núcleo permitido, matar se com limite de tempo

Nenhuma outra limitação deve ser imposta: o trabalhador deve ser capaz de carregar bibliotecas dinâmicas (da pasta somente leitura), gerar novas threads ou processos, chamar a função do sistema, ecc ecc, mas os limites devem ser herdados pelo spawned / carregado entidades e deve aplicar de forma sumária (por exemplo, não podemos ter um trabalhador gerar dois segmentos que usam 800MB cada um é o limite de memória para tal trabalhador é 1GB).

Escusado será dizer que não deve haver maneira de o trabalhador aumentar seus direitos.

Passei um tempo considerável revisando as alternativas disponíveis (SELinux, AppArmor, cgroups, ulimit, namespaces do Linux, LXC, Docker, ...) para a solução mais simples que satisfaz meus requisitos, mas minha experiência em campo é limitada.

Entendimento atual: o LXC e o Docker são um pouco pesados para o meu caso de uso e não são completamente seguros 1 . AppArmor preferível ao SELinux devido à configuração mais fácil, use-o para restrições de fs e de rede; cgroups preferível a ulimit (que opera em um único processo), usado para restrições de mem e cpu.

Esta é a maneira mais simples de alcançar meu objetivo? Posso usar o AppArmor ou cgroups exclusivamente? Existe alguma falha de segurança óbvia no meu modelo? A diretriz deve ser "trabalhador autorizado a derrubar a si mesmo, mas nada mais" .

    
por StephQ 21.12.2014 / 18:58

4 respostas

1

Sim, você pode usar cgroups e SELinux / AppArmor exclusivamente para monitorar e controlar o código arbitrário que você irá executar.

Com cgroups, você pode fazer o seguinte:

  1. Limitar o uso do núcleo da CPU a 1 CPU com o cpuset subsistema
  2. Defina limites de uso de memória com o subsistema memory , acompanhando até mesmo os garfos. Veja o link para um exemplo.
  3. Impedir o acesso da rede a qualquer coisa que não esteja em lo com net_prio subsistema.

E com o SELinux / AppArmor, você pode limitar o acesso de leitura / gravação do processo.

Nota: Eu não estou familiarizado com o AppArmor, mas é um sistema de Controle de Acesso Obrigatório (MAC), o que significa que proteger a escrita e a leitura é o seu trabalho.

O uso desses sistemas é uma questão de escrever as configurações adequadas. Claro, tudo isso é muito mais fácil falar do que fazer. Então, aqui estão alguns links de referência para você começar:

Boa sorte!

    
por 01.06.2016 / 10:09
1

Eu descartaria SELinux para AppArmor apenas se eu estivesse usando o Ubuntu . (realmente muito difícil)

LXC não é seguro por si só Se você precisa de segurança você deve usá-los via libvirt (baseado em SELinux MLS ).

Seu problema é infinito , então não tente encontrar nenhuma solução pronta e sem tempo infinito, lembre-se que mesmo o kernel.org foi desenvolvido e muito recentemente o < em> FBI declarou que alguém tem usado seus sistemas há anos sem ser detectado até agora.

Eu irei com o LXC / libvirt para uma segurança muito boa ou tentarei as "novas" intel Limpar recipientes , que usam uma VM muito leve para o seu contêiner com o uso claro de DAX / KSM (eu não os testei, mas eles parecem muito promissores).

Se você está preocupado com a exploração do kernel, grsecurity é a sua solução, mas você deve integrá-la à sua solução de contêiner (dores de cabeça, com certeza).

Portanto, não é tarefa fácil, com certeza, LXC / libvirt são realmente bacanas, mas talvez containers transparentes sejam o caminho a seguir.

Docker? Eu não utilizei o docker para mais do que testes locais quando não havia vagabundos disponíveis, eles precisam de muito mais trabalho e melhor comunidade.

É claro que os contêineres systemd são bons também, mas eu suponho que você não goste / queira porque nem sequer os mencionou e eles não são uma solução independente do fornecedor.

Se você quiser algo "mais fácil" e mais amador, você pode conferir firejail , que eu tenho usado em alguns computadores " aplicativos "e faz o trabalho (é muito fácil criar o modelo para o seu aplicativo personalizado, use montagens" privadas "em cima de seus dirs e restringir a rede apenas para uso local, gera processos herdados por pai e continua ... ).

Elogie e divirta-se sem enlouquecer. ;)

    
por 19.06.2016 / 23:25
0

seccomp-bpf é outra opção que funciona bem para o OpenSSH, vsftpd e Chromium, ele só tem exit (), sigreturn (), read () ele também usa write () embora permita a filtragem de chamadas do sistema usando o Berkeley Packet configurável Regras de filtro. Também pode ser usado em conjunto com cgroups para memória, cpu etc ...

link

    
por 15.07.2016 / 02:59
0

Você pode querer examinar os sistemas de computação em grade. Em particular, o BOINC ( link ) verifica quase todas as suas caixas.

Eu acredito que ele opera em seus parâmetros como tal:

fs: pode ler / gravar em seu próprio diretório, em nenhum outro lugar

net: pode ser configurado para permitir apenas o acesso de rede ao seu servidor BOINC, mas não é padrão fora da caixa IIRC

mem: sim, limites de memória separados para máquinas ociosas e não inativas

cpu: sim, pode até dizer "não execute se o computador não estiver inativo"

    
por 21.07.2016 / 06:45