Desenvolvo para a web há praticamente 8 anos. Pude ver muita coisa surgindo, tecnologias, conceitos, frameworks, aplicações, serviços… O bom de aprender cedo a desenvolver é que você presta atenção as falhas dos outros para não comete-las em seus projetos. Já vi absurdos completos, como um site em que os dados do login eram enviados via GET, usuário e SENHA, plaintext, na url de destino… Outros erros comuns, que por vezes me deparo são mais mascarados, mas qualquer desenvolvedor com o mínimo de experiência os conhece e deve tentar evitá-los. Um exemplo é SQL Injection… a técnica é conhecida desde sempre, no entanto, grandes portais ainda são vulneráveis a este “ataque” trivial, que qualquer usuário pode realizar. Já vi o site de um jornal importante, de grande circulação, abrindo as pernas para um “‘or 1 = 1’ ” colocados como usuário e senha… Mas o foco deste post não é este tipo de problema. Quero discutir aqui sobre outra fragilidade de aplicações web, ainda mais fácil de tratar do que SQL Injections ou XSS: Confiar na validação client-side.
Muita gente que desenvolve aplicações web atualmente, vem do mundo da programação desktop normal. Ao validar um campo (um textbox por exemplo), basta validar o valor inserido pelo usuário e processar aquele valor normalmente (se for o caso de inserção em banco de dados, vale a pena colocar validação no banco também, tanto para desktop como principalmente para web). Se quiser desabilitar algum campo, apenas desabilite ele na interface gráfica e pronto, o usuário não vai ter acesso à ele (não na prática, com facilidade suficiente). Ao desenvolver para web, assumir isto pode ser fatal para sua aplicação.
Modificar o conteúdo exibido em uma página, ou mesmo alterar os valores enviados via POST são atividades triviais, que um usuário com conhecimentos mínimos de HTML e/ou do protocolo HTTP podem fazer, usando complementos para o Firefox como o Firebug e o TamperData.
Através do Firebug, é muito fácil alterar por exemplo, o valor de um <option>, para enviar o valor que o usuário desejar, ao invés dos valores pré-definidos. Remover um “disabled” de um input checkbox ou radiobutton é trivial. Com a mesma facilidade, podem ser removidas as chamadas às funções javascript que realizam validação client-side. Confiar em validações feitas em javascript já não é algo muito inteligente, pois praticamente qualquer browser tem opções fáceis de desabilitar a execução de tais scripts.
A validação client-side no entanto não deve ser esquecida. Para o usuário honesto, sem intenção de quebrar o sistema ou explorar vulnerabilidades, ela é muito útil, diminuindo o tempo de resposta caso algum dado esteja incorreto (evitando que os dados sejam enviados, processados pelo servidor, verificados como incorretos e só então ser enviada uma mensagem de erro para o cliente corrigir os dados não conformes), melhorando assim a experiência do usuário.
Frameworks como ASP.NET oferecem facilidades para o desenvolvedor no momento de validar tanto client como server side. Os componentes de validação realizam uma validação client-side, no entanto, todas as verificações são novamente realizadas no momento em que os dados chegam no servidor. Caso estes não sejam válidos, Page.IsValid irá retornar false, e cabe ao desenvolvedor realizar uma verificação ao valor desta propriedade antes de usar os dados. No entanto, deve-se escolher corretamente as validações a serem realizadas em cada cenário, caso contrário, ainda assim poderão passar dados que não deveriam.
Se você acredita que isto é muito teórico, não acontece na prática, está enganado. Nestes dias, um amigo meu foi se inscrever em um curso. Eu e outro amigo já haviamos conseguido nos inscrever, mas as inscrições eram gratuitas, e as vagas haviam se esgotado quando este outro amigo tentou. Quando analisamos a página (escrita em ASP puro, não ASP.NET), percebemos que o radiobutton para escolher o curso que ele desejava estava com um disabled. Resolvemos alterar via Firebug (apenas remover o atributo disabled=”disabled” da tag), selecionar o curso e enviar o formulário. Resultado: Inscrição realizada com sucesso, e quando ele foi ao curso, estava o nome dele lá na lista de inscritos… Até certificado ele recebeu, tudo normal.
Num caso destes, teria que ser verificado se ainda existiam vagas no momento em que o servidor recebe a solicitação. Não precisaria nem de Firebug para um sistema que apenas valida client-side receber mais candidatos inscritos do que deveria. Uma página guardada em cache visitada antes do fim das vagas poderia inscrever várias pessoas. Outro cenário possível era se existisse apenas uma vaga aberta, mas 5 usuários tivessem carregado a página de inscrição ainda com esta vaga restante. Todos eles conseguiriam se cadastrar pela falta de uma validação server-side.
Neste caso, o efeito foi inofensivo. Não faltou lugar, comida (ótimo coffee-break por sinal 🙂 ) nem nenhum outro recurso necessário ao bom andamento do curso por causa desta inscrição adicional. No entanto, cenários em que o dano causado pela falta de verificações semelhantes podem ser consideráveis não são difíceis de imaginar.
Fica o recado, SEMPRE valide seus dados server-side para evitar problemas! Apesar do “trabalho” adicional (que varia consideravelmente dependendo da tecnologia que você estiver usando), vale a pena para garantir o comportamento que você ou seu cliente esperam do seu sistema.