Instituto de Tecnologia de Massachusetts. Curso de Aula nº 6.858. "Segurança de sistemas de computador". Nikolai Zeldovich, James Mickens. 2014 ano
Computer Systems Security é um curso sobre o desenvolvimento e implementação de sistemas de computador seguros. As palestras abrangem modelos de ameaças, ataques que comprometem a segurança e técnicas de segurança baseadas em trabalhos científicos recentes. Os tópicos incluem segurança do sistema operacional (SO), recursos, gerenciamento de fluxo de informações, segurança de idiomas, protocolos de rede, segurança de hardware e segurança de aplicativos da web.
Palestra 1: “Introdução: modelos de ameaças”
Parte 1 /
Parte 2 /
Parte 3Palestra 2: “Controle de ataques de hackers”
Parte 1 /
Parte 2 /
Parte 3Aula 3: “Estouros de Buffer: Explorações e Proteção”
Parte 1 /
Parte 2 /
Parte 3Palestra 4: “Separação de Privilégios”
Parte 1 /
Parte 2 /
Parte 3Palestra 5: “De onde vêm os sistemas de segurança?”
Parte 1 /
Parte 2Palestra 6: “Oportunidades”
Parte 1 /
Parte 2 /
Parte 3 Então, na continuação do tópico de compartilhamento de privilégios, hoje falaremos sobre oportunidades. Se você se lembra, na semana passada falamos sobre como o
Unix fornece alguns mecanismos para aplicativos que podemos usar se precisarmos separar privilégios da estrutura interna do aplicativo.
Hoje falaremos sobre as possibilidades que nos farão pensar de maneira muito diferente sobre os privilégios que o aplicativo pode ter. Portanto, na palestra de hoje, temos dois assuntos separados para discussão. Uma pergunta é sobre como evitar confusão na determinação da autoridade e tornar seus privilégios ao escrever um programa mais claro e inequívoco, para que você não use acidentalmente os privilégios errados.
A segunda pergunta diz respeito à "caixa de areia" chamada
Capsicum , é um sistema semelhante ao
OKWS , que permitirá executar um fragmento de código com menos privilégios. Portanto, se o sistema estiver comprometido, isso não ameaçará muitos danos.

Essa abordagem permite que você manipule privilégios de maneira diferente da permitida pelo
Unix . Para começar, vamos olhar para esse problema confuso de autoridade, que o autor do artigo que estamos discutindo Norman Hardy enfrentou e descobrir por que ela ficou tão intrigada com ele.
Este artigo foi escrito há muito tempo, e o autor usa uma estrutura sintática para nomes de arquivos, o que é um pouco surpreendente. Mas podemos tentar, pelo menos, transcrever o problema dele em uma sintaxe de nome no estilo
Unix, mais familiar.
Até onde eu sei, ele usou o
compilador Fortran , localizado em
/ sysx / fort , e queria mudar esse compilador para manter estatísticas sobre o que foi compilado, quais partes do compilador eram mais intensivas em recursos e assim por diante. Portanto, ele queria ter certeza de que esse
compilador Fortran de alguma forma forneceria uma entrada no arquivo
/ sysx / stat e que ele escreveria aqui informações sobre várias chamadas do compilador.

O sistema operacional deles tinha algo parecido com a função
setuid de que falamos no
Unix . Eles chamaram de licença de arquivo doméstico. Isso significava que, se você executou
/ sysx / fort , e este programa possui uma licença de
arquivos domésticos , esse processo que você acabou de lançar terá permissões de gravação adicionais para tudo em
/ sysx / . Ou seja, você pode escrever após a barra tudo o que normalmente é marcado com um asterisco, obtendo uma expressão do formulário
/ sysx / * . Isso deu acesso a todos os arquivos gravados no diretório após
/ , e o usuário poderia executá-los. Portanto, o problema específico que eles estavam enfrentando era que algum tipo de usuário inteligente poderia fazer isso, executando o compilador poderia receber muitos argumentos, como o
GCC .
Um usuário assim poderia, por exemplo, coletar algo como
foo.f , onde
f é o código fonte do
Fortran , e adicionar aqui - o
/ sysx / stat .

