Doze pecados mortais em programação e como evitá-los
Autor: Tarcisio Souza | Publicado: 2010-12-30T23:43:00-02:00


Blindar o código ou deixá-lo aberto? O que faz mais sentido, criptografia própria ou entregar-se às soluções prontas? Qual a decisão mais correta?






Grande parte das peculiaridades das linguagens de programação se deve ao fato de seu emprego ser propício apenas em ocasiões absolutamente singulares. O resultado disso são plataformas de programação obscuras, merecedoras de horas de estudo e de pesquisa, além de testes.

Web sites com implementações XML, por exemplo, podem não ter a instrução de avisar ao navegador que ele deve se prepara para receber dados nessa forma. Quando isso acontece, as funções não são executadas de forma propícia, até que os valores correspondentes sejam encontrados.


Desenvolvedores sofrem especialmente com programas desenvolvidos pelo que é conhecido na indústria de TI como Noob (novato, inexperiente). Estruturas antiquadas e ausência de recursos que aumentem a robustez dos códigos estão entre os principais motivos de seu descontentamento.

Mas existem outras questões, todas de cunho técnico, capazes de tirar definitivamente o sono dos desenvolvedores.

Erro de programação #1 – Um código relapso

O caminho mais rápido em direção a um programa falho consiste em relaxar na hora de desenvolver seu código. É comum isso se transformar em conseqüências desastrosas, de acordo com a aplicação, por parte de um usuário despreparado. Perguntas _ como será que uma entrada 0 é capaz de achar seu caminho até a operação de divisão? Terá o texto submetido no tamanho correto? O formato das entradas foi verificado? A identidade do usuário é verificada na base de dados? _ acabam não sendo feitas, levando a pequenos erros que podem comprometer um programa inteiro.

Para piorar ainda mais, o design avançado de linguagens de programação modernas, que deveriam corrigir esse tipo de contingência, não dá conta de cumprir seu papel. Um exemplo disso é a última versão do Java, em que foi implementada a tentativa de facilitar a checagem por “null-pointers” com base em sintaxes abreviadas para a realização dos ensaios de apontadores. Basta adicionar um ponto de interrogação a cada invocação de método; automaticamente será incluído um teste de “null-pointers” que ajuda a subsituir uma miríade de argumentos if-then desse tipo:

&nbsp;&nbsp;&nbsp; public String getPostcode(Person person) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String ans= null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (person != null) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Name nm= person.getName();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (nm!= null) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ans= nm.getPostcode();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ans&nbsp;&nbsp;&nbsp; }

Por isso:

&nbsp;&nbsp; public String getFirstName(Person person) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return person?.getName()?.getGivenName();&nbsp;&nbsp;&nbsp; }

Mesmo assim, no final das contas, esse tipo de correção de códigos apenas evita que o código trave, sem garantir que seja um código útil. Porque, em uma abordagem pragmática, percebe-se que esses recursos não erradicam o problema principal: a proliferação de valores nulos, resultado de programação relapsa.

Erro de programação #2 – Ser refém de detalhes

Na contramão do argumento anterior, códigos ultra detalhados podem transformar uma execução breve em um processo que se arrasta parecendo não ter fim. Nada contra verificar alguns null pointers, mas existem códigos que são um exemplo de paranóia, dada sua rotina de verificação obsessiva.

Sobrecarregar códigos com rotinas de verificação pode ser mal interpretado por determinados sites, o que ocasiona a negação de serviços na rede. Tenho vários pacotes que, de tanto verificar se existem atualizações, rodam de maneira lenta se não estiverem sendo executados em um PC conectado à web.

O desafio nesse caso é escrever um código com camadas que chequem os dados assim que eles aparecem. Em bibliotecas que exigem a participação de vários programadores ou que sejam feitas por um programador apenas é bastante complicado manter o controle sobre as verificações de pointers.

Erro de programação #3 – Complicar funções de controle

Equivale a implorar que aconteça um desastre.

“Meu maior arrependimento é ter trabalhado no desenvolvimento de um código base por três anos sem me importar em torná-lo modular. Aprendi da pior maneira quais são os resultados de não respeitar princípios de SIngle Responsibility (atribuições singulares). Hoje, não há um código novo que eu não comece por revisar a fatoração do código original”, diz Mike Subelsky, um dos fundadores da OtherInBox.com.

