7
Computação confiável Lições aprendidas em 5 anos de criação de softwares mais seguros Michael Howard - Microsoft Fonte: http://msdn.microsoft.com/pt-br/magazine/cc163310.aspx - Acessado em 08 de novembro de 2012 Conteúdo Não se trata apenas do código Corrija o código antigo primeiro Descarte! Elimine! Exclua! As ferramentas são fundamentais... a um ponto Automatize! Você nunca atingirá vulnerabilidades de segurança zero A segurança é uma batalha sem fim Não há um boletim de segurança mágico O mantra “muitos olhos” está certo! A atual negação de serviço é a exploração de amanhã Considerações finais Há cinco anos, Bill Gates enviou um memorando a todos os funcionários da Microsoft explicando a importância de criar um software mais seguro. Desde então, muitas pessoas na Microsoft trabalharam para aprimorar a segurança de seus produtos. Ao fazer isso, aprendemos muito sobre quais os requisitos para a criação de um software mais seguro. A segurança não é um campo estático – ela evolui constantemente à medida que os invasores atacam, os defensores defendem e cada lado aprende mais sobre as técnicas do outro. A segurança é uma corrida de armamento. Para ficar à frente e prever as manobras dos invasores, nós, os defensores, devemos aprender com nossos erros e criar formas melhores de impedir que os usuários sejam comprometidos. Sendo assim, o que aprendemos nos últimos cinco anos? A maioria dessas lições é praticamente óbvia, mas como muitas coisas aparentes, às vezes ajuda ter alguém indicando o caminho. Não se trata apenas do código A indústria de software, ou mais precisamente a indústria de qualidade de software, está concentrada em obter o código correto. Eu realmente não tenho problemas com isso, mas muitas vulnerabilidades de segurança não estão codificando esses problemas. Muitos problemas têm a ver com o projeto. Se você mantiver o foco somente na detecção de problemas de segurança no código, você perderá uma classe inteira de vulnerabilidades. Esse é um dos motivos pelos quais a Microsoft atribui a modelagem de ameaças e a análise de superfície de ataque como parte do Processo SDL (ciclo de vida do desenvolvimento da segurança). A modelagem de ameaças é uma técnica de análise que ajuda a identificar e

Computação Confiável - Lições aprendidas pela Microsoft sobre Desenvolvimento Seguro

Embed Size (px)

Citation preview

Computação confiável

Lições aprendidas em 5 anos de criação de softwares mais seguros

Michael Howard - Microsoft

Fonte: http://msdn.microsoft.com/pt-br/magazine/cc163310.aspx - Acessado em 08 de

novembro de 2012

Conteúdo

Não se trata apenas do código

Corrija o código antigo primeiro

Descarte! Elimine! Exclua!

As ferramentas são fundamentais... a um ponto

Automatize!

Você nunca atingirá vulnerabilidades de segurança zero

A segurança é uma batalha sem fim

Não há um boletim de segurança mágico

O mantra “muitos olhos” está certo!

A atual negação de serviço é a exploração de amanhã

Considerações finais

Há cinco anos, Bill Gates enviou um memorando a todos os funcionários da Microsoft

explicando a importância de criar um software mais seguro. Desde então, muitas pessoas na

Microsoft trabalharam para aprimorar a segurança de seus produtos. Ao fazer isso,

aprendemos muito sobre quais os requisitos para a criação de um software mais seguro.

A segurança não é um campo estático – ela evolui constantemente à medida que os invasores

atacam, os defensores defendem e cada lado aprende mais sobre as técnicas do outro. A

segurança é uma corrida de armamento. Para ficar à frente e prever as manobras dos

invasores, nós, os defensores, devemos aprender com nossos erros e criar formas melhores de

impedir que os usuários sejam comprometidos.

Sendo assim, o que aprendemos nos últimos cinco anos? A maioria dessas lições é

praticamente óbvia, mas como muitas coisas aparentes, às vezes ajuda ter alguém indicando o

caminho.

Não se trata apenas do código

A indústria de software, ou mais precisamente a indústria de qualidade de software, está

