Cibersegurança para desenvolvedores
Observo que muitos desenvolvedores não costumam ter muito interesse em estudar sobre segurança, e dentre os que têm esse interesse não costumam ter um entendimento muito profundo sobre o assunto. São poucos os desenvolvedores que realmente dá para dizer que tem uma boa noção de segurança.
E sem essa noção acabam cometendo vários erros em relação à segurança do projeto. E se com “erros” você pensou que seria somente vulnerabilidades como XSS ou SQL injection… Bem, pensar isso por si só já é um erro.
Download deste artigo como PDF: https://drive.google.com/file/d/1DGDXY8LMGftMTY3Tn1RZpjeZFb1IcAwA/view?usp=sharing
Introdução
Venho observando há um bom tempo que pessoas interessadas em aprender sobre segurança da informação, mais especificamente a parte técnica (cybersec), tendem a cometer os mesmos erros. No começo eu achei que era porque estavam aprendendo do mesmo lugar e, embora em parte isso também esteja certo, na verdade eu me toquei que era mais uma tendência geral mesmo.
Por isso eu me dispus a tentar entender esse problema. E daí surgiu este artigo onde a proposta é apontar alguns erros (“barreiras”) que eu acredito que atrapalham ou até impedem o aprendizado sério de segurança.
Tenha em mente que o artigo vai aumentando de nível técnico a cada barreira, então não se sinta intimidado se chegar em um nível que você considera complexo demais para você hoje. Um passo de cada vez, não é o tipo de coisa que se aprende em poucos meses ou só lendo um artigo.
Nota: esse artigo foi escrito focado em desenvolvedores (como o título sugere), mas creio que possa ser útil mesmo para quem não é um desenvolvedor e esteja interessado em aprender sobre segurança da informação.
Barreira 1: não entende o que é segurança
Quando se fala de segurança da informação muita gente tem uma visão errada de que se trata de uma dicotomia, algo como: “ou esse sistema é seguro ou não é”. Mas não é bem assim, segurança é mais como um espectro do que como uma chave de “liga ou desliga”. Envolve muitos pontos e muitos níveis, e todas as tecnologias também têm suas preocupações de segurança individualmente.
Para facilitar o entendimento: imagine que você desenvolveu uma aplicação web com um backend Java usando Spring e um frontend usando TypeScript e React. Você pode pensar que “segurança” seria uma coisa só, uniforme e “mágica” nesta aplicação web. Mas todas as tecnologias necessárias para essa aplicação existir têm individualmente suas próprias preocupações de segurança:
- A equipe que mantém a linguagem Java tem suas preocupações de segurança
- A equipe que desenvolve o compilador do Java também
- A equipe que desenvolve o JRE e a JVM também
- A equipe que desenvolve o Spring também
- As equipes que mantém cada uma das outras dependências do projeto também
- A equipe do React também
- A equipe do TypeScript também
- A equipe do JavaScript também
- A equipe da engine de JavaScript também
- A equipe do navegador também
- A equipe que configura o servidor Linux onde o backend roda também
- A equipe que mantém o nginx usado no projeto como reverse proxy também
- As equipes que mantém o Linux, seus serviços e seus drivers também
- A equipe que mantém o processador também
- A equipe que mantém a rede do projeto no cloud provider também
- As equipes que mantém o cloud provider também
- A equipe que gerencia o datacenter também
- As equipes que projetaram os protocolos de redes também
- As equipes que desenham e fabricam os hardwares também
- etc.
Portanto, lhe parece para você que se você escreve seu código Java evitando um SQL injection e XSS isso vai fazer com que sua aplicação web esteja absolutamente “segura”? Bem, para mim não parece.
Por isso que quando se fala de segurança não é algo absoluto como “vou fazer esse sistema X de forma que ele seja seguro”, mas sim algo relativo. Pois o objetivo da segurança da informação não é alcançar uma “segurança absoluta” mas sim reduzir e/ou dificultar possíveis ataques que um sistema possa enfrentar.
Ou seja, o objetivo é tornar relativamente mais seguro e não absolutamente seguro. Pois não é possível fazer um sistema absolutamente seguro. Se você parar pra pensar verá que não existe uma maneira palpável de provar que um sistema é “inviolável”, por isso se alguém ver um sistema/tecnologia como “absolutamente seguro” não passa de uma opinião e não algo que pode ser provado.
E considerando que segurança é relativa, então é tecnicamente válido dizer que uma tecnologia X é mais segura do que uma tecnologia Y (incluindo linguagens de programação) se a tecnologia X tem um menor número de ataques que pode sofrer e/ou os ataques são tecnicamente mais complexos. Assim diminuindo o número de ameaças que conseguiriam fazer um ataque bem-sucedido. Quanto menor esse número, mais segura a tecnologia é.
E esse é o objetivo de estudar a segurança da informação: ser capaz de tornar sistemas/tecnologias mais seguras do que são atualmente (o “como” será discutido ao longo do artigo).
Portanto eu não concordo com a visão de quem diz que toda tecnologia “bem feita” tem um nível equivalente de segurança e que não faz diferença significativa de uma para outra. Faz sim se você levar em consideração que segurança não é uma coisa só e dicotômica, e imagino que você irá concordar com isso até o final do artigo.
Barreira 2: não sabe como os ataques serão feitos
A segunda barreira que atrapalha o entendimento de uma pessoa sobre segurança da informação é o fato dela não ter uma compreensão clara de como os ataques serão feitos ao código dela. Com isso, tentar desenvolver um projeto com segurança é como tentar ser goleiro usando uma venda… Não vai dar muito certo.
É importante para evitar falhas de segurança saber como as falhas de segurança são exploradas. Vejo muitos erros serem cometidos por desenvolvedores por não terem noção nenhuma de como ataques são feitos aos softwares que eles desenvolvem.
Por isso, para ser capaz de impedir e/ou identificar falhas de segurança é importante ter uma compreensão bem clara de como os ataques serão feitos ao software que você desenvolve.
Se você for um desenvolvedor WEB, aprenda a atacar aplicações WEB. Estude sobre vulnerabilidades em aplicações, faça laboratórios e pratique a exploração de vulnerabilidades em aplicações WEB. Veja projetos como o OWASP Top Ten e OWASP API Security Top 10 para começar.
Algumas recomendações de plataformas onde você poderá praticar:
Se você desenvolve com linguagens de sistemas como C ou C++ (para desktop, embarcados, drivers etc.), aprenda sobre engenharia reversa e exploração de binários. Pratique fazer engenharia reversa em desafios de crackme (e softwares reais) e pratique a exploração de vulnerabilidades também. Sobre exploração de binários eu já escrevi um artigo sobre isso: Como aprender exploração de binários e desenvolvimento de exploits
Se for um desenvolvedor mobile, estude sobre engenharia reversa de aplicações mobile (para Android/iOS) e sobre ataques para este tipo de aplicação. E por aí vai…
Isso é muito importante porque não dá para se defender de algo que você não entende, não dá para evitar problemas de segurança que você nem sequer sabe que existem. Estudar sobre e realmente ser capaz de identificar e explorar falhas de segurança é essencial, do contrário você nem sequer sabe o que você está tentando evitar.
E sem entender isso é bem comum também cair no erro da segurança por obscuridade, que de forma resumida é basicamente o pensamento de: “se ninguém sabe o que é ou como funciona não pode explorar, logo é seguro.”
Que é quando o desenvolvedor acredita que ocultar informações sobre seu sistema vai torná-lo mais seguro, como:
- Achar que código compilado (e/ou ofuscado) e closed-source é mais seguro que um código open-source
- Achar que criar seu próprio algoritmo de encriptação de dados é mais seguro que usar um algoritmo conhecido, como AES ou Twofish.
- Achar que criar uma “tela secreta” ou “endpoint secreto” seja suficiente para impedir o acesso não autorizado.
- etc.
Ao estudar como os ataques são feitos ao tipo de software que você desenvolve, você começará a entender aos poucos porque essa ideia está errada. Mas se ainda não estiver convencido disso, pense no seguinte:
Digamos que um desenvolvedor X trabalhe numa empresa. Certo dia o chefe dele o demite de maneira que ele considera injusta e remove os acesso do desenvolvedor X. Com base somente nas informações que X sabe sobre como o código do projeto funciona e como foi configurado no servidor, ele seria capaz de comprometer a segurança do projeto?
Se sim, há um problema de segurança muito grave neste projeto. Porque este não deveria ser o caso…
Então quando for pensar na segurança do projeto, pense que você precisa se proteger de ameaças internas também, como: (ex-)funcionários, freelancers e/ou terceiros que possam ter acesso ao projeto temporariamente.
Mesmo em projetos que você esteja trabalhando sozinho, é importante também pensar desta forma. Pois informações sobre como um sistema funciona vazam ou podem ser deduzidas, não caia na armadilha de achar que é “impossível” de isso acontecer.
CTF não é segurança
Capture The Flag (CTF) são desafios (ou competições com desafios) relacionados à segurança da informação. Por mais que eu tenha recomendado algumas plataformas de CTF, vale deixar um aviso: CTF não é segurança.
Você não vai aprender sobre segurança da informação somente jogando CTF. Você pode praticar identificar e explorar algumas vulnerabilidades específicas, mas é só isso. A noção sobre segurança de quem só joga CTF é praticamente a mesma de um desenvolvedor que não entende nada de segurança mas estudou sobre as vulnerabilidades mais comuns.
Não estou dizendo que você deve “evitar” CTF ou coisa do tipo, mas é importante estudar sobre segurança de verdade e não somente ficar jogando CTF o dia todo. Tem muita gente que acha divertido jogar CTF e acaba esquecendo de estudar. Por isso, lembre-se: CTF é CTF, segurança é segurança.
Barreira 3: acredita que falhas de segurança são óbvias
Talvez você já tenha visto isso: uma pessoa querendo iniciar na área de desenvolvimento que aprende o básico do básico sobre uma linguagem de programação, o básico do básico sobre uma biblioteca/framework, faz um “clone do Twitter” ou “Pokedéx” e acredita que já é um desenvolvedor júnior plenamente apto para trabalhar na área.
Esse é um pensamento comum entre a galera que começou a aprender sobre desenvolvendo: achar que é fácil, achar que saber “só um pouco” é o suficiente. E esse pensamento também ocorre quando a pessoa começa a aprender sobre segurança.
Isso prejudica bastante o aprendizado sobre segurança da informação: quando a pessoa começa a acreditar que falhas de segurança são óbvias e/ou que ela não precisa aprender mais nada sobre segurança.
Isso muitas vezes acontece depois da pessoa começar a estudar sobre segurança, aprender sobre algumas vulnerabilidades mais básicas e conhecidas e achar que isso é tudo o que ela tinha para aprender. Muitas vezes porque a pessoa fica jogando CTF ou faz laboratórios (ambientes simulando uma aplicação vulnerável) para iniciantes, ela começa a acreditar que falhas de segurança na vida real vão ser fáceis de identificar e óbvias assim como ela viu naqueles projetos propositalmente vulneráveis.
Ou talvez pela pessoa ler sobre vulnerabilidades comuns em projetos como OWASP top ten, livros ou artigos, e começar a acreditar que toda vulnerabilidade vai ser simples e óbvia como as dos exemplos que ela leu. A ponto de ela acreditar que quando ela passar o olho por um código com uma falha de segurança ela vai automaticamente saber que tem uma falha ali.
Infelizmente o mundo real não é cor-de-rosa, se fosse fácil assim esse problema (segurança cibernética) já teria sido resolvido há muito tempo. E pelo contrário: a cibersegurança está ficando constantemente mais complexa e constantemente mais importante.
Segurança parece complexo para você? Que bom, porque é mesmo. Como eu gosto de dizer: se está fácil é porque você está aprendendo errado. Se a segurança da informação está começando a soar difícil e complexo na sua cabeça é um bom sinal, significa que você está pronto para começar a aprender.
Se por outro lado você acredita que segurança é fácil e/ou acha que problemas de segurança só existem em projetos onde os programadores são “burros”, “incompetentes” ou “preguiçosos”… Então espero que mude sua mentalidade até o final do artigo.
Sua intuição está errada
Uma coisa que eu reparei depois de alguns anos desde que comecei a estudar sobre segurança, é que a intuição de muitas pessoas (eu incluso) em relação ao tema é muito errada. Não tenho dados para generalizar que isso acontece com todo mundo, mas é possível que sim.
Então eu lhe dou uma dica: não confie na sua intuição sobre o assunto, não acredite em coisas relacionadas à segurança. Busque por evidências, procure entender fatos e não somente ter achismos sobre o assunto.
É uma dica rápida mas que faz muita diferença. E só para lhe servir de referência vou listar algumas intuições que eu tinha (e talvez você também tenha) e depois de alguns anos percebi que eu estava errado:
- Eu achava que projetos com problemas de segurança só existiam porque os programadores eram idiotas e não sabiam o que estavam fazendo…
- Eu achava que não existiam linguagens mais seguras do que outras, que era tudo exclusivamente “culpa do programador” se o código na linguagem X era inseguro…
- Eu achava que proteções de segurança presentes em frameworks, bibliotecas e/ou linguagens de programação eram frescuras e que se o programador fosse bom ele não precisaria de nada disso…
- Eu achava que se as pessoas pudessem ver meu código ele seria menos seguro. Logo projetos open source como o Linux ou FreeBSD seriam menos seguros do que projetos de código fechado como o Windows…
- Eu achava que só gente leiga/idiota poderia ser infectado por um malware e/ou ter seu computador invadido…
- etc.
Dentre outros erros que eu cometi se deixando levar por intuições sem embasamento e sem evidências.
Existem vulnerabilidades complexas
Materiais educativos introdutórios à segurança ofensiva (que é geralmente só isso que veem quando pesquisam por “segurança” no Google) muitas vezes vão apresentar exemplos de vulnerabilidades e até ter laboratórios e CTFs com essas vulnerabilidades.
Só que esses códigos são propositalmente vulneráveis e isso faz com que eles sejam relativamente simples. Além de que geralmente, em conteúdo para iniciantes, se costuma só exibir vulnerabilidades cuja complexidade técnica é baixa para explorá-las.
E isso faz com que a pessoa comece a enviesar seu pensamento para achar que vulnerabilidades em projetos reais também são assim. Embora muitas sejam mesmo, principalmente quando o programador daquele sistema tem uma competência baixa em segurança.
Só que isso não significa que só existem vulnerabilidades óbvias/fáceis nem significa que os únicos projetos que têm vulnerabilidades são os tocados por programadores com baixa competência em segurança.
E como eu já disse: segurança não é uma dicotomia, é mais como um espectro. Então existem sistemas/tecnologias mais seguros do que outros, existem vulnerabilidades mais complexas de explorar do que outras e/ou tecnicamente mais difíceis de serem identificadas.
Programadores competentes não vão cometer erros óbvios, mas isso não significa que não vão cometer erro nenhum. Uma dica que posso lhe dar para que você entenda isso de uma vez por todas é tomar um “choque de realidade”. Tente estudar o código de exploits para vulnerabilidades em projetos como o Linux, Chrome ou Firefox.
Quando você ver o quão complexo é explorar vulnerabilidades nesses projetos e o quão “sutis” são as vulnerabilidades, você entenderá que existe muito mais do que apenas o óbvio.
Sugestão de leitura: https://retr0.zip/blog/abusing-Liftoff-assembly-and-efficiently-escaping-from-sbx.html
Muitas vezes pode ocorrer de você não entender alguma coisa e acabar não dando a importância devida ou achar que “não existe” por causa disso. Por exemplo: é possível você estudar um executável binário, gerado por um compilador, para entender como ele funciona. Isso é chamado de engenharia reversa de software.
Mas já vi muita gente que não entendia isso e achava que um software, por ser compilado, seria “mais seguro” já que supostamente ninguém conseguiria entender o código dele. E já vi casos de, por exemplo, a pessoa fazer uma conexão com SGBD salvando as credenciais do SGBD dentro do executável. É fácil obter essas credenciais dentro do executável, mas tem gente que não entende isso.
Então eu lhe dou um conselho: só porque você não consegue entender alguma coisa não significa que não seja importante, não exista ou não seja possível. Tem muita gente no mundo que sabe o que você não sabe e/ou é capaz de fazer coisas que você não é.
Sim, você precisa se preocupar com vulnerabilidades complexas
Muita gente cai na armadilha de pensar: “ah, eu só preciso me preocupar com as vulnerabilidades mais básicas que eu consigo entender. Essas complexas só um gênio consegue encontrar e não tem nada que eu possa fazer”
Isso não está certo, há muito que você pode fazer mesmo não sendo “um gênio”. E como eu falei: não é uma dicotomia. Não existem só vulnerabilidades “muito óbvias” ou “muito complexas”.
Existe toda uma gama de níveis de complexidade para se encontrar e explorar uma vulnerabilidade. Entender isso é necessário para, justamente, reduzir o número de vulnerabilidades menos complexas que possam ser exploradas.
Lembre-se: seu objetivo é diminuir o número de ataques possíveis e/ou dificultar os ataques. Fazer as vulnerabilidades serem complexas de se achar/explorar é seu objetivo e reduzir o número delas também.
Como fazer isso eu falarei sobre na “barreira 6”.
Código não é tudo
Outro ponto que faz as pessoas acharem que “falhas de segurança são óbvias” é acreditarem que vulnerabilidades no código é tudo o que elas precisam se preocupar em relação à segurança… Ledo engano. Falhas de segurança não são apenas SQLi, XSS, SSTI, SSRF, IDOR ou qualquer outra sigla que você possa ter visto na internet.
...
Barreira 4: não entende como as coisas funcionam
...
Barreira 5: não tem pensamento crítico e/ou analítico
...
Barreira 6: não tem estratégia e planejamento
...
O ARTIGO NÃO ACABOU! Mas infelizmente o TabNews tem um limite de 20 mil caracteres por publicação e o artigo completo tem quase 45 mil. Mas caso queira ler o artigo completo pode fazer isso no meu blog ou ler a versão em PDF. Escolha o que achar melhor:
- Blog: https://blog.freedev.com.br/ciberseguran%C3%A7a-para-desenvolvedores-a37385cf5d23
- PDF: https://drive.google.com/file/d/1DGDXY8LMGftMTY3Tn1RZpjeZFb1IcAwA/view?usp=sharing
Até mais! 😄