Como você deve desconfiar, Subelsky é um programador de Ruby on Rails, um framework que incentiva a criação de códigos simples, pois parte do princípio de a estrutura principal do código seguir padrões usuais. No jargão de programadores da plataforma Ruby esse procedimento é chamado de convenção no lugar de configuração. O software parte do princípio de que, se o programador criar um objeto de valor “name” com dois campos, sendo estes “first” e, outro, “last”, ele (o programa) deve fundar duas bases de dados com os mesmos nomes. A definição dos nomes em apenas um campo evita que surjam complicações caso alguém esqueça de manter todas as camadas em sincronia.

Erro de programação #4 – Deixar tudo na mão dos frameworks

Ao interpretar as intenções do programador, os frameworks terminam gerando mais confusão do que o esperado deles e dificultam a identificação de possíveis erros de programação.

Para G. Blake Meike, profissional de programação sediado nas imediações de Seattle, o excesso de confiança em frameworks “inteligentes” é um impeditivo quando se trata de criar códigos limpos.

Para Meike, a convenção é algo que deve acontecer fora do software, ela deve ser fruto do acordo entre quem programa. “A não ser que você seja íntimo das regras adotadas pelo Ruby on Rails na hora de transformar uma URL em um método de chamadas, você jamais saberá o que acontece em resposta a uma requisição”, diz.

“Se, por um lado, as regras são bastante razoáveis, elas estão longe de serem triviais. Trabalhar com Ruby requer conhecimento. À medida que o aplicativo cresce, se torna cada vez mais essencial saber detalhes dessas regras. No final das contas, de tantos detalhes triviais em sua natureza, mas não em seu conteúdo, dominar a programação&nbsp; Ruby significa saber viver em um ecossistema singular”.



Erro de programação #5 – Acreditar no cliente

Boa parte dos erros de programação aparecem quando o desenvolvedor parte do princípio de que o cliente sabe o que fazer. Um código, por exemplo, escrito para rodar em um browser, pode ser reescrito pelo navegador com a finalidade de executar qualquer ação arbitrária. Cabe aos desenvolvedores realizar dupla verificação dos dados retornados, pois tudo pode dar errado.

Entre os ataques mais elementares, encontra-se o fato de alguns programadores permitirem a transmissão de dados do cliente diretamente para a base de dados. Nada de errado até o cliente decidir enviar informações no formato SQL no lugar de repostas válidas. Sites que solicitam o nome do usuário e o adicionam às requisições podem ser atacados por usuários que decidam responder informando um nome “x; DROP TABLE users;“. O que acontece é que a base de dados partirá do princípio do nome do usuário "x" e seguirá para o próximo comando, apagando a tabela contendo todos os usuários.

Outras ocasiões que propiciam o abuso por parte de usuários mais experientes são as pesquisas digitais. O Buffer overrun continua sendo um dos métodos mais elementares para corromper softwares.

Para piorar, várias brechas de segurança podem surgir da união de três de quatro supostas brechas benignas. Um programador pode permitir que um cliente escreva um arquivo partindo do princípio de as permissões do diretório serem suficientes para evitar escritas em locais proibidos. Pouco depois, outro programador pode alterar as permissões temporariamente para corrigir um bug randômico. Sozinhas, essas circunstâncias não oferecem grande risco, mas uma vez combinadas, dão acesso privilegiado ao cliente.

Erro de programação #6 – Desconfiar demasiadamente do cliente

Em função de rotinas fortemente orientadas à segurança muitas vezes afastarem os usuários, alguns desenvolvedores web procuram afrouxar a segurança ao máximo. Isso facilita a interação de visitantes com os produtos além de propiciar uma defesa mínima de suas informações na hora de configurar uma conta, por exemplo.

Existe uma variedade de jeitos que permitem às bases de dados armazenar menos informação enquanto fornecem o mesmo serviço. Existem ocasiões em que a solução irá funcionar sem que guarde qualquer dado legível.

Erro de programação #7 – Confiar cegamente em caixas mágicas

Programadores são, definitivamente, profissionais de muita sorte. Afinal de contas, cientistas de computação continuam criando bibliotecas intermináveis com correções para todo e qualquer mal que assole o código. O problema, ao mensurarmos com certa leviandade o trabalho de terceiros, é terminar criando situações de risco no código, em função da complexidade que cerca o projeto.