concentrada em obter o código correto. Eu realmente não tenho problemas com isso, mas

muitas vulnerabilidades de segurança não estão codificando esses problemas. Muitos

problemas têm a ver com o projeto. Se você mantiver o foco somente na detecção de

problemas de segurança no código, você perderá uma classe inteira de vulnerabilidades. Esse é

um dos motivos pelos quais a Microsoft atribui a modelagem de ameaças e a análise de

superfície de ataque como parte do Processo SDL (ciclo de vida do desenvolvimento da

segurança). A modelagem de ameaças é uma técnica de análise que ajuda a identificar e

reduzir os pontos fracos do projeto em um produto. A análise da superfície de ataque se

concentra em quais partes de um produto de software estão expostas a usuários não

confiáveis, sejam locais ou remotos. Um produto com uma ampla superfície de ataque tem

mais código exposto a usuários não confiáveis do que um produto com uma pequena

superfície de ataque. (Leia mais em

msdn.microsoft.com/msdnmag/issues/04/11/AttackSurface.)

A vulnerabilidade de saturação do buffer RPC DNS documentada no Microsoft Security Bulletin

MS07-029 (consulte microsoft.com/technet/security/Bulletin/MS07-029.mspx) permite que

um invasor tenha total controle de um sistema afetado. Nesse caso, houve certamente um

problema de código. No entanto, o código estava acessível a usuários anônimos e remotos

quando deveria estar restrito aos administradores. Dessa forma, o problema foi uma

combinação de vulnerabilidade de código e projeto. Analisei essa vulnerabilidade no blog do

SDL (consulte blogs.msdn.com/sdl/archive/2007/06/28/lessons-learned-from-ms07-029-the-

dns-rpc-interface-buffer-overrun.aspx).

Lição aprendida: É fundamental criar modelos de ameaças para detectar pontos fracos em

potencial do projeto e determinar a superfície de ataque do software. Você precisa se

certificar de que todas as ameaças materiais serão atenuadas e que a superfície de ataque será

a menor possível.

Corrija o código antigo primeiro

No que diz respeito à revisão de código, gosto de classificar o código pelo potencial de

vulnerabilidade. Escrevi um artigo sobre Segurança e a privacidade da IEEE, intitulado "A

Process for Performing Security Code Reviews" (em inglês), que explica as métricas que utilizei

para priorizar a revisão de código (você pode encontrar um link para o artigo no meu blog em

blogs.msdn.com/michael_howard/archive/2006/08/01/686029.aspx).

A primeira prioridade é o código antigo, pois é muito mais provável que ele tenha mais

vulnerabilidades de segurança do que o código mais recente. As ameaças estão em constante

evolução. O código antigo – até mesmo o código criado há alguns anos – foi criado quando as

ameaças eram diferentes do que são atualmente. Além disso, as técnicas usadas para criar o

código antigo não têm as técnicas de defesa e práticas recomendadas mais recentes. Da

mesma forma, o código herdado foi criado usando bibliotecas mais antigas e menos seguras. E,

finalmente, o código anterior foi criado com menos percepção situacional, em um momento

em que os desenvolvedores tinham pouco ou nenhum conhecimento de segurança.

Meu conselho é simples: todo o código antigo deve ser revisado manualmente quanto a

vulnerabilidades de segurança. Na verdade, essa é a finalidade da fase do esforço de segurança

do SDL na Microsoft. Embora o objetivo principal do SDL seja reduzir a probabilidade de os

desenvolvedores adicionarem novas vulnerabilidades a um produto, o esforço de segurança é

desenvolvido para forçar a equipe de desenvolvimento a verificar se há problemas no código

antigo.

Nenhuma outra métrica que avaliamos foi tão importante ao priorizar a revisão de código –

não a complexidade do código, nem a contagem do número de linhas, nem a formação do

código. O indicador número um da densidade potencial de vulnerabilidade é simplesmente a

idade do código.

Lição aprendida: Identifique todos os seus arquivos de código-fonte e classifique-os por idade,

em que idade é a data de “nascimento” do código. Execute a análise estática e revise

