Pressione enter para ver os resultados ou esc para cancelar.

Noções de Segurança da Informação para Times de Desenvolvimento Web – Parte 1

A imagem de hackers como pessoas extremamente habilidosas que tomam energético, ouvem The prodigy e que estão sempre de capuz preto pode surgir e criar um mau entendimento sobre o que é segurança de sistemas. Essa imagem idealizada faz com que tentativas de ataques sejam vistas como monstros implacáveis que só equipes de segurança com seus próprios monstros implacáveis podem resolver, quando muitas vezes são só gatinhos e tudo o que você precisava fazer era fechar a porta.

Por que sistemas são invadidos?

Antes de falar sobre métodos preventivos, primeiro é necessário dar contexto ao que é um ataque e quem está atacando. O objetivo aqui é tornar a palavra “ataque” menos abstrata no contexto de desenvolvimento web e, principalmente, tornar o “atacante” alguém menos idealizado.

 

Existem dezenas de motivações pelas quais um ataque começa, mas o foco desse post será em casos em que a motivação acontece por recursos ou dinheiro. Pois ambas costumam precisar de, relativamente, pouca habilidade e vão depender de sistemas vulneráveis. 

 

Dinheiro x Recursos

Essa distinção pode ser tênue, mas para esse texto eu vou definir dinheiro como um material intrinsecamente valioso como informações de usuários (logins e senhas, CPFs, e-mails, informações de cartão de crédito, etc…), propriedade intelectual (códigos fonte, informações internas, planos futuros etc…) e quaisquer outras coisas que podem ser vendidas, mas normalmente não são muito úteis para quem as adquire. 

 

Já recursos representam poder computacional de máquinas comprometidas e, portanto, possui  infinitas utilidades práticas, desde servir como proxy para realização de um ataque, simples anonimato ou até mesmo sustentar um ataque DDoS que pode derrubar toda a Playstation Network [1][2][3][4], além de usos mais especializados, como mineração de bitcoins, criação de bots, etc… 

 

O ponto a se entender aqui é que, em ambos os casos, a intenção não é danificar o sistema sendo atacado. O objetivo é obter algo e, se possível, não ser percebido. Portanto, o tipo de vulnerabilidade que uma pessoa que desenvolve para web deve priorizar são as que tornam seus dados ou recursos vulneráveis ao fácil acesso externo e não necessariamente em parar o Elliot Alderson.

 

Ataques direcionados x Ataques não direcionados

Além dessa distinção de recursos, é importante fazer uma distinção de ataques direcionados e ataques não direcionados. Ataques direcionados costumam envolver pessoas, não apenas habilidosas, mas também com algum propósito específico (ativismo, fama, dinheiro, prova de conceito, recursos, compartilhamento de informações, pentest, etc..), além da capacidade para analisar um sistema e criar um plano de ataque. Dada a natureza de sistemas complexos, não há nenhum sistema que seja imune a um ataque direcionado, sempre depende da habilidade e do tempo disponível da equipe que está atacando. Lidar com esse tipo de ataque é responsabilidade de uma equipe de segurança e foge do escopo de desenvolvimento.

 

Já ataques não direcionados buscam sistemas vulneráveis, quaisquer que sejam, desde empresas antigas com uma ampla base de usuários (onde quem desenvolve não tem tanta liberdade para realizar refatorações ou atualizar ferramentas), até startups com más práticas de desenvolvimento. Qualquer pessoa é capaz de realizar um ataque não direcionado, é possível achar sistemas vulneráveis e tutoriais para explorar esses sistemas em qualquer ferramenta de busca ─ o que não é muito legal de se fazer mas serve para ilustrar que o atacante nem sempre precisa ser um um gênio com décadas de prática; às vezes é só alguém entediado. 

 


O objetivo aqui é clarificar quais medidas podem ser realisticamente tomadas por uma equipe de desenvolvimento para reduzir a possibilidade de que seu sistema seja vítima de ataques genéricos, portanto este não vai ser um post para um blue team e sim uma contextualização de como falhas de segurança acontecem. O propósito é entender mais sobre um assunto pouco discutido, para que pequenas decisões tomadas no dia a dia façam um sistema mais seguro. Portanto, as informações serão menos técnicas, já que a perspectiva de um time de segurança é completamente diferente de um time de desenvolvimento; a ideia é apontar pro cinto de segurança e falar que ele deve ser usado, não ensinar como construir um carro seguro.

 

Como evitar que o seu sistema seja comprometido

