Execute o código do usuário com segurança

6

Eu tenho que marcar o código C e parte disso envolve correr e cronometrar seus envios. O problema é que o código deles é executado como eu e eles podem, em princípio, fazer o que quiserem usando minhas configurações de permissão. Por exemplo, eles podem copiar minha chave privada ssh.

Eu poderia configurar uma máquina virtual e executar o código dentro dela (embora eu não tenha certeza da melhor maneira de bloquear isso também). Um problema com isto é que o desempenho de velocidade agora não será realista. Eu poderia fornecer a mesma máquina virtual para todos os usuários para testar seu código de antemão, pelo menos, eles têm a mesma configuração para testar.

Existe uma boa maneira de configurar um ambiente onde você pode executar código escrito por outros, mas limitar o dano que ele pode causar?

    
por marshall 19.12.2013 / 11:16

6 respostas

10

Na verdade, existem vários tipos de máquinas virtuais, que estão sendo perdidas nas outras respostas. Você pode ter o que é conhecido como virtualização de contêiner - algo como o Linux vServer ou o OpenVZ. Eles compartilham o kernel do host, executando o que é conhecido como 'containers' (com seus próprios ambientes) em vez de virtualizar qualquer hardware, e são quase tão v v v ves v v ves ves ves ves v es vesv v ves (O OpenVZ é mais comum em serviços VPS mais baratos, mas suporta apenas até um kernel personalizado 2.6.x, enquanto o vServer vai para o mais recente estável).

Além disso, a sobrecarga da virtualização completa em uma máquina moderna não é tão ruim quanto você pensa! Com a virtualização de hardware em uma CPU de médio e grande porte, a maioria dos usos nem perceberia qualquer penalidade de desempenho, a menos que houvesse contenção de recursos (por exemplo, o host ou outra VM estava usando muito). Será um pouco mais lento, porque alguns recursos são usados pelo sistema operacional convidado, mas o custo da própria virtualização é quase insignificante - especialmente o uso da CPU, já que isso pode ser passado para o hardware bruto com (quase) nenhuma tradução, se for v vv vvesvesves es veses eseses eseseses esesesveseses Você poderia tentar, você pode se surpreender.

Observe que cada um também vem com diferentes níveis de isolamento. A virtualização de contêiner torna muito mais fácil a exploração do kernel e outros bugs para 'quebrar' o contêiner - o LXC não é seguro, embora o OpenVZ seja considerado bastante maduro e seguro (e é comumente usado em serviços VPS, onde você vende contentores para pessoas não fiáveis). vServer está em algum lugar entre. A virtualização completa tem melhor isolamento, mas ainda existem alguns ataques para explodir.

Depende do quanto você espera que um aluno mal-intencionado vá. Pode ser suficiente simplesmente executar como um usuário diferente. Você pode querer um contêiner para mais segurança. As chances são de que um contêiner é suficiente para qualquer coisa que você encontrará nessas circunstâncias.

    
por 19.12.2013 / 13:11
8

Crie uma única conta de usuário com privilégios limitados (o que significa acesso a apenas um conjunto limitado de rotinas de biblioteca, possivel até mesmo um acesso de shell reduzido).

ssh como o usuário em seu sistema e execute seus programas.

Você pode até escrever um pequeno script de shell bash (ou qualquer outro script de shell) para conseguir isso.

    
por 19.12.2013 / 11:22
4
  1. Execute o código como nobody , que deve fornecer privilégios mínimos. Dependendo de como a configuração é empolgante, isso pode não ser seguro
  2. Executar em chroot jail. Dependendo do código, isso pode mudar o comportamento e as cadeias podem ser quebradas. Eles não são um recurso de segurança.
  3. Executar em uma máquina virtual. Eu acho que há apenas alguns exemplos conhecidos de ser capaz de romper com eles, mas não tenho certeza. Você pode usar, por exemplo, o Vagrant para configurar uma virtualização muito simples. Exemplo de configuração e comandos .
por 19.12.2013 / 13:01
1

Existem algumas possibilidades diferentes, dependendo de quanto isolamento você deseja.

O mais fácil é simplesmente confiar no código. Parece que isso está fora de questão para você, ou você não estaria perguntando isso.

O próximo passo é executar o código em uma conta de usuário separada, conforme Vigneshwaren sugeriu . Se você quiser restringir o acesso à rede especificamente para uma conta de usuário em particular, isso pode ser feito através de proprietário do iptables correspondente . Quando concluído, a conta do usuário pode ser deixada por perto ou excluída, e qualquer processo executado como esse usuário pode ser eliminado imediatamente.

Mais uma etapa é adicionar uma cadeia chroot à conta de usuário separada. Isso pode causar problemas com bibliotecas ou arquivos de configuração que precisam estar no lugar, mas se for, por exemplo, um puro exercício de trituração de números, pode ser prático. Ele garante que apenas os arquivos que você deseja que o código dos alunos consiga acessar estejam acessíveis a esse código.

O passo final seria executar o código em um ambiente completamente separado. Pense máquina virtual, aqui, embora um computador físico separado poderia realizar a mesma coisa. O código pode ser executado em um ambiente completamente isolado, inclusive com o cabo de rede virtual desconectado, e qualquer dano que ele possa causar, incluindo o preenchimento do disco ou a explosão de um fork, será isolado dentro da máquina virtual e o pior que pode acontecer é que você precisa forçá-lo a desligar. Como a VM terá uma instalação de SO completamente separada, especialmente se você remover a conexão de rede antes de executar o software, isso possivelmente não causará vazamento de dados confidenciais. Com uma VM, você pode usar instantâneos de disco para permitir que você retorne rápida e facilmente a um estado conhecido depois de executar o programa de cada aluno.

Tudo depende de onde na escala de esforço versus confiança necessária você coloca seus alunos. Menos confiança requer mais esforço de sua parte para garantir que nada de mal aconteça.

    
por 19.12.2013 / 11:50
0

I have to mark C code

Então você tem acesso total ao código-fonte, veja bem - é duvidoso que eles serão capazes de passar qualquer coisa maliciosa no código sem que você perceba.

Se você não tiver certeza de executar uma VM, mas na maioria dos casos você saberá o que está sendo executado

    
por 19.12.2013 / 15:17
0

Eu trabalhei em um sistema semelhante há alguns anos atrás. O que eu fiz foi usar o ptrace para limitar as chamadas do sistema (veja o código aqui ), e opcionalmente altere o id do usuário ou o chroot. Se os programas forem simples, envolvendo somente algoritmos puros e tarefas básicas de E / S, essa deve ser uma solução prática que você possa considerar.

BTW, vale a pena mencionar que você também deve limitar o uso do tempo / memória do compilador. Alguns programas mal-intencionados podem incluir diretivas como #include </dev/random> , que podem fazer o compilador travar por um longo tempo, ou algumas macros recursivas, fazendo com que o compilador consuma muita memória.

    
por 21.12.2013 / 06:03