manualmente o código, começando primeiro com o código mais antigo.

Descarte! Elimine! Exclua!

Às vezes, um recurso pode não ser seguro o suficiente no atual cenário de ameaças. O recurso

pode ter sido bom há alguns anos, mas não é seguro atualmente não devido a vulnerabilidades

de código, mas sim às alterações no atual ambiente computacional.

Um bom exemplo disso é o serviço Alerter no Windows® que deveria mostrar o status de

impressão e enviar breves mensagens que seriam exibidas como pop-up na tela do outro

usuário. Isso se tornou rapidamente um mecanismo de spam. Portanto, tomamos a difícil

decisão de desativar o serviço por padrão no Windows XP SP2 e então o removemos

totalmente do Windows Vista®.

Outro bom exemplo são os protocolos herdados IPX e SPX. (Sim, sei que o IPv4 também é

antigo e tem seus próprios problemas.) No Windows Vista, simplesmente removemos o

suporte para o Microsoft® Client for NetWare Networks, pois o código era muito antigo e não

era utilizado pela maioria dos usuários.

Com o tempo, você verá que a Microsoft remove cuidadosamente os recursos mais antigos.

Como, alguns usuários contam com determinados recursos, é importante equilibrar o risco

com a utilidade.

Lição aprendida: Identifique os recursos antigos que podem ser problemas de segurança a

longo prazo e elabore um plano para eliminar tais recursos. Talvez a primeira etapa seja

continuar lançando o curso, mas desativá-lo por padrão. Então, na próxima versão do produto,

o recurso pode ser totalmente removido, mas disponibilizado como um download da Web

para aqueles que dependem absolutamente dele. Finalmente, interrompa o suporte para o

recurso. Apenas lembre-se de manter os clientes informados.

As ferramentas são fundamentais... a um ponto

No passado, eu era extremamente crítico em relação às ferramentas. Na verdade, não das

próprias ferramentas, mas a confiança excessiva de alguns desenvolvedores em relação a essas

ferramentas. Por ferramentas, quero dizer análise estática de código, análise binária e

similares que possam ajudar a determinar vulnerabilidades de segurança. Em meus velhos

tempos, eu era de certa forma menos rígido em relação a isso.

Se você tem muito código – digamos, um milhão de linhas – torna-se muito mais difícil analisar

todo esse código manualmente. As ferramentas são práticas porque analisam rapidamente

grandes faixas de código. No entanto, elas não substituem o intelecto humano. Além disso,

muitas delas tendem a não detectar vulnerabilidades por estarem preocupadas em manter

uma taxa de falso-positivos e falso-negativos o mais baixa possível. E, para ser totalmente

honesto, muitas ferramentas de análise de segurança criam uma quantidade tão ampla de

erros e avisos que pode ser muito difícil determinar quais bugs são reais.

É claro, se você vir uma grande quantidade de problemas, isso não significa que pode

simplesmente ignorar o resultado da ferramenta! Quando realizamos uma análise da causa

dos efeitos de uma vulnerabilidade de segurança, sempre temos que nos perguntar por que o

problema não foi detectado pelas nossas ferramentas. Existem três motivos possíveis: a

ferramenta não detectou a vulnerabilidade, a ferramenta a detectou mas separou

erroneamente o problema como prioridade baixa e a ferramenta de fato detectou o problema

e o revisor humano o separou erroneamente. Essa análise nos permite ajustar as nossas

ferramentas e treinamento ao longo do tempo.

As ferramentas de análise também são muito boas para determinar o potencial de

vulnerabilidades de segurança no código. Digamos que você tenha dois produtos, cada um

com aproximadamente 100.000 linhas de código C++. Você executa suas ferramentas em cada

base de código – para esse exemplo, vamos pressupor que você usa os comutadores de

compilador /W4 e /analyze. A primeira base de código produz 121 avisos /W4 e 19 avisos

/analyze, enquanto a segunda base de código tem 235 avisos /W4 e 65 avisos /analyze. Qual

conjunto de código você acha que precisa de mais revisão?

