Programação defensiva é um conjunto de técnicas de projeto (do inglês design) e programação objetivando a estabilidade e a segurança de um software independentemente de seu imprevisível. A ideia pode ser vista como forma de reduzir ou eliminar a hipótese de as Leis de Murphy terem efeito. Técnicas de programação defensiva começaram a ser desenvolvidas quando sistemas de software começaram a possibilitar efeitos catastróficos, seja deliberadamente ou inadvertidamente.
Aqui estão algumas dicas em programação defensiva de forma a evitar problemas de segurança. Muitas dessas técnicas também melhoram a qualidade geral do código, uma vez que qualquer defeito de maior porte pode ser potencialmente usado por um cracker para um ataque como DoS.
Perceba que essas técnicas não são suficientes para garantir segurança.
gets
e scanf
não devem ser usadas por não terem nenhum valor de tamanho máximo.Crackers provavelmente inventarão novos tipos de dados incorretos. Por exemplo, se você checou se um arquivo solicitado não é "/etc/passwd", um cracker pode pedir "/etc/../etc/passwd".
De uma maneira geral, é preferível usar mensagens de exceções e de erros inteligíveis de forma que não haja surpresas desagradáveis no cumprimento de contratos relativos a APIs para que a robustez e a segurança do seu software sejam boas.
Pré-condições, pós-condições e validação de variantes também são parte da programação defensiva. Isso pode envolver verificar argumentos passados a uma função ou método depois da execução do corpo da função. Depois do corpo da função, verificar o estado do objeto (OO) ou outro dados também é uma boa ideia.
Dentro de funções, você pode querer verificar mais de uma vez se algo que você está usando não é inválido. Uma boa heuristica é não confiar nas bibliotecas que você não escreveu. Sempre que você chamar elas, cheque o que recebe delas.