Segurança em sistemas distribuídos

Autor: Vidal Martins - GPT

Durante o ano de 1997, Lisiane Maes Volpi, Marcelo Fermann Guimarães, Ricardo

Shoiti Ikematu e eu, Vidal Martins, fizemos uma pós-graduação em objetos distribuídos e, como trabalho de conclusão do curso, desenvolvemos um sistema de segurança.

Nosso interesse pelo tema desse trabalho, segurança em sistemas distribuídos, despertou quando assistimos uma aula na qual foi apresentado o Kerberos, um protocolo de autenticação desenvolvido no MIT e baseado no protocolo de chave-secreta de Needham e Schroeder. Sabíamos que a CELEPAR precisava aprimorar seu sistema de segurança a informações e encontramos nesses protocolos propostas inteligentes e compatíveis com as necessidades da empresa.

Este artigo descreve os perigos aos quais estão expostos os sistemas de informações e como funciona um protocolo de autenticação capaz de protegê-los. A solução de segurança que construímos na pós-graduação baseou-se nesses conceitos.

Algumas ameaças à segurança dos sistemas distribuídos são óbvias. Por exemplo, na maioria dos tipos de rede local é fácil construir um programa que obtenha cópias de mensagens transmitidas entre processos. Um programa desse tipo pode ser executado em um computador que já está conectado à rede ou em um que está infiltrado nela, através de um ponto de conexão sobressalente. Outras ameaças são mais sutis. Um programa pode se instalar como um servidor de arquivos e obter cópias de informações confidenciais contidas nos dados que os clientes encaminham para armazenamento.

Para se resguardar dessas ameaças, políticas de segurança devem ser adotadas e mecanismos de segurança devem ser empregados a fim de implementar tais políticas. A distinção entre políticas e mecanismos é útil quando se projetam sistemas de segurança, mas freqüentemente é difícil ter certeza de que um certo conjunto de mecanismos implementa plenamente as políticas desejadas. Note que as políticas independem de tecnologia.

A proposta de um sistema de segurança é restringir o acesso às informações e aos recursos, somente aos principals que estão autorizados. O termo principal é usado para designar os agentes que acessam informações e recursos mantidos em um sistema distribuído. Portanto, um principal é uma pessoa ou um processo. No modelo de segurança que adotamos, cada principal tem um nome e uma chave secreta.

Para produzir um sistema que seja comprovadamente seguro contra ameaças específicas, é necessário classificar essas ameaças e os métodos pelos quais cada uma delas pode se concretizar, isto é, os métodos de ataque, ou o modus operandi. As ameaças aos sistemas de computador subdividem-se em quatro grandes classes:

  • Leakage (vazamento): aquisição de informação por agentes não autorizados;
  • Tampering (falsificação): alteração não autorizada de informação (inclusive de programas);
  • Resource stealing (roubo de recursos): uso de facilidades sem autorização;
  • Vandalism (vandalismo): interferência na operação apropriada de um sistema sem ganhos para o criminoso;

Para violar um sistema através de quaisquer das estratégias apresentadas acima, é necessário acessá-lo. Virtualmente, todos os computadores possuem canais de comunicação para acesso autorizado às suas facilidades, e é através destes que o acesso não autorizado ocorre. Nos sistemas distribuídos, os computadores estão conectados a uma rede e os seus sistemas operacionais oferecem uma interface de comunicação padrão que permite o estabelecimento de canais de comunicação virtuais.

Os métodos pelos quais violações de segurança podem ser cometidas em sistemas distribuídos dependem da obtenção de acesso aos canais de comunicação existentes, ou do estabelecimento de canais que mascarem conexões aos principals, com a autoridade desejada. Isto inclui:

  • Eavesdropping: obtenção de cópias de mensagem sem autorização. Isto pode ser feito capturando mensagens diretamente da rede, ou examinando informações que estão inadequadamente protegidas em dispositivos de armazenamento de dados. Por exemplo, usando a Internet um computador pode ser configurado com o endereço de rede de outro, permitindo que este também receba as mensagens endereçadas àquele.
  • Masquerading (disfarce): envio ou recebimento de mensagens usando a identidade de outro principal sem a sua autorização.
  • Message tampering (falsificação de mensagem): captura e alteração do conteúdo das mensagens antes de passá-las ao destinatário. Isto é difícil de fazer em meios que se utilizam de broadcast para troca de mensagens, como é o caso das redes Ethernet. De maneira simplificada, podemos definir broadcast como sendo a entrega simultânea de uma mensagem para todas as estações da rede.
  • Replaying: captura e armazenamento das mensagens por um certo período de tempo, seguido do envio atrasado dessas mensagens aos seus destinatários. Este método de ataque não pode ser evitado por simples criptografia, uma vez que pode ser usado para operações do tipo vandalismo, ou roubo de recurso, mesmo quando as mensagens não podem ser interpretadas pelo criminoso.

