Uma análise do ciclo de vida do desenvolvimento da segurança na Microsoft

Por Michael Howard

Este artigo discute:

Visão geral do ciclo de vida do desenvolvimento da segurança

Segurança nos processos de design e de desenvolvimento

Modelagem de ameaças e teste

Revisões de segurança e respostas

Este artigo usa as seguintes tecnologias:
Ciclo de vida do desenvolvimento da segurança

Os objetivos do SDL (Security Development Lifecycle, Ciclo de vida do desenvolvimento da segurança), agora adotado pela Microsoft, são dois: reduzir o número de defeitos de codificação e de design relacionados à segurança e reduzir a gravidade de todos os demais defeitos. Isso segue nosso lema freqüentemente citado: "Seguro por design, seguro por padrão, seguro em implantação e comunicação" (também conhecido em inglês como SD3+C). O SDL se concentra principalmente nos dois primeiros elementos desse lema. Seguro por design significa que o design e o código serão seguros desde o início e Seguro por padrão é o reconhecimento de que isso jamais ocorrerá. Na realidade, você jamais obterá o código 100 por cento correto, mas isso será analisado posteriormente, quando tratarmos da redução da superfície de ataque.

Este artigo descreve a aplicação do SDL aos processos de desenvolvimento do próprio software. Explicarei como você pode utilizar algumas das lições que aprendemos na Microsoft ao implementar o SDL, para que possa usar esses conceitos no seu próprio processo de desenvolvimento. Porém, antes de começar, gostaria de deixar claro que o SDL não reconhece o processo no que se refere ao desenvolvimento do software por você. Realmente tanto faz usar um modelo em cascata, um modelo em espiral ou um modelo ágil; você também pode usar os aprimoramentos do processo do SDL. O SDL envolve a modificação dos processos de uma organização de desenvolvimento de software através da integração de medidas que levam a uma segurança de software aprimorada. A ótima novidade é que o SDL aprimora a qualidade do software, reduzindo os defeitos de segurança.

O SDL adiciona verificações e medidas específicas de segurança a todo processo de desenvolvimento de software existente. A Figura 1 mostra como o SDL mapeia em um processo "genérico". Se for do seu agrado, envolva o SDL em uma espiral ou em cascata.

Examinarei cada fase principal e descreverei o que você pode fazer dentro da sua organização para implementar o SDL.

Liderança e treinamento

Freqüentemente me perguntam por que o SDL é tão bem-sucedido na Microsoft. A resposta é muito simples: suporte executivo, treinamento e reconhecimento. Foi fundamental Bill Gates e Steve Ballmer terem se comprometido com o SDL, mas uma força de trabalho de engenharia capacitada é igualmente fundamental.