Finalmente, as ferramentas são excelentes quando executadas em código novo ou modificado

antes da verificação, pois podem atuar como protetores do código e detectar determinadas

classes de bug no início do processo.

Lição aprendida: As ferramentas de análise podem ajudá-lo a determinar qual o cuidado

necessário ao seu código. Você também pode usar o resultado da análise para determinar o

risco geral do código. Use as ferramentas no momento da verificação para detectar os bugs

precocemente. Além disso, execute as ferramentas com freqüência, de forma que possa lidar

rapidamente com novos problemas – se executar as ferramentas somente em intervalos de

meses poderá acabar tendo que lidar com centenas de avisos de uma só vez.

Automatize!

No início de um programa de melhoria de segurança, há uma quantidade significativa de

trabalho manual – revisão manual de código, revisões manuais de projeto e assim por diante.

Para realmente elevar seu trabalho, você precisa automatizar o máximo possível do processo.

Em nossa equipe, criamos muitas ferramentas personalizadas e criamos um site interno da

Web para coletar dados de ferramentas, de forma que a equipe de segurança central pudesse

revisar o resultado das ferramentas. Quando é proposta uma melhoria do SDL, essa proposta

deve incluir uma forma de automatizar a melhoria. Os principais motivadores para a

automação são a escalabilidade e o uso constante. Se você tiver uma quantidade significativa

de código, será necessário automatizar. E, se você quiser que partes de um processo sejam

repetidas constantemente, então a automação é obviamente a solução.

Lição aprendida: Sempre que possível busque a automação. Crie ou compre ferramentas que

verifiquem o código e carreguem os resultados em um local central para análise por

especialistas de segurança.

Você nunca atingirá vulnerabilidades de segurança zero

É triste, mas é verdade, mas você nunca terá vulnerabilidades de segurança zero. Lembro

quando lancei uma das primeiras atualizações de segurança para o Windows Vista. Alguns

usuários ficaram surpresos porque pensaram que a Microsoft alegava ter resolvido o problema

de segurança com o Windows Vista. Primeiro, eu não conheço alguém que tenha feito essa

alegação e, segundo, simplesmente não é possível atingir vulnerabilidades de segurança zero.

Embora as vulnerabilidades de segurança zero sejam o ideal, é ilusório achar que é possível

atingir essa condição. O fato é que o cenário da tecnologia está sempre em fluxo, as ameaças

são um alvo em movimento e a pesquisa de segurança está em andamento. Disse

anteriormente que a segurança é uma corrida de armamento. Adicionamos defesas aos nossos

produtos e os invasores se adaptam.

O seu código pode parecer totalmente isento de vulnerabilidades hoje, mas isso pode mudar

amanhã quando um novo tipo de vulnerabilidade for detectado. Por exemplo, em 15 de

outubro de 2003, a Microsoft lançou um boletim de segurança que corrigia uma

vulnerabilidade de script em diferentes locais no Outlook® Web Access, incluído com o

Microsoft Exchange 5.5. Em 4 de março do ano seguinte, a Sanctum (adquirida pela Watchfire

e agora pela IBM) divulgou um artigo que descrevia uma nova vulnerabilidade de script em

diferentes locais denominada divisão de resposta de HTTP. Seis meses depois, a Microsoft

divulgou outra atualização de segurança para o Outlook Web Access no Microsoft Exchange

5.5 para corrigir uma vulnerabilidade de divisão de resposta de HTTP. Então, o que aconteceu?

Em síntese, no momento em que o primeiro boletim foi lançado, os problemas de divisão de

resposta não eram conhecidos, mas o cenário mudou.

Lição aprendida: Certifique-se de que as pessoas na organização saibam que a meta é reduzir

as vulnerabilidades de segurança, mas que você nunca atingirá problemas de segurança zero

enquanto houver invasores buscando novas técnicas e vulnerabilidades.

A segurança é uma batalha sem fim

Nunca haverá um momento que você dirá, “concluímos a parte de segurança; o problema

agora está resolvido”. Essa é uma extensão do ponto anterior, mas com um ângulo levemente

