Sandboxing seguro mais simples possível (são necessários recursos limitados)

15

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

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 vários processos de trabalho (1 para cada núcleo).

Esta pergunta é sobre como garantir que cada trabalhador opere em um ambiente em á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 comunicações locais permitidas (IPC, TCP, qualquer que seja ...)
  • mem : limite de uso de memória (sem memória swap) mata se estiver acima do limite de mem
  • CPU : apenas 1 núcleo permitido, matar se ao longo do tempo

Nenhuma outra limitação deve ser imposta: o trabalhador deve poder carregar bibliotecas dinâmicas (da pasta somente leitura), gerar novos threads ou processos, chamar a função do sistema, ecc ecc, mas os limites devem ser herdados pelas entidades geradas / carregadas e deve aplicar-se de maneira sumária (por exemplo, não podemos ter um trabalhador gerando dois threads que usam 800 MB cada, o limite de memória para esse trabalhador é de 1 GB).

Escusado será dizer que não deve haver maneira para 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 estão um pouco pesados ​​para o meu caso de uso e não são completamente seguros 1 . O AppArmor é preferível ao SELinux devido à configuração mais fácil, use-o para restrições de rede e rede; cgroups preferível ao ulimit (que opera em um único processo), usou-o para restrições de mem e cpu.

Essa é 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 "permitida ao trabalhador derrubar a si mesma, mas nada mais" .

StephQ
fonte
2
Se limitar [ing] recursos é seu objetivo, você pode fazer muito melhor do que um convidado do Ubuntu (ou realmente qualquer derivado do Debian) . Em qualquer caso, você provavelmente vai querer linux-modo de usuário e / ou (com kernels recentes) o espaço de nomes de usuário
mikeserv
2
O LXC parece exatamente o que você precisa. Por que você acha que é pesado e inseguro? (Claro, houve bugs, mas também tem tudo o que você pode usar.)
Gilles 'SO- stop be evil'
A apresentação vinculada (reconhecidamente a partir de 2011) e a seção Segurança da documentação do Ubuntu LXC falando sobre 'vazamentos de espaços para nome' não são muito tranquilizadoras. Parece que o LXC, baseado principalmente em namespaces e cgroups, poderia ser a melhor opção no momento. Eu também encontrei Linux-Sandboxing , leitura interessante
StephQ
Pode exigir um pouco de reformulação, mas você já pensou em executar nas cadeias BSD?
Ryder
Embora o LXC possa ser "pesado", pois é como várias VMs, é realmente simples fazê-las. Algumas dessas soluções, embora "mais leves", podem exigir muita configuração. Com o LXC, talvez você não precise configurar coisas como escrever, pois o único aplicativo teria o contêiner inteiro.
28416 MikeP

Respostas:

1

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

Com o cgroups, você pode fazer o seguinte:

  1. Limitar o uso do núcleo da CPU a 1 CPU com o cpusetsubsistema
  2. Defina os limites de uso de memória com o memorysubsistema, rastreando até os garfos. Veja https://github.com/gsauthof/cgmemtime para obter um exemplo.
  3. Impedir o acesso à rede a qualquer coisa que não está na locom net_priosubsistema.

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

Nota: 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 dizer do que fazer. Então, aqui estão alguns links de referência para você começar:

Boa sorte!

Dennis Chen
fonte
1

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

O LXC não é seguro por si só Se você precisar de segurança, deverá usá-los via libvirt (baseado no SELinux MLS ).

Seu problema é infinito, portanto, não tente encontrar nenhuma solução pronta e sem tempo infinito, lembre-se de que até o kernel.org foi copiado e muito recentemente o FBI declarou que alguém usa seus sistemas há anos sem ser detectado até agora.

Eu irei com o LXC / libvirt para obter uma segurança muito boa ou tentarei os "novos" contêineres claros da Intel , que usam uma VM muito leve para o seu contêiner com o uso claro do DAX / KSM (eu não os testei, mas eles parecem muito promissor de fato).

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

Portanto, não é tarefa fácil, com certeza, o LXC / libvirt é realmente legal, mas talvez contêineres limpos sejam o caminho a percorrer.

Docker? Eu não usei / não usaria o docker para mais do que testes locais, quando não havia uma caixa vagrant disponível, eles precisam de muito mais trabalho e muito melhor comunidade.

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

Se você quiser algo "mais fácil" e mais amador, poderá verificar o firejail , eu o uso em alguns "aplicativos" da área de trabalho e ele faz o trabalho (é muito fácil criar o modelo para seu aplicativo personalizado, use "private" monta em cima de seus diretórios e restringe a rede apenas para uso local, processos gerados herdam para o pai e continuam ...).

Saúde e divirta-se sem enlouquecer. ;)

more2000
fonte
0

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

https://wiki.mozilla.org/Security/Sandbox/Seccomp

Keith Smith
fonte
0

Você pode querer examinar os sistemas de computação em grade. Em particular, o BOINC ( http://boinc.berkeley.edu ) verifica quase todas as suas caixas.

Eu acredito que ele opera com 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 à rede no servidor BOINC, mas não é o padrão fora da caixa IIRC

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

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

user159726
fonte