Eles tinham outro arquivo no sistema
/ sysx , que era um arquivo de cobrança para todos os clientes do sistema. Seu dano causaria ainda mais dano. Foi possível, de maneira semelhante, "pedir" ao compilador para compilar o arquivo de origem
/ sysx / bill e colocá-lo em algum arquivo especial em
/ sysx . E no caso deles, funcionou. Apesar do fato de o próprio usuário não ter acesso de gravação a esse arquivo ou diretório, ele usou o compilador, que tinha esse privilégio adicional - uma licença para arquivos domésticos. Graças aos privilégios do compilador, ele foi capaz de substituir arquivos contrários às intenções do desenvolvedor.

Quem eles deveriam culpar pelo que aconteceu? O que eles acham que deu errado? Você poderia ter agido de maneira diferente para não encontrar esses problemas? Eles acreditavam que o
compilador Fortran seria muito cuidadoso ao usar seus privilégios. De fato, em um certo nível, o compilador Fortran possui dois tipos de privilégios que ele usa.
Um deles, o principal, é baseado no fato de que, se o usuário chamou o compilador, ele deve poder acessar o arquivo de origem, como
foo.f. E se algum outro usuário não ativou ou não chamou o compilador, esse usuário não poderá acessar o código-fonte do usuário "correto".
O segundo tipo de privilégio é fornecido por essa mesma licença, que permite gravar esses arquivos especiais. No nível interno do código-fonte do compilador, deveria haver instruções claras sobre qual desses privilégios ele deseja usar ao abrir um arquivo ou ao executar qualquer operação privilegiada. Poderia simplesmente abrir, ler e gravar arquivos como qualquer outro programa. Ele usa implicitamente todos os privilégios que possui, ou seja, no design do sistema, era uma espécie de combinação de privilégios de usuário e licenças para o uso de arquivos domésticos.
Assim, esses caras estavam realmente interessados em resolver esse problema. E eles meio que chamavam esse compilador de "ajudante estúpido", porque ele precisava distinguir entre os muitos privilégios que possuía e usá-los cuidadosamente, se necessário.
Portanto, devemos considerar como desenvolver um compilador semelhante no
Unix . No sistema deles, tudo estava vinculado a essa licença de arquivo. Existem outros mecanismos que eles introduziram posteriormente em seu programa para identificar oportunidades, falaremos sobre eles em um futuro próximo. Mas podemos resolver esse problema em um sistema
Unix ?
Suponha que você tenha que escrever este
compilador Fortran no
Unix , escrever este arquivo especial e evitar o problema. O que você faria? Alguma idéia? Eu acho que você pode simplesmente declarar isso um plano ruim e, por exemplo, não manter estatísticas. Ou não suporta o tipo de entrada de dados -
oh . Por outro lado, você pode especificar qual código-fonte você deseja compilar para poder ler o arquivo
/ bill ou o arquivo de estatísticas, que talvez precise ser secreto.
Ou talvez você possa fornecer suporte para o código-fonte padrão, mas ele deve conter partes de outro código-fonte, o que é um pouco obscuro.
Público: é possível compartilhar privilégios de compilador.
Professor: sim, esse seria outro design potencialmente bom, compartilhando suas credenciais. Sabemos que, de fato, o compilador Fortran não precisa dos dois privilégios ao mesmo tempo. Então, talvez, falando em
Unix , possamos criar um compilador como
world / bin / fortcc , e seria apenas um programa regular sem privilégios adicionais. E então
criaríamos / bin / fortlog , que será um programa especial com alguns privilégios adicionais, e coletará estatísticas sobre o que está acontecendo no compilador, e a função
fortcc chamará
fortlog . Então, que privilégios daríamos a este
fortlog ?
Público: talvez se você usar algo como
setuid ou
fortlog , qualquer outro usuário também poderá registrar dados arbitrários por meio dele.
Professor: sim, então não é tão bom. Como a única maneira no
Unix de conceder privilégios adicionais ao
fortlog é se tornar seu proprietário, não sei, talvez crie um
forte UID e um
setuid . E toda vez que você executa o
fortlog , ele muda para esse
forte UID . E, talvez, algum arquivo de estatística especial ainda seja necessário aqui. Mas, afinal, todos podem chamar isso de
fortlog .