diferente. É extremamente importante que você mantenha um treinamento contínuo para

seus engenheiros. Caso contrário, as habilidades podem ficar desatualizadas e a urgência se

dissipar ao longo do tempo. A segurança é fundamental e proteger os seus sistemas é

imprescindível. Como dito no ponto anterior, as novas ameaças e vulnerabilidades estão

constantemente sendo detectadas. Portanto, você deve tratar sempre a segurança como uma

tarefa que nunca é concluída.

Você também deve se conscientizar de que não há mais algo de especial em relação à

segurança. A segurança é simplesmente parte da conclusão do trabalho.

Lição aprendida: Continue fornecendo treinamento contínuo aos seus engenheiros e

certifique-se de que eles sempre estejam cientes da importância de solucionar os problemas

de segurança.

Não há um boletim de segurança mágico

As pessoas me perguntam com frequência “qual é o elemento mais importante do SDL?”. A

resposta é: tudo. Se uma parte do SDL comprovar não ser útil, ela será excluída do SDL. Cada

parte do SDL leva a uma redução nas vulnerabilidades de segurança. Portanto, quando escuto

alguém dizer que tem uma tarefa única e mágica para solucionar a segurança, como executar

ferramentas de análise estática ou treinar pessoas, ele não está cobrindo todas as suas bases

de segurança. Com certeza, as ferramentas de análise estática têm seu lugar e ensinar os

usuários é fundamental, mas não por eles mesmos. A segurança deve ser completa, bem como

deve ser parte do processo.

Lição aprendida Certifique-se de que você esteja solucionando a segurança de todos os

ângulos disponíveis. Caso contrário, você precisará alterar o seu processo!

O mantra “muitos olhos” está certo!

Renomado defensor de código-fonte, Eric Raymond, disse “tendo olhos suficientes, todos os

bugs são superficiais”. Ele está certo. Mas eu considero que essa afirmação simplificada peca

em um ponto principal. Ela deveria continuar assim, “desde que os olhos sejam incentivados e

instruídos”.

Na Microsoft, podemos exigir que as pessoas adotem melhorias de processo, pois esses

requisitos fazem parte do trabalho. Esse é o incentivo. Oferecemos ensino de várias formas,

como treinamentos dinâmicos, laboratórios e treinamento online. Portanto, há bastante

material para garantir que os engenheiros estejam atualizados com o que está acontecendo no

front de segurança.

Lição aprendida: Quanto mais olhos houver no código, melhor, mas isso deve ser feito em

uma determinada estrutura. Você deve garantir que os desenvolvedores fornecendo a revisão

do código tenham um incentivo para que se preocupem em se adaptar ao seu atual processo,

bem como que estejam treinados em relação às mais recentes ameaças de segurança.

A atual negação de serviço é a exploração de amanhã

Muitos fornecedores de software, incluindo a Microsoft, aprenderam essa lição arduamente.

Os engenheiros podem analisar o problema de código e rapidamente descartá-lo por ser

“apenas um DoS”. Lembre-se de que o mundo da pesquisa em segurança está em constante

evolução e as pressuposições sobre determinadas classes de vulnerabilidade podem mudar da

noite para o dia.

Lição aprendida: Não seja rápido ao descartar um problema de negação de serviço. Com

pouco trabalho, os usuários maliciosos podem transformar vulnerabilidades de DoS em

verdadeiras vulnerabilidades de execução de código.

Considerações finais

Se há algo que aprendi nos últimos anos é que, no que diz respeito à segurança, você precisa

estar preparado para ter suas ideias e ponto de vista constantemente desafiado, além de estar

sempre atualizado sobre os problemas mais recentes. Se você seguir à risca as lições

apresentadas neste artigo, você se sairá muito bem.

Michael Howard é um dos principais gerentes de programas de segurança na Microsoft e se

concentra no aprimoramento e nas melhores práticas do processo seguro. Ele é o co-autor de

muitos livros de segurança, incluindo Writing Secure Code for Windows Vista, The Security

Development Lifecycle, Writing Secure Code e 19 Deadly Sins of Software Security (em inglês).