Por que e como desenvolver software visando a segurança? 🔒🗝
A cibersegurança é muito mais do que um tópico de TI. - Stéphane Nappo, Global Head Information Security.
Photo by Micah Williams on Unsplash
A segurança das aplicações web é um fator fundamental para qual qualquer empresa, afinal a falta de segurança pode quebrar empresas inteiras nos dias de hoje. Engenheiros de softwares não devem apenas desenvolver pensando em um software com uma arquitetura limpa e boas práticas de codificação, mas também devem dar muita importância se o código que desenvolvem é seguro. E isso é muitas vezes deixado de lado. Vamos entender a importância da segurança no dia a dia e alguns pontos de atenção no desenvolvimento.
Sem segurança sem confiança!
Segundo o bussines insider, 86% dos executivos de negócios acreditam que as ameaças à segurança cibernética, como segurança de dados fraca, são preocupantes. E por que eles acreditam nisso? A resposta está nas leis de proteção de dados. Multas altas podem afetar significativamente o négocio e também a reputação da empresa. Mas para por ai? Veja as outras consequências que muitas empresas hoje enfrentam por não terem se planejado com antecedência a ataques:
Perda de receita: Para muitos, a consequência mais fatal de uma violação de dados é a perda financeira incorrida. E isso tem ocorrido muito em nossos dias! Uma pesquisa (The Impact of Data Baches on Reputation & Share Value) confirma que, em caso de violação, os consumidores são rápidos em virar as costas, com 65% das vítimas de violação de dados relatando 'perda de confiança' em uma organização que teve seus dados violados. Além disso, 85% provavelmente informam outras pessoas sobre sua experiência negativa, com 33,4% usando as mídias sociais e 20% fazendo um comentário diretamente no site da empresa. Isso vai impactar nos négocios e investimentos que a empresa poderia receber no futuro!
Perda de Propriedade Intelectual: Em alguns casos, os atacantes também terão como alvo designs, estratégias e projetos. Isso significa que se a organização está lançando algum produto novo e está mantendo isso em sigilo, pode ocorrer vazamento desse produto para o público. A perda de propriedade intelectual pode afetar a competitividade do negócio e impactar futuros lucros da empresa. Algumas empresas concorrentes não hesitariam em tirar proveito dessas informações!
Existem outros pontos como perda do valor das ações da empresa e custo de recuperar todo o ambiente afetado por um ataque. Mas para que o artigo não se prolongue muito, destaquei apenas esses dois pontos que são muito importantes e críticos. Para evitar chegar a esse ponto é essencial ter em mente sempre os três pilares da segurança, vamos passar rapidamente por eles no próximo tópico.
Pilares da Segurança
A segurança das informações de clientes, colaboradores ou até mesmo fornecedores tem sido uma das grandes preocupações das empresas nos últimos tempos, semanalmente empresas vem sendo atacadas e tendo seus dados vazados. Para garantir que os dados não sejam comprometidos as empresas devem ter em mente os três pilares da segurança digital: confidencialidade, integridade e disponibilidade, podemos nos referir como sigla CID. Vamos entender rapidamente esses três pilares:
Confidencialidade: Se refere à proteção de informações que não devem ser acessadas por indivíduos não autorizados, ou seja, determinadas informações são confidenciais e só podem ser acessadas por aqueles que possuem autorização para tal. Esse pilar tem como principal objetivo assegurar a proteção dos sistemas de cunho confidencial e sigiloso. Para cumprir com seu objetivo, podemos implementar, logins, senhas, criptografia, biometria, entre outros.
Integridade: Está relacionado à integridade do armazenamento dos dados. Então da mesma forma que as informações são fornecidas pelo usuário, elas devem ser armazenadas, sem qualquer alteração em seu conteúdo. Isso é essencial! Todas as informações devem estar em seu formato original e verdadeiro. Como garantir a integridade? Podemos utilizar dos mecanismos de criptografia, hashing e assinaturas digitais. Outros mecanismos indispensáveis para a manutenção da integridade das informações incluem o uso da definição de permissões para acesso a arquivos por meio de códigos de verificação e senhas, além do uso do backup.
Disponibilidade: Esse pilar diz respeito ao acesso dos dados sempre que este for necessário. Significa a garantia da disponibilidade das informações. Esse pilar está muito associado à parte operacional da organização. Para garantir a disponibilidade da informação é preciso que a empresa tenha uma estrutura adequada e estável. Alguns dos métodos usados para garantir a disponibilidade de dados e aplicativos incluem redundância como servidores, redes, aplicativos e serviços, tolerância a falhas (hardware), patching de software regular e atualizações de sistema, manutenção de backups e cópias de backup e estratégias de recuperação de desastres. Afinal não adianta garantir os dois pilares e não poder disponibilizar os dados corretamente para os usuários!
Entendo esses pontos surge a pergunta. Como podemos desenvolver um sistema que siga regras e padrões visando a segurança? Vamos ver algumas sugestões.
Segurança é prioridade!
A segurança deve ser considerada desde as etapas de planejamento do seu projeto. A segurança começa com os requisitos, por isso é fundamental pensar em quais vulnerabilidades podem surgir em cada etapa do desenvolvimento de software. E isso significa que a segurança deve sempre ser avaliada ao fazer alterações ou adicionar recursos posteriormente. Mas por que?
"Os investidores veem as violações de dados como uma ameaça ao valor material de uma empresa e se sentem desencorajados a investir em um negócio que teve suas informações confidenciais comprometidas. " - Autor desconhecido.
Atualmente empresas que tem seus dados expostos perdem a confiança de seus clientes, afinal ninguém quer ter seus dados expostos, como endereço residencial e outros dados sensíveis. Então como podemos planejar e pensar desde o inicio do ciclo de desenvolvimento do software em segurança?
Uma das sugestões é adotar o ciclo de vida de desenvolvimento de software seguro ou SSDLC. E como ele funciona?
A implementação da SSDLC afeta todas as fases do processo de desenvolvimento de software. Requer uma mentalidade focada na entrega segura, levantando problemas nos requisitos e nas fases de desenvolvimento à medida que são descobertos. Isso é muito mais eficiente — e muito mais barato — do que esperar que esses problemas de segurança se manifestem no aplicativo já em produção. Os processos de ciclo de vida de desenvolvimento de software seguro incorporam a segurança como um componente de cada fase do SSDLC.
Você pode ler mais sobre o SSDLC e entender todas as fases dessa esteira de desenvolvimento seguro.
Conscientização de segurança!
Engenheiros de software precisam saber o que estão enfrentando e como os atacantes agem, pelo menos saber o básico é importante dos ataques comuns no mundo do desenvolvimento de software e como evitá-los. Os desenvolvedores precisam saber quais erros evitar ao escrever código, assim podem evitar cometer esses erros no futuro em outros projetos. A educação e a transferência de conhecimento auxiliam muito!
Revisões de código
Se todos os desenvolvedores revisam os códigos um dos outros isso ajuda muito a evitar que desenvolvedores inexperientes subam códigos com bugs e vulnerabilidades. Assim os desenvolvedores com maior experiência conseguem auxiliar e transmitir conhecimento. É um trabalho em equipe que ajuda muito a evitar erros que poderiam ser notados antes de ir para produção. O mesmo serve para desenvolvedores seniors, receber feedbacks em seu código pode auxiliar sua evolução profissional cada vez mais! Por isso é essencial sempre estar disposto a receber feedbacks.
Use bibliotecas confiáveis!
Sempre devemos usar bibliotecas ou estruturas populares e bem mantidas ao escrever software, pois é menos provável que tenham vulnerabilidades do que as bases de código recém-criadas. É importante que todos verifiquem a reputação de uma biblioteca ou estrutura antes de usá-la extensivamente em seus aplicativos. Podemos utilizar ferramentas on-line que fornecem informações detalhadas sobre a atividade da comunidade de cada projeto, frequência de lançamento e outras métricas, para saber se a lib está sendo mantida e recebendo correções.
Conheça a lista OWASP!
Os engenheiros de software precisam conhecer pelo menos o top 10 vulnerabilidades de software da OWASP. Essas falhas de segurança de aplicativos da Web são os erros mais comuns que as práticas recomendadas de desenvolvimento de software seguro evitam. Além disso é importante que entender como evitar essas vulnerabilidades em suas aplicações web. Não é necessário ser um especialista, mas é importante saber como evitar esses erros comuns ao escrever seu código.
Padrões de codificação seguro!
Existem várias abordagens para criar aplicativos com segurança, como CERT Coding Standards, Common Weakness Enumeration, etc. Mas o OWASP (Open Web Application Security Project) oferece critérios de codificação seguros e meticulosos. Você pode também acessar a lista e ler todos os tópicos em português.
Vamos ver alguns conceitos importantes que os desenvolvedores devem conhecer para realizar uma codificação segura no dia a dia.
Validação de entrada
A validação de entrada é uma técnica de programação que garante que apenas dados formatados corretamente possam entrar em um componente do sistema de software. A entrada é rigorosamente verificada quanto a quaisquer variáveis que levem o software a agir de forma estranha, o que pode causar ameaças como injeção e script entre sites, os já conhecidos XSS e SQL Injection.
A validação de entrada deve sempre ser feita no lado do servidor para segurança. Embora a validação do lado do cliente possa ser útil para fins funcionais, ela pode ser facilmente ignorada. Isso torna a validação do lado do servidor ainda mais fundamental para a segurança. Por exemplo, a validação de JavaScript pode alertar o usuário de que um determinado campo deve consistir em números, mas do lado do servidor deve ocorrer uma validação para se certificar de que está recebendo exatamente aquilo que foi exigido pela regra de negócio. Um exemplo disso é quando precisamos validar um e-mail tanto no frontend e backend. Se fazemos a validação apenas no frontend, isso pode ser facilmente manipulado com ferramentas que nos permitem editar a request, como BurpSuite e Charles Proxy.
Output Encoding
Codificação e escape são técnicas defensivas destinadas a impedir ataques de injeção. A codificação (comumente chamada de “codificação de saída” ou do inglês, Output Encoding) envolve a tradução de caracteres especiais em alguma forma diferente, mas equivalente, que não é mais perigosa no interpretador de destino. Então quando o usuário insere dados, o software deve codificá-los antes da saída. Vários ambientes de codificação, como .NET, frameworks frontend, já incluem codificação de saída integrada.
Autenticação e senhas
A autenticação é o procedimento de confirmação de que uma pessoa, organização ou site é quem se diz ser, para isso muitas vezes utilizamos tokens para nos auxiliar nessas etapas. O uso de senhas é o método mais comum usado para provar a identidade de alguém ao acessar sites, contas de email e o próprio computador. Abaixo segue uma lista de recomendações feita pela OWASP vamos iniciar pelas senhas:
Implementar o monitoramento para identificar ataques contra várias contas de usuário, utilizando a mesma senha.
Implementar hash nas senhas.
Impedir senhas de dicionário. As senhas de dicionário são uma lista das senhas mais comuns. Os crackers podem utilizar esse dicionário para tentar brute force. Eles geralmente passam por estes primeiro. Aqui está uma lista das 100.000 senhas mais comuns - use isso como referência e verifique o arquivo.
Evite que o usuário tenha senhas repetidas. Isso pode parecer um recurso indesejado para o usuário final, mas diminui as chances de que se atualize a conta com uma senha que já foi utiliza dois ou três meses atrás.
As respostas de falha de autenticação não devem indicar qual parte dos dados de autenticação estava incorreta. Por exemplo, em vez de “Nome de usuário inválido” ou “Senha inválida”, apenas use “Nome de usuário e / ou senha inválidos” para ambos. As respostas de erro devem ser verdadeiramente idênticas na exibição e no código-fonte.
Aplicar os requisitos de comprimento de senha estabelecidos por política ou regulamento.
Exigir autenticação para todas as páginas e recursos, exceto aqueles especificamente destinados ao público.
Todas as funções administrativas e de gerenciamento de contas devem ser pelo menos tão seguras quanto o mecanismo de autenticação principal.
Usar a autenticação multifator para contas transacionais altamente confidenciais.
Sempre assine o token com a chave secreta. Após selecionar um algoritmo apropriado, você deve sempre assinar o token antes de enviá-lo.
Faça uso de reivindicações baseadas no tempo. É crucial definir uma vida útil adequada para os tokens JWT, pois é impossível invalidá-los. Por exemplo, um id ou token de acesso não pode ser revogado, pois não está vinculado a nenhuma sessão. Portanto, você deve definir a vida útil do JWT o mais curta possível em segundos ou minutos no máximo. Mas nunca defina em dias ou meses.
Não utilize o JWT para transportar informações sensíveis! Ele é assinado para proteger contra manipulação ou alteração de dados. Mas os dados podem ser facilmente lidos ou decodificados. Portanto, você não pode incluir informações confidenciais, como o registro do usuário ou qualquer identificador, porque os dados não são criptografados.
Criptografia
A criptografia é utilizada para manter a confidencialidade e integridade das informações. Existem duas categorias principais de algoritmos de criptografia:
Chave simétrica: Em algoritmos simétricos, a chave de criptografia é a mesma que a chave de descriptografia, ou a chave de descriptografia pode ser facilmente derivada da chave de criptografia. Em algoritmos simétricos, a chave deve permanecer secreta. Blowfish, AES, RC5 e RC6 são exemplos de criptografia simétrica. Os algoritmos simétricos mais usados são AES-128, AES-192 e AES-256.
Chave assimétrica ou pública: Em algoritmos assimétricos, existem duas chaves: a chave privada e a chave pública. A chave privada deve permanecer secreta, mas a chave pública pode ser exposta para o mundo. O conhecimento da chave pública não pode levar ao cálculo da chave privada. A criptografia assimétrica é mais utilizada nos canais de comunicação do dia a dia, principalmente pela internet. Algoritmos populares de criptografia de chave assimétrica incluem EIGamal, RSA, técnicas de curva elíptica, PKCSe ChaCha20.
Esses dois algoritmos podem ser utilizadas durante a transferência de informações e armazenamento, dependendo das demandas de segurança e dos riscos presentes. É necessário entender os riscos envolvidos em não criptografar informações e quais impactos podem gerar.
Veja algumas dicas de como melhorar a criptografia de seu software:
- A geração de números aleatórios, nomes de arquivos, GUIDs e strings deve usar um gerador de números aleatórios aprovado.
- Estabeleça e utilize uma política e processo para como as chaves criptográficas são gerenciadas.
- As chaves mestras devem ser protegidas contra acesso não autorizado. Existem as soluções em nuvem para isso.
- Evitar a criptografia fraca ou obsoleta: DES, 3DES, RC4, MD5, MD2, SHA-1.
- Evitar tamanhos de chave inseguros. A chave deve ser grande o suficiente para que um ataque de força bruta (possível contra qualquer algoritmo de criptografia) seja inviável - ou seja, levaria muito tempo para executar. Os tamanhos de chave aprovados como seguros para AES são 128, 192 e 512 bits. No caso do RSA, o tamanho da chave recomendado pelo NIST é no mínimo 2048 bits. Para algoritmo de curva elíptica são recomendados 256, 384, 512 bits.
Gerenciamento de sessão
O processo de manipulação segura de várias solicitações de um serviço de um aplicativo da Web de diferentes usuários é conhecido como gerenciamento de sessão.
A seguir estão alguns pontos sobre gerenciamento de sessão das listas de verificação do OWASP:
- Sessões e conexões devem ser totalmente encerradas após o logout.
- Vários logins não devem ser permitidos no mesmo ID de usuário.
- Com base nos riscos e objetivos de negócios, o intervalo de tempo limite de inatividade da sessão deve ser o mais baixo possível. Isso é muito aplicado em sessões para contas bancárias.
- As informações de cookies devem ser criptografadas.
- O ID da sessão deve ser caracteres aleatórios sem significado e não deve conter nenhuma informação útil.
- Gerar novos cookies de sessão – O gerenciamento de sessão segura deve remover ou expirar os cookies de sessão no logout e criar um novo quando eles revisitarem o aplicativo ou site e fornecerem as credenciais de login corretas.
Gerenciamento e upload de arquivos.
A seguir estão algumas das medidas e técnicas fornecidas pelo OWASP:
- Garanta a autenticação ao carregar um arquivo no servidor.
- Os arquivos carregados no servidor devem ser validados verificando os cabeçalhos dos arquivos.
- Os privilégios de execução devem ser desativados nos diretórios onde os arquivos são carregados.
- O caminho absoluto do arquivo nunca deve ser enviado ao cliente.
Como evitar a vulnerabilidade de upload de arquivo:
- Sempre verifique a extensão do arquivo com a distinção entre maiúsculas e minúsculas. Exemplo: .PDf, .XmL, .Sh, php.
- Filtre o conteúdo do arquivo antes de carregá-lo no servidor.
- Não dê permissão executável para o arquivo carregado.
- Sempre armazene o arquivo carregado em um diretório não público.
- Use mensagens de erro simples: Ao exibir erros de upload de arquivo, não inclua caminhos de diretório, definições de configuração do servidor ou outras informações que os invasores possam usar para obter mais acesso aos seus sistemas.
- Verifique os tipos de arquivo: Além de restringir os tipos de arquivo, é importante garantir que nenhum arquivo seja "mascarado" como tipos de arquivo permitidos. Por exemplo, se um invasor renomear um .exe para .docx e sua solução depender inteiramente da extensão do arquivo, ele ignorará sua verificação. Portanto, é importante verificar os tipos de arquivo antes de permitir que sejam carregados.
Erros comuns de programação a serem evitados
Tudo o que lemos acima sobre os padrões de codificação evitam os erros comuns de programação, que poderá conferir na lista abaixo:
- Neutralização imprópria de elementos especiais usados em um comando SQL ('SQL Injection').
- Cópia de buffer sem verificar o tamanho da entrada ('Clássico Buffer Overflow').
- Autenticação ausente para funcionalidades críticas.
- Autorização ausente ou incorreta.
- Criptografia ausente de dados confidenciais.
- Upload irrestrito de arquivo com tipo perigoso.
- Confiança em entradas não confiáveis em uma decisão de segurança.
- Execução com privilégios desnecessários.
- Falsificação de solicitação entre sites (CSRF).
- Download do código sem verificação de integridade.
- Cálculo incorreto do tamanho do buffer.
- Restrição imprópria de tentativas de autenticação excessivas.
- Redirecionamento de URL para Site Não Confiável ('Redirecionamento Aberto').
- String de formato não controlado.
Além disso você pode conferir o top 10 OWASP.
Lembre-se que a lista acima não diz respeito apenas a como escrevemos o código, mas também diz respeito a como planejamos as funcionalidades do software. Se não consideramos em nossos planejamentos os riscos envolvidos nas funcionalidades que precisam ser desenvolvidas, novamente isso pode trazer sérios riscos financeiros! Então quando estiver escrevendo uma funcionalidade no frontend ou backend, pare e pense um pouco se o que está desenvolvendo pode trazer brechas de segurança no sistema e o que você pode fazer para evitar isso!
Conclusão
Vimos ao longo deste artigo que desenvolver software não é uma tarefa fácil. Demanda esforço, estudo, muito planejamento e organização. Criar funcionalidades sem questionar o grau de segurança que devemos envolver no processo de desenvolvimento, pode gerar grandes prejuízos financeiros! Não pense que as vulnerabilidades mais recorrentes nunca irão ocorrer no projeto que você atua. Lembre-se que os atacantes tem tempo, recursos e muitos tem o conhecimento necessário para serem criativos para explorarem brechas em sites, sistemas e apps. Se mantenha atualizado e preparado.
Fico por aqui neste post! Até o próximo!
Referências: