Pontos Principais
- Raramente engenheiros questionam se um software é seguro, mas quase todos os sistemas deveriam se preocupar com a segurança;
- A Internet das coisas (IoT) expande a área de abrangência de potenciais ataques, bem como os tipos de danos que podem ser causados;
- A diferença entre um software seguro e inseguro é sutil;
- Diversas técnicas de análise, incluindo FTA, STAMP e máquinas de estado UML, podem ajudar a identificar possíveis falhas em um sistema;
- Não espere a solução perfeita, qualquer incremento que torne seu software mais seguro é valioso.
Esse software é seguro? Em toda a minha carreira, ouvi essa pergunta de apenas um dos meus funcionários e meus clientes de consultoria.
Em nossa batalha de metodologias, nós gastamos uma energia imensa em funcionalidades, histórias, épicos, técnicas de extração de requisitos e metodologias de testes. Mas afinal, o que produzimos é seguro?
Um produto seguro:
- Não causa danos materiais, financeiros e nem aos dados;
- Não causa danos físicos, emocionais ou de reputação aos seres humanos ou outras criaturas;
- Resiste a ameaças de segurança de fontes maliciosas as quais podem comprometer as características #1 ou #2,
Estado atual da área
Em Julho de 2015, os white-hat (chapéu branco) hackers Charlie Miller e Chris Valasek assumiram o controle do Jeep Cherokee 2014 conduzido pelo jornalista Andy Greenberg. Enquanto Greenberg dirigia a 70 milhas por hora, Miller e Valasek, sentados em um local a 10 milhas do veículo, manipularam o ar condicionado do carro, o rádio, a exibição do painel, habilitaram e desabilitaram os freios e, por fim, causaram completa pane no veículo. Depois que a história de Greenberg ganhou repercussão nacional, a Fiat Chrysler realizou o recall de 1,4 milhão de Cherokees, para dois meses depois se envergonhar novamente quando teve que realizar outro recall de 8,000 SUVs equipadas com o mesmo componente inseguro UConnect.
Uma coletânea de histórias de hacking automotivo é mantida no site de Security Affairs (Aventuras/Casos de Segurança). Como engenheiro de software, estou profundamente incomodado com o fato de que especialistas da indústria afirmam que os fabricantes de automóveis estão muito defasados em relação ao resto da indústria de software. De acordo com Ed Adams, pesquisador da Inovação de Segurança que testa a segurança de automóveis:
As técnicas e tecnologias utilizadas por fabricantes de automóveis sao ultrapassadas. Os softwares de automóveis não são criados com os mesmos padrões, por exemplo, de um sistema bancário, ou do software que é produzido na Microsoft.
Enquanto buscamos umaInternet das coisas onipresente, quando somos desafiados com uma nova e perturbadora vulnerabilidade nos questionamos: "Por que alguém não antecipou isso?" Sergey Lozhkin, da Kaspersky Lab, relatou falhas de segurança perturbadoras em equipamentos médicos. Lozhkin concentrou sua atenção nas clínicas para determinar a vulnerabilidade desses equipamentos. Em uma das clínicas, ele relatou:
Testei a rede Wi-Fi e consegui me conectar a um equipamento de ressonância magnética (MRI), e encontrar informações pessoais e falhas na arquitetura. Fiquei assustado com a facilidade. O vetor inicial do ataque foi a rede Wi-Fi, pois a rede não era tão segura quanto deveria, especialmente em um lugar onde você mantém registros médicos (dados de saúde dos pacientes).
Seus relatórios terminam com uma visão perturbadora. Lozhkin afirmou:
Esta é uma área onde os pesquisadores de segurança "white-hat" e criminosos têm muito interesse, pois trata-se de um grande mercado potencial. Como exemplos podemos citar a pirataria de carros, carros conectados, equipamentos médicos, entre outros.
A Insegurança é sutil
O Juramento de Hipócrates diz: "Acima de tudo, não faça mal". Contudo, falhas de segurança muitas vezes podem ser sutis, por exemplo, uma mensagem enviada duas vezes devido a um atraso de rede ou ainda um commit corrompido em um banco de dados. Muitas vezes nós consideramos estes erros como simples e abstratos, mas a diferença entre um remédio e o um veneno é apenas na dosagem. Estas falhas podem levar seu banco de dados a um estado corrompido mas ainda operacional, gerando inconsistências posteriores difíceis de se rastrear.
Testar melhor nosso software é apenas parte da solução para tornar nossos códigos mais seguros. Uma mentalidade de verificação agressiva de segurança é essencial. Mas como determinar se nosso software possui vulnerabilidades?
Nem sempre é fácil encontrar esta resposta pois muitas vezes não conseguimos nem imaginar cenários de falha. Por exemplo, um editor de texto pode causar mal?
Considere que você criou um documento em seu editor de texto como o abaixo. O símbolo " <\t> " representa o caractere TAB.
Você salva o documento e, depois de algum tempo, abre o mesmo arquivo no seu editor. Contudo, a estrutura do documento é diferente.
Nós percebemos que um caractere TAB desapareceu. Mas quanto isto é perigoso? A resposta é o que foi omitido do trecho anterior. Foi retirado o cabeçalho das colunas correspondentes a cada TAB. Este é o documento "real" contendo os cabeçalhos: prisoner name (nome do prisioneiro), to be hanged (a ser enforcado) e to be released (para ser solto):
"Me perdoe Chester, este bug será corrigido no próximo release." Este exemplo é originado de um Plano de Teste da Marinha dos EUA para fidelidade de documentos. O cenário foi alterado para simplicidade.
Soluções do mundo real
Para determinar o nível de segurança, nós não devemos somente confiar nos testes no nosso código do produto. Quantidade de defeitos e segurança são questões independentes. Zero defeitos pode ainda significar software inseguro pois defeitos são relacionados à especificação do sistema, mas ela muitas vezes pode estar incorreta. Esta é a razão para muitos defeitos nos surpreenderem: "Como isto aconteceu"", "Isto não deveria nunca ter acontecido" ou "Eu nunca pensei neste caso".
Uma técnica de análise importante que podemos utilizar no desenvolvimento dos produtos é a Fault Tree Analysis (FTA - Análise da Árvore de Falhas). A FTA produz um modelo visual de eventos e caminhos que podem levar a falha de um componente de sistema. Conceitualmente, a análise da árvore de falhas possibilita identificar estados finais/terminais não pretendidos ou inseguros e, ainda, identificar as condições que levaram a este estado terminal.
A FTA incorpora conceitos tradicionais de lógica booleana (AND, OR, XOR) como gates (portas). Caminhos e eventos alimentam estes gates e geram a árvore dos estados indesejáveis. O exemplo abaixo é dos estados de dor de cabeça severa e suas causas potenciais.
FTA é uma técnica poderosa desenvolvida para projeto de sistemas com estados finais conhecidos e é baseado na filosofia que a falha destes sistemas é originada da falha dos componentes de hardware e software. Diagramas de árvore de falhas são simples de serem criados por qualquer profissional técnico, por exemplo, no Microsoft Visio. Baseado na minha experiência, FTAs combinados com diagramas UML de máquinas de estados são muito úteis para entender o que pode ocorrer de errado em um sistema.
Uma alternativa às FTAs é a técnica STAMP (System-Theoretic Accident Model and Processes). Criada pelo especialista em segurança Nancy Leveson, esta técnica foca no sistema como um todo e na interação entre os componentes do sistema. A tese de Levenson é que falhas ocorrem quando os sistemas entram em estado perigoso (hazardous) e este estado é consequência da aplicação inadequada das restrições de segurança ao comportamento do sistema.
Por se tratar de uma visão sistência, a técnica STAMP é mais complexa quando comparada a criar diagramas de análise da árvore de falhas. STAMP possui uma semântica rica e suporta diversas perspectivas na análise dos fatos, incluindo: cadeia de eventos, condições casuais e agentes que contribuíram para a condição de falha sistência. Por também incorporar restrições, níveis hierárquicos de controle e modelo de processos, esta técnica também pode ser aplicada a desenvolvimento e entrega de produtos.
E como isto se aplica ao desenvolvimento Web?
O desenvolvimento de software evoluiu de aplicações simples para o que eu chamo de "softwares" - interação entre múltiplas unidades funcionais, em diversas linguagens, executadas em diversas plataformas de forma concorrente e cada uma destas unidades é produzida por grupos e empresas diferentes. Nós vivemos em um mundo de sistemas de sistemas e a interação na interfaces destes produtos são os pontos de falha potencial. Devemos adotar todas as ferramentas que ajudem a termos uma visão mais clara da segurança (safety) do software que produzimos.
Preocupações relativas à segurança são presentes desde a especificação até o release do produto. Para enfrentar estas questões, nós não devemos esperar a resposta perfeita: se focada, mesmo uma abordagem fragmentada pode ser um importante passo em direção a segurança dos nossos sistemas.
Diagramas UML de máquinas de estado nos ajudam a identificar estados que são perigosos ou possam corromper o sistema. Um exemplo é o estado "catch all" (pegue tudo) que ocorre quando o programador não sabe qual lógica executar e enquanto um componente estiver neste estado inválido, um evento ou mensagem pode ser recebido e não será processado.
Avaliar cenários de múltiplas threads é sempre complicado. Nós devemos buscar uma análise compreensiva das regiões críticas, a possibilidade de condições de corrida (race conditions), deadlocks potenciais e outras anomalias de multithreading.
Quando seu código detecta um erro, ele deve encerrar a thread, o processo ou a aplicação? Ou ele deve continuar executando o sistema em modo limitado? Nós devemos listar os benefícios e riscos de cada um destes cenários e escolher o melhor entre eles, sempre tendo a segurança em primeiro lugar.
A complexidade das aplicações modernas é assombrosa e o acesso não autorizado de veículos conectados e dispositivos médicos é apenas o início do problema. Produtos de software já mataram.
No início dos anos 80, a indústria de software pela primeira vez se mostrou letal. A máquina de diagnóstico médico Therac-25, aplicou uma overdose de radiação X em seis pacientes.
A tragédia com o Therac-25 teve muitas causas, entre elas:
- Reuso de software do modelo anterior, o Therac-20.
- Mudanças na interface de usuário que não foram aplicadas nos subsistemas de controle.
- Condições de corrida (race conditions).
Três dos seis pacientes que receberam a overdose faleceram em resultado da exposição a radiação.
Mas isto foi consequência da falta de testes? De acordo com Leveson, o fabricante executou testes extensivos, mas talvez não os testes necessários. Simuladores de hardware foram o principal mecanismo de testes do software. É tentador assumir que se o software não existe bugs, ele deve ser seguro. Contudo isto muitas vezes não é verdadeiro.
No meio do seu relatório, Leverson faz uma afirmação em relação ao código assembly PDP-11 que pode ser aplicável aos dias de hoje:
Os erros foram relativos a más práticas de engenharia de software em uma máquina que depende de software para uma operação segura. Além disto, o erro de codificação em particular não é importante se comparado ao design inseguro do dispositivo.
O problema desta afirmação, quando aplicada aos design atual de software, é que normalmente um produto de software está além da nossa habilidade de compreendê-lo com precisão. Nós somos confrontados com um paradoxo. No desenvolvimento ágil, nós entregamos pequenos conjuntos de funcionalidades de forma a entender melhor os requisitos, design e execução do código. Mas como cada conjunto é adicionado aos conjuntos anteriores, as interações dos nossos sistemas compostos por sistemas crescem exponencialmente, diminuindo a nossa compreensão, entendimento e confiança do que entregamos.
Maturidade leva tempo
FTA, STAMP e modelos UML são ferramentas que nos ajudam a produzir sistemas mais confiáveis. Relatórios de falha na nossa indústria sugerem que devemos aumentar de forma agressiva a nossa preocupação com a segurança de nossos produtos, além de desenvolver a funcionalidade correta. Veículos wireless vulneráveis, dispositivos médicos expostos, redes de hospitais inseguras, babás eletrônicas vulneráveis, smart TVS que possibilitam que hackers escutem suas conversas são provas que devemos tornar o nosso mundo digital mais seguro.