Vale notar que diferentes tecnologias possuem diferentes vulnerabilidades. É sempre importante pesquisar o que sua stack provê por padrão na versão que você está usando (como autenticação, ORM, serialização de dados, etc..), quais convenções existem e o que elas garantem. Muitas vezes, simplesmente seguir as recomendações documentadas evita boa parte dos problemas descritos aqui, então antes de quebrar o padrão oferecido pela tecnologia que você está usando (seja usar flags que ignoram serialização, permitir CORS, ou qualquer fuga do padrão que resolve um problema pontual), é essencial entender no que essa quebra de padrão implica.

Dito isso, abaixo está uma lista das vulnerabilidades mais frequentes no desenvolvimento web, como elas funcionam e como se proteger.

 

1 – Injection

Injection é uma classe de problemas que envolve, tanto linguística, como ciência da computação e implica na manipulação do comportamento de um sistema através do seu input. Esse input pode ser qualquer tipo de informação que vem de uma fonte externa e potencialmente maliciosa, como por exemplo, cookies, parâmetros de URL, forms, webservices, variáveis de ambiente e todo tipo de dado dinâmico que irá ser enviado a um interpretador.

 

Funções que executam código arbitrário são historicamente inseguras por essa capacidade de manipulação. Utilizar dados não higienizados para executar um comando como por exemplo:

É como oferecer um café, um beijo na testa e uma mesa prontinha com o servidor do seu sistema interno, alguém mal intencionado vai poder fazer qualquer coisa. O que eu mais quero expressar com esse post é que dados externos não devem ser tratados com confiança, e “dados externos” têm um significado extremamente amplo e muitas vezes pouco intuitivo. A ideia de que só forms e parâmetros de URL representam dados manipuláveis é equivocada. Qualquer request pode ser forjado e enviado ao servidor com extrema facilidade, assim como o consumo de APIs externas não deve ser tratado como seguro. Basicamente, tudo que vem de fora do seu sistema deve ser tratado com muito cuidado, especialmente quando esse input externo é utilizado para manipular comandos enviados a interpretadores.

 

1.1 – SQL Injection

SQL injection é o caso mais frequente de manipulação de interpretadores. Quando um form é enviado ao seu servidor, uma query dinâmica precisa ser criada e a pessoa que enviou o form controla parte dessa query que vai ser usada pelo seu interpretador SQL; basicamente nitroglicerina com um aviso de “mexa antes de beber”. Apesar das ferramentas de desenvolvimento modernas mitigarem bastante o risco de SQL injection, é importante entender como ela funciona, esse entendimento evita que soluções rápidas, porém perigosas, sejam implementadas sem um senso crítico.

Vamos supor que em um site hipotético exista a seguinte URL:

Essa página recebe um ID que é então usado para executar uma query dinâmica como:

Onde ? é o input do usuário. O banco retorna os dados e o sistema exibe o perfil de ID=9. Caso o sistema envie esses dados ao interpretador SQL sem nenhum tipo de higienização ou filtragem, alguém com más intenções pode manipular o sistema interno de diversas formas, como por exemplo acessar a seguinte URL:

O que se traduz em “traga o usuário de id = ‘’, ou true”, e permite que os dados de todos usuários na tabela “users” sejam visualizados (na verdade o banco vai retornar todos os dados mas a página decide como esses dados vão renderizar, dependendo do resultado, o atacante vai precisar ser um pouco mais criativo antes de conseguir realmente acessar as informações). Basicamente, nesse momento essa pessoa mal intencionada tem uma porta de acesso ao seu servidor SQL e pode fazer o que quiser, incluindo deletar ou manipular todos os dados como este quadrinho do XKCD exemplifica:  

 

 

Vale notar que a maioria das stacks modernas de desenvolvimento tem algum tratamento de dados e, caso você não fuja do padrão oferecido pelas ferramentas que usa, boa parte dessas preocupações já vão ser tratadas de fábrica. Em Rails, por exemplo, você já tem essa barreira entre o pedido por informações e o interpretador e dificilmente vai precisar escrever SQL puro. Em PHP também existem ferramentas que são responsáveis pela higienização de input, como PDO, MySQLi entre outros. O ponto aqui é que o desenvolvimento moderno de sistemas já se preocupa com SQL injections, assim como todos os carros hoje já vêm com cinto de segurança, ele só precisa ser conscientemente usado.

1.2 – Material de estudo extra

(Inglês) - The science of insecurity, uma explicação didática sobre o uso de linguística e ciência da computação no estudo de injections.

(Inglês) - GraphQL and security, um detalhamento de como GraphQL incentiva (mas não garante) boas práticas no processo de absorção de dados.


Na próxima parte vamos falar sobre problemas com autenticação e priorização de privacidade!