Para lançar esses ataques em um sistema distribuído, o criminoso deve ter acesso ao sistema a fim de executar o programa que implementa o ataque. A maioria dos ataques são lançados por pessoas que são usuários legítimos do sistema. Para usuários ilegítimos, um método simples de infiltração é a adivinhação de senhas, ou o uso de programas de quebra de senhas para obter as chaves de acesso de usuários conhecidos. Além dessas formas diretas de infiltração, existem diversos métodos mais sutis, que estão se tornando bem conhecidos, tais como:

  • Vírus: um programa anexado a um hospedeiro legítimo, que se instala sozinho no ambiente alvo, sempre que o programa hospedeiro é executado. Uma vez instalado, ele realiza suas ações criminosas sempre que lhe apraz, freqüentemente usando uma data como gatilho.
  • Worm: um programa que varre um sistema, ou uma rede, replicando-se e buscando bloquear todos os recursos disponíveis, até torná-lo inoperante. Ao contrário do vírus, um worm normalmente não destrói dados.
  • Cavalo de Tróia: um programa oferecido aos usuários de um sistema como sendo capaz de realizar uma função útil, mas que tem uma segunda função oculta. O exemplo mais comum é o spoof login, um programa que apresenta aos usuários um diálogo idêntico ao diálogo normal de obtenção de login (nome do usuário) e password (senha), mas que na realidade armazena as informações fornecidas pelos usuários em um arquivo, com o objetivo de uso posterior ilícito.

A discussão acima, sobre ameaças e métodos de ataque, leva-nos à conclusão de que para construir um sistema distribuído seguro, nós devemos projetar seus componentes partindo do princípio de que os agentes do sistema (pessoas e programas) não são confiáveis, até que provem o contrário. No entanto, é impossível produzir um sistema útil considerando que não há nenhum componente confiável. Assim sendo, o objetivo passa a ser produzir um sistema no qual um número mínimo de componentes sejam considerados confiáveis.

Os mecanismos de segurança para sistemas distribuídos baseiam-se no uso de três técnicas: criptografia, autenticação e controle de acesso.

A criptografia de mensagens possui três papéis principais na implementação de sistemas seguros. Em primeiro lugar, é usada para esconder informação privada nos lugares do sistema onde ela estiver exposta, como por exemplo num canal de comunicação, o qual é vulnerável a eavesdroping e message tampering. Esta aplicação de criptografia corresponde ao seu uso tradicional em atividades militares e de inteligência. Baseia-se no fato de que uma mensagem criptografada com uma chave específica só pode ser descriptografada por um agente que conheça a chave inversa correspondente. Nosso sistema de segurança usa criptografia com este objetivo.

A segunda utilidade desta técnica é apoiar mecanismos de autenticação que suportam a comunicação entre pares de agentes do sistema. Um agente que descriptografa uma mensagem com sucesso, usando uma chave inversa específica, pode assumir que a mensagem é autêntica se ela contém algum valor esperado. Então, se as chaves são mantidas em sigilo, uma descriptografia com sucesso autentica a mensagem decodificada como sendo proveniente de um agente específico. Nosso sistema de segurança também utiliza criptografia com este objetivo.

A terceira aplicação da técnica é a implementação de um mecanismo conhecido como assinatura digital. Este mecanismo simula o papel das assinaturas convencionais, verificando com um terceiro se a mensagem é uma cópia inalterada daquela produzida pelo agente específico. A habilidade de prover assinaturas digitais depende da existência de alguma coisa que o agente emissor da mensagem possa fazer que outros não possam. Isso pode ser atingido requisitando-se a um terceiro confiável a criptografia da mensagem de maneira convencional, ou em uma forma reduzida chamada digest. A mensagem resultante deste processo, ou o digest, age como uma assinatura que acompanha a mensagem. A autenticidade dessa assinatura pode ser verificada pelo agente receptor, requisitando-se ao mesmo terceiro confiável uma nova criptografia da mensagem. Nosso sistema de segurança não faz uso de assinatura digital.