Para liderança, é preciso designar uma ou mais pessoas como os responsáveis pela segurança. Suas tarefas incluem ficar à frente de questões de segurança, promover práticas de segurança na organização de desenvolvimento e ser a voz da razão quando for necessário tomar decisões difíceis em relação à segurança. (Se você está lendo este artigo, provavelmente essa pessoa é você.) O líder (ou líderes) deve monitorar os vários grupos de notícias relacionados à segurança, como o Bugtraq (http://www.securityfocus.com/).

Se os seus engenheiros não conhecem nada sobre essas filosofias básicas de segurança, os tipos de defeitos de segurança comuns, o design seguro básico ou os testes de segurança, não há realmente chance de produzirem um software seguro. Digo isso porque, na média, os engenheiros de software não prestam muita atenção à segurança. Eles podem saber muito sobre recursos de segurança, mas precisam ter um melhor conhecimento sobre o que é necessário para criar e fornecer recursos seguros. É pena que o termo segurança possa implicar os dois significados, pois esses dois territórios de segurança são muito distintos. Os recursos de segurança mostram como funciona a coisa; por exemplo, as operações internas do modo seguro do Java ou do CLR (Common Language Runtime) ou como funcionam os algoritmos de criptografia, como o DES ou o RSA. Apesar de serem tópicos muito interessantes e úteis, saber que o algoritmo de criptografia DES é uma rede Feistel de 16 rodadas não ajudará as pessoas a criarem softwares mais seguros. Conhecer as limitações do DES, e o fato de que seu tamanho de chave infelizmente é pequeno para as ameaças atuais, é muito útil e esse tipo de detalhe é a principal filosofia de como criar recursos seguros.

O verdadeiro problema é que a maioria das escolas, universidades e cursos técnicos ensina recursos de segurança, e não como criar softwares seguros. Isso significa que há muitos engenheiros de software sendo formados por essas escolas ano após ano que acreditam que sabem criar softwares seguros apenas porque sabem como um firewall funciona. Resumindo, você só pode contar que a pessoa contratada saberá criar defesas de segurança para o seu software se perguntar a ela especificamente qual sua experiência e seu conhecimento do assunto.

Algumas boas fontes para treinamento em segurança online e dado por instrutor incluem o Microsoft eLearning (http://www.microsoftelearning.com/security/). O guia de segurança para desenvolvedores é resultado de alguns materiais básicos de segurança que apresentamos na Microsoft.

Você também deve criar uma biblioteca com bons livros sobre segurança, como os listados na Figura 2.

Alguns grupos na Microsoft formaram clubes de livros onde cada um lê um capítulo de determinado livro e depois o analisa com o grupo. Para ampliar seu conhecimento, eles procuram exemplos de defeitos ou de problemas de design em territórios comuns de segurança, como o Bugtraq.

Suponha que os responsáveis pela segurança na sua empresa façam apresentações sobre tópicos de segurança, incluindo defeitos de código de segurança comuns (estouro de buffer, scripts intersites, injeção de SQL, aritmética de inteiros, criptografia fraca etc.), design seguro, modelagem de ameaças e testes de segurança. Para dar mais profundidade e relevância às discussões, procure defeitos no seu próprio código e use-os como exemplos para os outros desenvolvedores.

Por fim, a equipe de engenheiros deve ser incentivada a atualizar suas habilidades pelo menos uma vez ao ano, sozinhos ou participando de eventos de desenvolvimento de equipes. Deve haver um controle sobre isso, para que as pessoas não se acomodem. É realmente importante as pessoas estarem no topo do panorama de segurança, já que ele muda com rapidez. Um erro comum hoje pode ser uma vulnerabilidade na segurança amanhã.

Início da páginaInício da página

A fase de design

A melhor oportunidade de influenciar o design de segurança de um produto é no início do ciclo de vida do produto. É na fase em que os arquitetos, desenvolvedores e designers tradicionalmente executam o grosso do design dos recursos. O design normalmente tem início com uma breve descrição da funcionalidade esperada (algumas vezes na forma de um pequeno resumo funcional), seguida de uma especificação funcional que descreve a visão do recurso pelo cliente, seguida, por sua vez, de uma especificação de design que descreve os detalhes técnicos, mostrando como o recurso será implementado.

Se você estiver usando um método de desenvolvimento ágil, poderá simplesmente optar pelo resumo menor, de uma página, mas essa página deverá incluir os aspectos de segurança do componente. Talvez seja necessário que as especificações funcionais descrevam os recursos de segurança que serão expostos diretamente para os clientes, como a exigência de autenticação do usuário final para acesso a dados específicos ou funcionalidade avançada. As especificações de design deverão descrever como implementar recursos de segurança e garantir que todas as funções serão implementadas como recursos seguros. Observe o uso da palavra seguro em vez de segurança. Os recursos seguros são definidos como uma garantia de que todas as funções possuem boa engenharia em relação à segurança, como o uso intenso de APIs Crypto, o uso de código gerenciado sempre que possível, validando rigorosamente todos os dados antes de processá-los, além de várias outras considerações. Ao projetar recursos, é fundamental considerar com bastante atenção as questões de segurança para evitar incluir a segurança no produto no final do processo de design.

Todas as especificações de funções e de design, independentemente do tamanho do documento, devem conter uma seção que descreva como o componente influencia a segurança. Para ter algumas idéias sobre o que adicionar a esta seção, consulte a RFC 3552 "Guidelines for Writing RFC Text on Security Considerations".

Uma parte importante do processo de design é entender como você reduzirá a superfície de ataque do seu aplicativo ou componente. Portas UDP acessíveis anonimamente ou abertas para a Internet representam uma superfície de ataque maior do que, por exemplo, uma porta TCP aberta acessível somente a um conjunto restrito de endereços IP. Não pretendo levar muito tempo com este assunto; consulte o meu artigo sobre redução da superfície de ataque "Mitigate Security Risks by Minimizing the Code You Expose to Untrusted Users" (em inglês), em MSDN®Magazine novembro de 2004. A Figura 3 lhe fornecerá uma referência rápida para a redução da superfície de ataque do seu código.

Início da páginaInício da página

Modelagem de ameaças

A modelagem de ameaças deve ser concluída durante o processo de design do produto. Uma equipe só pode criar um produto seguro se conhecer os bens que o produto está tentando proteger (informações pessoais do cliente, como números de cartão de crédito, para não mencionar seus computadores), as ameaças e vulnerabilidades apresentadas pelo produto e os detalhes de como o produto reduzirá essas ameaças. Além disso, é importante considerar as ameaças e vulnerabilidades presentes no ambiente em que o produto está implantado ou que surjam devido à interação e à interface com outros produtos ou sistemas em soluções de ponta a ponta do mundo real. Para esse fim, a fase de design de um produto não pode ser considerada concluída até que exista um modelo de ameaça. Os modelos de ameaça são componentes fundamentais da fase de design e farão referência às especificações funcionais e de design do produto para descrever vulnerabilidades e atenuações.

Conhecer as ameaças ao software é uma etapa fundamental à criação de um produto seguro. Muitas pessoas incluem uma tecnologia de segurança no aplicativo e o declaram seguro, mas o código só é seguro quando as contramedidas de segurança realmente resolvem as ameaças do mundo real. Essa é a meta da modelagem de ameaças. Para ter uma boa noção do processo em menos de 30 minutos, é recomendável ler a entrada do blog "Guerrilla Threat Modeling", escrita pelo meu colega Peter Torr.

Início da páginaInício da página

A fase de desenvolvimento

Durante a fase de desenvolvimento, você deve implementar ferramentas de segurança, listas de verificação e as melhores práticas de codificação segura para ajudar a implementar um design seguro. Lembre-se, um design seguro pode muito facilmente se tornar inseguro devido a uma implementação fraca.

Antes de entrar nesse assunto, gostaria de mencionar algo muito importante. As ferramentas de segurança não tornarão seu software seguro. Elas ajudam, mas sozinhas não tornam o código resistente ao ataque. Simplesmente não há substituto para uma força de trabalho capacitada que use as ferramentas para impor a diretriz. A nova versão do Visual Studio® 2005 Team System Developer's Edition inclui algumas ferramentas de segurança muito úteis:

PREfast O PREfast é uma ferramenta de análise estática para código C/C++. Ela consegue detectar defeitos de segurança bastante sutis e alguns erros flagrantes também. É apenas uma pequena parte em termos de segurança.

SAL (Standard Annotation Language) De todas as ferramentas que adicionamos ao Visual Studio 2005, esta é a tecnologia que mais me anima, pois ela pode ajudar a encontrar alguns erros difíceis de localizar. Imagine a seguinte função:

void *function(
    char *buffer, 
    DWORD cbBufferLength);

Você sabe que buffer e dwBufferLength estão diretamente relacionados; o buffer tem cbBufferLength bytes. Mas o compilador não sabe disso -- tudo o que ele vê é um ponteiro e um inteiro de 32 bits sem sinal. Usando o SAL, você pode vinculá-los. Assim, o cabeçalho que inclui esse protótipo de função pode ser como este:

void *function(
    _in_bytecount(cbBufferLength) char *buffer, 
    DWORD cbBufferLength);

Observe que a sintaxe final usada no SAL pode mudar antes do lançamento do Visual Studio 2005.

FxCop Agora você já pode conhecer o FxCop -- é uma ferramenta para encontrar defeitos, incluindo defeitos de segurança em código gerenciado. Encontra-se disponível para download em http://www.gotdotnet.com/, mas a versão do Visual Studio 2005 está totalmente integrada e inclui algumas questões a serem observadas.

Application Verifier O AppVerifier é uma ferramenta de tempo de execução que opera em um aplicativo que está sendo executado. Pode ser usado para resolver problemas relacionados à memória em tempo de execução, incluindo saturações de buffer baseadas no heap.

Entre outras ferramentas e requisitos na Microsoft encontram-se:

Todo o código C/C++ não gerenciado deve ser compilado com o recurso de detecção de saturação de pilha /GS.

Todo o código C/C++ não gerenciado deve ser vinculado por meio da opção /SafeSEH.

Todo o código RPC deve ser compilado com o sinalizador MIDL /robust.

Os problemas de segurança sinalizados pelo FxCop e pelo PREfast devem ser corrigidos.

As funções mostradas na Figura 4 são excluídas do novo código e devem ser removidas com o passar do tempo do código antigo.

Leia sobre o código de substituição de seqüência de caracteres Strsafe em "Strsafe.h: Safer String Handling in C" (em inglês). A biblioteca Safe C é a nova substituta de biblioteca de tempo de execução C incorporada ao Visual Studio 2005. Leia sobre ela em "Safe! Repel Attacks on Your Code with the Visual Studio 2005 Safe C and C++ Libraries" (em inglês).

Início da páginaInício da página

Testes de segurança

Uma técnica de teste muito útil para localizar defeitos de segurança é a "difusão", que significa tomar dados válidos, metamorfoseá-los e depois observar um aplicativo que empregue esses dados. Em sua forma mais simples, você pode criar uma biblioteca de arquivos válidos que seu aplicativo utilize e depois usar uma ferramenta para corromper sistematicamente um arquivo e fazer seu aplicativo executá-lo ou processá-lo. Execute o aplicativo no verificador de aplicativos com verificação de heap habilitada para ajudar a descobrir mais erros. São exemplos de metamorfose de dados:

Troca de bytes aleatórios em um arquivo.

Escrita de uma série aleatória de bytes de tamanho aleatório em um local aleatório no arquivo.

Procura de inteiros conhecidos para alterar o sinal, ou aumentá-los ou diminuí-los demais.

Procura de caracteres ASCII ou Unicode e definição do caractere NULL à direita como não-NULL.

Michael Sutton e Adam Greene fizeram uma palestra interessante no Blackhat USA 2005 sobre difusão. Leia sobre o assunto em The Art of File Format Fuzzing (em inglês). Ejovi Nuwere e Mikko Varpiola também fizeram uma interessante apresentação sobre difusão no protocolo de rede VoIP, disponível em The Art of SIP Fuzzing and Vulnerabilities Found in VoIP (em inglês).

Início da páginaInício da página

Iniciando um esforço de segurança

Um esforço de segurança é o foco de toda a equipe em atualizações do modelo de segurança, na revisão do código, nos testes e nas minúcias da documentação. Observe que o esforço não é uma correção rápida para um processo que não possui disciplina de segurança; ele é, na verdade, uma tentativa centralizada de confirmar a validade das informações da Arquitetura de segurança, de descobrir alterações que possam ter ocorrido durante o processo de desenvolvimento e de identificar e corrigir quaisquer vulnerabilidades de segurança ainda existentes que você possa descobrir. Não é possível criar segurança em um software apenas com um esforço de segurança.

Não há maneira fácil de determinar quanto tempo é necessário para um esforço de segurança; a duração do esforço no fim é determinada pela quantidade de código que precisa ser revisado quanto à segurança, visto que todos os esforços até hoje foram embarreirados pela quantidade de código. As equipes são altamente incentivadas a tentar conduzir as revisões de código de segurança em todo o processo de desenvolvimento, desde que o código esteja razoavelmente estável, pois a qualidade das revisões de código será comprometida ao se tentar condensar um excesso de revisões de código em um período de tempo muito curto.

O princípio básico é determinar o código principal, usando a heurística tal como exposição à Internet, manipulação de informações sigilosas ou identificáveis pessoalmente, etc. e marcá-lo como código de prioridade um. Esse código deve ser revisto durante o esforço, e o esforço só pode ser concluído quando o código é revisado. Atribua um nome a cada arquivo de código e atribua um nome e uma prioridade ao código antes do esforço.

Início da páginaInício da página

Revisões finais de segurança

Quando se aproximar o final do projeto, uma pergunta muito importante deverá ser respondida: do ponto de vista de segurança, o software está pronto para o lançamento? A Revisão final de segurança (FSR) responde a essa pergunta. Ela é executada pela equipe de segurança central com ajuda da equipe de produto, mas não apenas pela equipe de produto. Normalmente é executada alguns meses antes da conclusão do software e inclui:

Completar um questionário, que ajuda a equipe de segurança a se concentrar no próprio esforço. As perguntas podem incluir:

Você possui controles ActiveX® marcados como Seguros para script?

Liste todos os protocolos que você difundiu.

O seu componente verifica conexões não autenticadas?

O seu componente usa UDP?

O seu componente usa um filtro ou aplicativo ISAPI?

Alguma parte do código é executada no contexto do sistema? Em caso afirmativo, por quê?

Você define ACLs no código de configuração?

Confira os erros que provavelmente "não serão corrigidos" e verifique se não são defeitos de segurança marcados erradamente.

Analise os defeitos de segurança de outras versões do produto e até mesmo dos produtos dos concorrentes para verificar se resolveu todas essas questões. Uma pergunta comum que fazemos é: "como você diminuiu essa ampla categoria de questões de segurança?".

Execute testes de penetração nos componentes de alto risco, talvez por meio de outra empresa.

No final do processo FSR, as descobertas são anotadas e é tomada uma decisão sobre o lançamento do software ou o retrabalho de seções.

Início da páginaInício da página

A resposta de segurança

Existem duas partes principais nesse processo. Uma é responder a defeitos de segurança e trabalhar com pessoas que descobrem problemas de segurança no seu código. O outro aspecto é aprender com esses erros. Na Microsoft, temos uma equipe dedicada cuja função é fazer a análise da causa dos defeitos. Esses documentos são então usados para influenciar iterações futuras do SDL. Cada documento post mortem inclui:

Nome e versão do arquivo.

O problema era de design?

O problema era de codificação?

Diferença do código-fonte se for um erro de codificação.

O erro afeta outras versões do produto? Em caso afirmativo, por quê? Em caso negativo, por que não? (Ambas as perguntas são muito válidas.)

Quais testes poderiam ter detectado esse defeito?

Quais ferramentas poderiam ter detectado esse defeito?

Precisamos alterar nosso treinamento, as ferramentas ou o processo para descobrir esses problemas?

As respostas são então usadas para modificar o SDL. O SDL na Microsoft é atualizado duas vezes por ano, em 1º de janeiro e em 1º de julho.

Início da páginaInício da página

O SDL funciona?

Então, a grande questão é: "o SDL funciona"? O uso das técnicas do Ciclo de vida do desenvolvimento da segurança resulta em softwares mais seguros? A resposta é um ressonante Sim! Constatamos a redução dos defeitos de segurança em aproximadamente 50 a 60 por cento quando acompanhamos o SDL. O fato é que todo produto tocado pelo SDL possui menos defeitos de segurança. Ponto. E isso certamente já basta para que ele seja adquirido.

Michael Howard é gerente de programas sênior na Microsoft e se concentra no aprimoramento e nas melhores práticas do processo seguro. Ele é co-autor de 19 Deadly Sins of Software Security (em inglês) (McGraw-Hill Osborne, 2005) e de Processes to Produce Secure Software (em inglês) (Dept. of Homeland Security National Cyber Security Division).


Início da páginaInício da página