“Criptografia é um dos algozes dessa realidade”, diz John Viega, um dos autores do “24 Deadly Sins of Software Security: Programming Flaws and How to Fix Them” (Os 24 pecados mortais em segurança de software – como corrigir erros de programação). “A maioria dos programadores parte do princípio de que linkar dentro da biblioteca de criptografia é garantia de robustez”, diz.

Erro de programação #8 – Querer reinventar a roda

“Desenvolver um método de criptografia próprio é um convite aos hackers”, diz Viega. O autor sabe que até programadores cometem erros quando tentam prevenir seus sistemas dos ataques de outros usuários ou de explorarem eventuais fraquezas em seus sistemas.

Então resta a perguntar em quem confiar. Em você ou nos outros “especialistas” em segurança?

A resposta para tal pergunta se encontra na sala e na mente dos gestores de riscos. Muitas bibliotecas dispensam perfeição, o que permite que se use a primeira solução em criptografia disponível.

Erro de programação #9 – entregar o controle nas mãos dos usuários

Programadores amam incrementar seus produtos com opções de otimização e de adequação para o usuário customizar o aplicativo. O problema é que a maioria dos usuários não tem ideia de como fazê-lo.

Um bom exemplo disso é o Android. A última vez que instalei um software para um smartphone com esse sistema, foram necessários cinco ou seis parâmetros de acesso aos dados. Apesar disso revelar esmero por parte da equipe do Android em desenvolver um sistema altamente personalizado e customizável, as opções de acesso aos recursos como a câmera e o GPS podem deixar um usuário menos experiente confuso. Quando transferem às mãos do usuário o poder de definir tais configurações também abrem as portas do sistema para, em caso de configuração imprecisa, deixar entrar pessoas mal-intencionadas no sistema.

A ironia está no fato de os usuários desejarem essas opções quando decidem por este ou aquele sistema. Quando chega a hora de configurar o ambiente, faltam as informações necessárias para realizar esses ajustes de forma adequada.

Erro de programação #10 – Simplificar demasiadamente

Para alguns desenvolvedores, a solução nos casos de múltipla escolha é deixar apenas uma opção aberta ao usuário. O Gmail é famoso por restringir as opções de uso aos desenvolvedores. Não há como criar diretórios. Por outro lado, é possível marcar cada tipo de mensagem com uma tag própria. Na perspectiva de desenvolvedores,&nbsp; isso pode ser ainda mais funcional que as pastas.

Pode até ser. Mas dificulta a compreensão por parte dos usuários. O resultado desse tipo de idiossincrasia é dar oportunidade à concorrência, ao passo que tentar agradar a gregos e troianos acaba custando muito caro.

Erro de programação #11 – Blindar o código

Um dos maiores desafios impostos às empresas é definir quantas informações serão partilhadas com os usuários.

O co-fundador de uma das empresas pioneiras no segmento de código aberto, a Cygnus Solutions, diz que a decisão de não distribuir o código fonte junto dos produtos é uma das maneiras mais rápidas de esfriar os ânimos do público em geral.

As vantagens em abrir o código dos sistemas são variadas. É previsível que ele cresça com uma estrutura aperfeiçoada à medida que passa pelas mãos de vários colaboradores. Deixar o código fonte aberto consiste em tornar o programa mais confiável e compreensível.

Erro de programação #12 – Abrir o código a espera de perfeição

Milhões de projetos de código aberto foram iniciados, mas poucos conseguiram reunir mais de meia dúzia de entusiastas. Se, por um lado, abrir o código é um incentivo na busca por um produto melhor, é necessário prover algum tipo de recompensa para os colaboradores da plataforma. As pessoas têm outras coisas a fazer em suas vidas. O código aberto irá competir com família, amigos, bares e empregos remunerados. Vale, ainda, ressaltar que o entusiasmo dos colaboradores na busca por opções e incremento dos recursos em um sistema pode resultar em um código com várias falhas de segurança.

Muitas vezes, projetos de código aberto são disponibilizados no sourceforge.net à espera do trabalho mágico dos gnomos digitais. Essa estratégia pode condenar um sistema antes mesmo dele começar de verdade.

Abrir as informações acerca de um projeto ainda é um repelente contra investidores. A noção geral de que esses projetos são repletos de hippies e pessoas com desprezo por lucro e outras iniciativas não é um grande incentivo para quem tem poder&nbsp; e desejo de fazer de uma iniciativa open source algo rentável.



Por&nbsp;INFOWORLD/EUA