A outra técnica que serve de base teórica para mecanismos de segurança de sistemas distribuídos é autenticação. Esta técnica é o meio pelo qual as identidades dos agentes clientes e servidores são estabelecidas de maneira confiável. O mecanismo utilizado para atingir esse objetivo baseia-se na posse de chaves de criptografia, isto é, podemos inferir que um agente tem a identidade que afirma, se ele possui a chave secreta apropriada. Assim como nos trabalhos de espionagem ou nas sociedades secretas, a posse da senha é exigida para autenticar o possuidor da identidade.

Os mecanismos de autenticação para sistemas distribuídos tomam a forma de um serviço de autenticação, quando implantados em um ambiente computacional. Esse serviço deve prover funcionalidades como geração, armazenamento e distribuição de todas as chaves de criptografia necessárias ao sistema. Nosso sistema de segurança implementa um servidor de autenticação, cujo protocolo será descrito mais adiante.

A última técnica relativa a segurança é controle de acesso. Os mecanismos de controle de acesso preocupam-se em assegurar que os acessos aos recursos de informação (por exemplo, arquivos, processos, ou portas de comunicação) e aos recursos de hardware (servidores de impressão, pools de processadores ou gateways de rede) estejam disponíveis apenas para os usuários autorizados a fazê-los. Realizar controle de acesso é a principal missão do nosso sistema de segurança. Esse controle é feito com base em informações obtidas de forma criptografada e mediante autenticação dos agentes que se comunicam.

A seguir, apresentamos o protocolo de autenticação no qual se baseou nosso sistema de segurança. Nesse protocolo é possível observar também operações de criptografia. Primeiramente, será dada uma visão esquemática do protocolo e, em seguida, ele será explicado em detalhes, através de um exemplo.

 

A

è

S:

A,B,NA

S

è

A:

{NA, B, KAB, {KAB, A} KB} KA

A

è

B:

{KAB, A} KB

B

è

A:

{NB} KAB

A

è

B:

{NB-1} KAB

A: Objeto que inicia a comunicação;

B: Objeto parceiro de A na comunicação;

KA: Chave secreta do objeto A;

KB: Chave secreta do objeto B;

KAB: Chave secreta usada exclusivamente para comunicação entre os objetos A e B;

NA: Número gerado por A para certificar-se de que está se comunicando com S;

S: Servidor de autenticação no qual os objetos confiam;

{M}k:Mensagem M criptografada usando a chave K.

Vamos entender esse processo através de um exemplo. Suponha que existe um usuário chamado João, o qual utiliza a versão 1.5 de um sistema de informações destinado à gerência de recursos humanos, denominado SRH. Transportando esse contexto para um sistema computacional, temos dois objetos que precisam se comunicar, de tal forma que nenhum outro elemento seja capaz de entender os dados que eles trocam: um usuário e uma versão de aplicação. Devido a essa capacidade de comunicação sigilosa chamamos ambos os objetos de principal. O sigilo da mensagem é obtido através de operações de criptografia e descriptografia, usando chaves secretas. Isto nos permite concluir que todo principal deve possuir uma senha, a qual será conhecida apenas por ele e por um servidor de autenticação em quem ele confie. Então, vamos completar nosso exemplo: a senha de João será sjoão e a senha de SRH 1.5 será ssrh15. Traduzindo os elementos desse contexto para o esquema apresentado anteriormente, temos o seguinte:

A: é o usuário João (é um principal que inicia uma comunicação);

B: é a versão de aplicação SRH 1.5 (é o principal parceiro de A na comunicação);

KA: é a chave secreta de João - sjoão;

KB: é a chave secreta de SRH 1.5 - ssrh15.

Para que o objeto João (A) consiga iniciar uma "conversa" segura com o objeto SRH 1.5 (B), os seguintes procedimentos de autenticação são executados:

(A è  S: A,B,NA): João (A) envia uma mensagem ao servidor de autenticação (S), que conhece sua senha e a de muitos outros objetos, solicitando que este gere um ticket de acesso. Para tanto, João (A) informa seu nome (A), o nome do objeto com quem deseja se comunicar (B), SRH 1.5, e um identificador de mensagem (NA). Note que, no passo 2, João (A) receberá de volta o identificador de mensagem (NA), porém criptografado através da sua própria chave ({NA} KA), que só é conhecida por ele mesmo e pelo servidor de autenticação em quem ele confia (S). Assim sendo, João (A) terá certeza de que foi respondido pelo autenticador em quem confia (S) se, ao descriptografar o identificador de mensagem, encontrar exatamente o valor que enviou no passo 1 (NA).