E isso não é bom, porque qualquer um pode escrever no arquivo de estatísticas. Nesse caso, por segurança, esse é um pequeno problema, mas o que acontece se, em vez de
stat , for um arquivo de pagamento de
faturas ? Nesse caso, os problemas serão muito mais graves.
O Unix tem um mecanismo bastante complicado, que omitimos da última palestra na segunda-feira. Esse mecanismo permite que o aplicativo alterne entre vários
uid . Portanto, para executar aplicativos diferentes, você pode alternar entre os
IDs do usuário. É um pouco difícil de fazer da maneira certa, mas factível. Portanto, esse mecanismo pode ser outro projeto em potencial do nosso sistema.
Eu acho que você poderia fazer mais um truque: tornar o
fortlog “binário” executável apenas para um determinado grupo e criar o binário
fortcc setgid para esse grupo. No entanto, isso não é muito bom, pois apaga qualquer lista de grupos que o usuário originalmente tinha. Mas quem sabe, talvez isso seja melhor que nada.
De qualquer forma, este é um problema bastante complicado, mas pode ser completamente resolvido usando mecanismos
Unix . Talvez você deva repensar seu problema e não se preocupar muito com o arquivo de estatísticas, colocando sua segurança em primeiro lugar. O que está acontecendo de errado em nosso projeto?
Há duas coisas a serem observadas se algo der errado. O primeiro é chamado de
autoridade ambiental ou autoridade externa. Alguém entende o que eles quiseram dizer? Eles nunca deram essa definição exata.
Público: isso significa que você tem a autoridade que lhe é dada pelo meio ambiente. Como se você fosse um usuário agindo sem restrições.
Professor: sim, você está executando uma operação e pode indicar qual operação deseja executar, mas a decisão sobre se essa operação será bem-sucedida vem de alguns parâmetros indiretos adicionais no seu processo.
No
Unix, você pode descobrir como será a verificação da autoridade ambiental. Portanto, se você fizer uma chamada de sistema, provavelmente deu um nome à chamada de sistema. E dentro do kernel, esse nome é mapeado para algum objeto. E esse objeto supostamente contém em si algum tipo de lista de controle de acesso, por exemplo, permissões para esse arquivo e assim por diante.

Portanto, existem algumas permissões que você pode obter desse objeto e precisa determinar se a operação com esse nome que foi concedida ao aplicativo será permitida, ou seja, a cadeia
Nome -> Objeto -> Permissão será criada . É isso que o aplicativo obtém para ver o processo.
Dentro do kernel, existe o ID do usuário atual do
UID do processo de
processo que faz chamadas. Ele também está envolvido na decisão de permitir ou não a execução de uma operação específica. Portanto, esse ID do usuário do processo atual é um privilégio externo. O kernel tentará verificar qualquer operação que você queira executar usando seu
UID atual, seu
GID atual e quaisquer outros privilégios adicionais que você possa ter. E embora haja um certo conjunto de privilégios que permitem fazer isso, você pode fazê-lo. Embora seja possível que você não queira usar todos esses privilégios para abrir um arquivo específico ou executar qualquer outra operação.
Você entende quais são esses
privilégios ambientais , privilégios externos? No caso do sistema operacional, isso significa que o processo possui algum tipo de ID do usuário. Você pode dar exemplos desses privilégios que não estão relacionados ao sistema operacional? Por exemplo, quando você executa uma operação de identificação de processo para descobrir se foi bem-sucedida ou não. Um firewall pode servir como exemplo - se você estiver dentro da rede ou tiver um endereço IP interno, poderá executar algum tipo de operação e, se estiver fora da rede, a mesma operação será proibida.
Digamos que você visite um site que contém um link para outro servidor e talvez você não queira usar os privilégios necessários para seguir este link. Porque talvez isso conceda a alguém acesso à sua impressora de rede interna e que alguém possa usá-la. Mas, na realidade, quem forneceu o link não deve chegar à sua impressora, pois está localizada fora da rede. Ou o firewall do seu navegador, visitando este link, pode fazê-lo de maneira fraudulenta.

