Lições Sobre Desenvolvimento de Código Seguro

Desenvolver um programa complexo e amplamente utilizado sem que ele tenha qualquer falha de segurança em 10 anos de vida é um feito de engenharia de segurança. Por isso é leitura obrigatória o artigo do Daniel J. Bernstein (DJB) com os seus pensamentos sobre segurança após 10 anos do qmail. Para os não-iniciados, DJB é professor da Universidade de Illinois em Chicago, e desenvolveu o qmail para ser uma alternativa de MTA mais segura que o sendmail. Ele ambém é o autor do djbdns, uma alternativa mais segura ao BIND.

(O sendmail é open source. O qmail não é open source. O sendmail teve centenas de vulnerabilidade de segurança identificadas. O qmail não teve nenhuma. Mas não existe relação entre uma coisa e outra.)

Como desenvolver um software mais seguro? No seu artigo DJB dá três respostas:

¦ Eliminar os bugs - Esta é claro é a resposta mais óbvia e inevitável. Nada substitui um corrigir os bugs existentes, e o artigo reforça os pontos que todos os fluxos de dados devem ser explícitos (evitando fluxos de dados implícitos via, por exemplo, variáveis globais), cuidado com as operações de inteiros e no parsing de dados, e atenção com código que raramente é executado (como código de tratamento de erros).

¦ Eliminar código -   Michael Howard faz a mesma consideração ao listar as lições aprendidas pela Microsoft com o processo de desenvolvimento de software seguro. Menos código implica em menos bugs, inclusive menos bugs de segurança. Descarte, elimine, exclua a funcionalidade que não é necessária. Crie funções para fazer operações comuns, como abrir arquivos, tratar exceções ou acessar bancos de dados.

¦ Eliminar código trusted - Código untrusted (não vou me arriscar a traduzir) é aquele, não importa o quão ruim ele seja, não consegue violar os requisitos de segurança do usuário. DJB recomenda que a maior parte do código do seu programa seja untrusted, rodando em "containers" lógicos, e que o código trusted do qual a segurança do sistema realmente dependa seja o mínimo possível.

Este acaba sendo para mim o ponto principal do artigo. DJB ataca o princípio do "menor privilégio" como sendo uma distração: segundo ele, de nada adianta ter código rodando em privilégio baixo se a segurança do usuário ainda assim dependa dele. Na arquitetura de um sistema, deve-se identificar não código executando com alto ou baixo privilégio, e sim código que seja trusted e untrusted.

Sobre esse ponto, uma pérola ontem no caderno de Informática da Folha (somente para assinantes). Uma leitora pergunta se o Linux é realmente mais seguro. José Antonio Ramalho responde dizendo que, "devido a sua arquitetura, [o Linux] é reconhecidamente mais seguro que o Windows".

Como assim?? A explicação vem em seguida:

Ao contrário do Windows, onde um vírus, uma vez instalado, tem controle total da máquina, no Linux o vírus afeta, em principio, apenas o usuário que executou o programa.

Ahhhhhhh bom! O vírus afeta apenas você... Deixando de lado todo o enorme número de vulnerabilidades de elevação de privilégio, a Folha não enxerga justamente a diferença entre código de baixo privilégio e código untrusted. Mesmo rodando em baixo privilégio, o malware pode violar os requisitos de segurança do usuário apagando os seus arquivos, enviando e-mails em seu nome, acessando as sessões abertas nos seus sites Web, utilizando o sistema para enviar spam e armazenar pedofilia/pirataria, etc.

Rodar softwares baixo privilégio é uma boa medida (caso contrário a Microsoft não teria investido tanto no UAC do Vista, ignorado pela Folha), mas não representa uma proteção absoluta contra malware. É preciso ainda dar um passo alguns passos além, o que eu pretendo comentar em breve.

UPDATE: Thomas Ptacek comenta o mesmo paper.