(S è A: {NA, B, KAB, {KAB, A} KB} KA): após receber de João (A) a solicitação de um ticket de acesso para se comunicar com a versão de aplicação SRH 1.5 (B), o servidor de autenticação em quem os dois confiam (S) prepara as informações requisitadas e as envia para o João (A). Como isso funciona? Em primeiro lugar, o servidor de autenticação (S) procura no seu catálogo de principals os dois objetos envolvidos na conexão (João e SRH 1.5) e recupera suas respectivas chaves secretas. Em seguida, o autenticador (S) gera aleatoriamente uma chave secreta (KAB) que deve ser usada nas trocas de mensagens entre João (A) e SRH 1.5 (B). O próximo passo é a preparação do ticket de acesso que foi solicitado ({KAB, A} KB). Note que essa informação está criptografada com a chave secreta de SRH 1.5 (KB, portanto João (A) não conseguirá desvendá-la quando recebê-la, apenas SRH 1.5 será capaz disso. No passo 3, João (A) enviará o ticket para o SRH 1.5 (B) que, ao descriptografá-lo, descobrirá quem deseja contatá-lo (A - João) e qual chave secreta deve ser usada nessa conexão (KAB). Finalmente, o servidor de autenticação (S) criptografa todas as informações que João (A) necessita, utilizando sua chave secreta, e lhas envia. Vale observar que, neste caso, B representa a referência de SRH 1.5, ou seja, é uma informação que permite localizar o objeto SRH 1.5 na rede, antes de interagir com o mesmo.

(Aè B: {KAB, A} KB): João (A) recebe as informações produzidas pelo servidor de autenticação (S) no passo 2 e realiza algumas tarefas antes de prosseguir no passo três. Em primeiro lugar, descriptografa a resposta do autenticador usando sua chave secreta. Em seguida, certifica-se de que o autenticador não é um impostor, isto é, verifica se o identificador de mensagem está correto. Depois, guarda a chave secreta de conexão entre João (A) e SRH 1.5 (B) (KAB) para utilizá-la mais tarde, durante uma troca de mensagens. Finalmente, obtém a referência de SRH 1.5 (B) para enviar-lhe a mensagem registrada neste passo 3. Esta mensagem é simplesmente o ticket de acesso gerado pelo servidor de autenticação (S). João (A) envia o ticket para o SRH 1.5 (B) e espera receber como retorno um enigma, ou seja, um valor criptografado através da chave secreta de conexão entre João (A) e SRH 1.5 (B) (KAB), o qual deve ser interpretado, convertido para outro valor e devolvido ao SRH 1.5, no intuito de provar-lhe que o objeto interlocutor é realmente João (A) e não um impostor.

(B è A: {NB} KAB): a chegada de um ticket em SRH 1.5 (B) indica que o objeto origem da mensagem deseja se comunicar de forma segura. Antes, porém, de começar o intercâmbio de informações, o SRH 1.5 (B) deve certificar-se de que não está interagindo com um impostor. Com esse objetivo, ele envia para seu interlocutor um enigma ({NB}KAB), criptografado com a chave secreta de conexão entre João (A) e SRH 1.5 (B) (KAB), guardando uma cópia desse dado. Se o objeto interlocutor for realmente João (A), saberá interpretar o enigma.

(A è B: {NB-1} KAB): somente João (A) e SRH 1.5 (B) conhecem a chave de conexão KAB. Quando recebe o enigma (NB), João (A) descriptografa essa informação e a converte em outro valor, que representa a solução do enigma (NB-1). Em seguida, criptografa esse valor usando a chave secreta KAB e envia para SRH 1.5, que confere a informação e, caso esteja correta, estabelece a conexão. Se o objeto que interage com SRH 1.5 é um impostor, ele não conhece KAB e conseqüentemente soluciona o enigma de forma equivocada. Neste caso, não será estabelecida a conexão entre os objetos.

Observe que em momento algum circulam pela rede as senhas dos objetos que se comunicam. Elas são usadas apenas para codificar e decodificar as mensagens de autenticação. Este é o grande mérito desse processo.