Esse é um tipo de equivalente moral desse problema confuso nos modelos de rede.
Público-alvo: as permissões existentes também afetam isso.
Professor: sim.
Público: porque
Capsicum usa essencialmente
DAC - controle de acesso discricionário.
Professor: sim, isso ocorre principalmente porque os funcionários da
Capsicum usam algo como controle de acesso discricionário. Isso significa que o usuário ou proprietário do objeto decide como será a política de segurança desse objeto. Para o
Unix, isso é muito natural - esses são meus arquivos, e eu posso decidir o que quero fazer com eles, posso dar a você ou mantê-los. Portanto, quase todos os sistemas
DAC se parecem com isso porque precisam de algum tipo de permissão que o usuário possa alterar para gerenciar a política de segurança de seus arquivos.

O outro lado do
DAC é o controle de acesso obrigatório. Falaremos sobre isso mais tarde, mas em algum nível, esses sistemas têm uma visão muito diferente do mundo. Eles acham que você é apenas um usuário de computador e outra pessoa define uma política de segurança para usar este computador. Essa visão surgiu nos anos 70 ou 80, quando os militares realmente queriam ter sistemas secretos de computador nos quais você trabalha em algumas coisas marcadas como "secretas". E se você estiver trabalhando em coisas marcadas como
“secretas” e eu estiver trabalhando em coisas rotuladas como
“secretas” , elas não poderão te levar tão facilmente. Mas não preciso definir os direitos para o arquivo e assim por diante, isso não é permitido por algum tipo de cara de primeira linha.
Assim, o controle de acesso obrigatório realmente tenta colocar vários tipos de políticas de acesso em primeiro lugar, onde há um usuário e um desenvolvedor de aplicativos, e além deles, há outro cara que define essa política. No entanto, como você pode imaginar, isso nem sempre funciona. Falaremos sobre isso um pouco mais tarde. Mas esse é o significado essencial do controle de acesso discricionário.
Temos muitos outros exemplos de uso de controle de acesso externo. Isso não é necessariamente ruim, você só precisa ter muito cuidado ao usá-lo. Se você possui um sistema de
privilégios de ambiente , precisa ter muito cuidado ao executar operações privilegiadas. Você precisa se certificar de que está realmente usando as permissões corretas e não será enganado acidentalmente, como neste
compilador Fortran há quase 25 anos.
Portanto, essa é uma das interpretações do que está acontecendo. E essa não é necessariamente a única maneira de pensar sobre o que está errado, certo? Outra possibilidade é que seria bom se o próprio aplicativo soubesse se deveria acessar o arquivo em nome de algum princípio. Portanto, o problema número 2 é a complexidade das verificações de controle de acesso.

De certo modo, quando o compilador
Fortran está em execução, ele abre o arquivo em nome do usuário e é necessário repetir a mesma lógica que vemos aqui no diagrama, exceto que o
compilador Fortran deve conectar outra coisa para o
UID do processo Sur . Em vez de usar os privilégios atuais, ele deve simplesmente repetir a verificação
Nome -> Objeto -> Permissão e tentar fazer isso com um conjunto diferente de privilégios para o
UID do processo .
No
Unix, isso é bastante difícil, porque há muitos lugares onde as verificações de segurança ocorrem. Se você tiver links simbólicos, o link simbólico será verificado e o nome do caminho também será avaliado com alguns privilégios e assim por diante. Mas pode acontecer que, em algum sistema, você possa simplificar a verificação do controle de acesso, se isso puder ser feito independentemente no aplicativo. Você não acha que este é um plano inteligente? Você concorda com isso? Existe o risco de repetir este teste?
Público: se você fizer checagens no aplicativo, simplesmente não poderá fazer outras checagens.
Professor: sim, você pode facilmente ignorar outras verificações, isso é absolutamente verdade. De certa forma, quando eles usaram o compilador
Fortran aqui, ele nem tentou fazer nenhuma verificação, então eles falharam. Outra conseqüência, além da falta de verificações, é que o kernel pode mudar o tempo todo e, em seguida, terá verificações ligeiramente diferentes. Isso introduzirá alguns requisitos de segurança adicionais, mas o aplicativo não será alterado e implementará o estilo antigo de verificações. Portanto, este não é um bom plano.
Lembre-se de que existe uma boa ideia no campo da segurança - uma redução no número de mecanismos envolvidos. Portanto, o programa possui apenas um pequeno número de locais em que as políticas de segurança são aplicadas. Você provavelmente não deseja repetir a mesma funcionalidade em aplicativos, no kernel e assim por diante. Você realmente deseja focar essas verificações em um local do programa. Então, qual deve ser a solução para o problema de concessão de autoridade?
Mais perto de resolver o problema estão os recursos do descritor de arquivos no
Unix .

No mundo das possibilidades, uma alternativa para esse esquema é que, em vez de seguir a cadeia
Nome -> Objeto -> Permissão e decidir usá-lo com base nas permissões externas do
processo UID do
processo de processo , você pode usar um esquema muito simples.
Suponha que você tenha recursos relacionados a um objeto específico. E esses recursos podem ter várias limitações quanto ao que você pode fazer com esse objeto.

Mas, basicamente, se você tiver oportunidades para esse objeto, poderá acessá-lo. . , , , .
,
Capability , , , , . .
Capability , - , — .
Capability , . , ?
, , . , . , , .
, , , « ». , ,
Capsicum ? ?
: , , ,
Capability .
: , , , , . — .
Unix , 0, , 1, . . , , . , - , , .
PID , ,
PID:57 , . , , . , , , , , .. .

, , , . , -, - , .
, , ,
Unix , , ,
/etc/pwd .
. . , . , « »?

, ,
integer . , . , .
, . , ? , . , .
, ,
Capability ,
Fortran .
sysx/fort ? , ?
: , . , ,
output- . , , .
: , . ,
Fortran /sysx/stat . , .
, , . , , «»
Unix . , , ,
Fortran , , , , , .
.
fort1 , , - , ,
foo.f , , , —
o ,
. , . , .
, , , . ! , , , ,
setuid Fortran .

,
setuid - , . , . , , , , .
, , , , . , , ,
Capability , , , , .
26:30
:
Curso MIT "Segurança de sistemas de computadores". 6: «», 2.
Obrigado por ficar conosco. Você gosta dos nossos artigos? Deseja ver materiais mais interessantes? Ajude-nos fazendo um pedido ou recomendando a seus amigos, um
desconto de 30% para os usuários da Habr em um análogo exclusivo de servidores básicos que inventamos para você: Toda a verdade sobre o VPS (KVM) E5-2650 v4 (6 núcleos) 10GB DDR4 240GB SSD 1Gbps de US $ 20 ou como dividir o servidor? (as opções estão disponíveis com RAID1 e RAID10, até 24 núcleos e até 40GB DDR4).
Dell R730xd 2 vezes mais barato? Somente nós temos
2 TVs Intel Dodeca-Core Xeon E5-2650v4 128GB DDR4 6x480GB SSD 1Gbps 100 a partir de US $ 249 na Holanda e nos EUA! Leia sobre
Como criar um prédio de infraestrutura. classe usando servidores Dell R730xd E5-2650 v4 custando 9.000 euros por um centavo?