Alura > Cursos de DevOps > Cursos de Segurança > Conteúdos de Segurança > Primeiras aulas do curso OWASP: padrão de verificação de segurança de aplicações V5 a V8

OWASP: padrão de verificação de segurança de aplicações V5 a V8

Validation, Sanitization and Enconding Verification Requirements - Introdução

Boas-vindas à segunda parte do curso de Padrão de Verificação de Segurança de uma Aplicação, conforme o relatório da OWASP. Eu sou o Guilherme Silveira e serei seu instrutor. A OWASP nos fornece esse padrão de verificação e temos um checklist, um guia, uma métrica e diversas formas de utilizar este relatório. Abordaremos uma série de pontos em relação a essas informações, esse checklist e esse padrão de verificação.

Nós já conversamos sobre alguns deles e nós vamos, posteriormente, não só falar sobre a verificação de autenticação, mas também sobre gerenciamento de exceção e sobre o controle de acesso. Assuntos que nós já falamos, vamos falar sobre sanitização, validação e o encoding de saída de dados de acordo com o contexto, para evitarmos diversos dos tipos de ataque de injeção.

Falar sobre criptografia de dados armazenados, sobre o tratamento de erro e requerimentos de “logging”. Como tratar com “logging” e quais são os problemas - porque é importante lidarmos com a segurança do “log” - e finalmente falaremos sobre os requerimentos ligados à proteção dos dados em si. Lembrando que essa última sessão também vai ter restrições segundo as leis de onde a sua empresa está estabelecida ou de onde ela vai ser aplicada.

Então, conforme o país ou regulamentações locais que podem ser, por exemplo, no Brasil, a lei geral de proteção de dados, onde temos curso específico falando sobre isso. Aqui nós vamos falar sempre na abordagem do relatório do OWASP, que vai ter diversos requerimentos. Nós vamos falar sobre os requerimentos do OWASP e de todos esses pontos. Vamos lá?

Validation, Sanitization and Enconding Verification Requirements - Validation Sanitization and Encoding Verification Requirements

Vamos começar com a quinta seção de verificação. A parte que vai falar de validação, sanitização e “encoding”. Requerimentos ligados à verificação desses três pontos. Qual é o objetivo dos controles que vamos ver? Eles vão estar muito ligados com os ataques em que os usuários entram com dados, ataques ligados com Injection ou algo do gênero. Esses dados são interpretados por nós e de alguma forma devolvidos para o cliente.

Então, o cliente entra com um SQL Injection, entra com um Shell Injection, faz um Cross-Site scripting, isso é, ele faz um Injection que nós devolvemos para outros usuários, por exemplo, ou algo do gênero. Então tem várias maneiras em que os usuários finais atacantes podem tentar injetar e colocar dados que nós precisamos de alguma maneira validar, sanitizar ou até mesmo tomar cuidado com o “encoding” na hora de ler ou na hora de devolver o nosso resultado. Essa é a linha geral.

A linha geral está aqui e é muito ligada com Injection e com tudo que apareceu de Injection nos dois cursos iniciais de OWASP ou nos cursos de verificação de padrão de verificação. Tem três linhas gerais que passam por pontos e problemas que nós já discutimos, a validação de toda a entrada e um “encoding” da saída que tem que ter uma arquitetura que previna injeções. Então de preferência já usar API's e usar ferramentas que previnam esse tipo de problema. O que mais?

Que os dados de entrada são tipados fortemente. Isto é, se eu estou recebendo um número de cartão de crédito, ele tem que ter um número específico de dígitos e são dígitos, não são letras etc. Você valida, isto é, um número de cartão de crédito tem regra de validação? Valide! CPF tem regra de validação? Valide! Os números que são válidos, o Range, se, por exemplo, um valor que eu vou debitar de uma conta tem que ser um valor positivo, não pode ser um valor negativo.

Ou até mesmo o tamanho. Se o número de cartão de crédito tem 4, 8, 12 ou 16 dígitos, então são 16 dígitos, não vou aceitar 15 e não vou aceitar 17. Tem ataque em todos esses tipos de situações. Tem todos esses tipos com ataques. No pior dos casos, o mínimo que nós vamos fazer é sanitizar ou filtrar os dados. E na saída? Na saída nós vamos querer usar um “encoding” ou escapar de alguma maneira. Nós vamos escapar caracteres ou encodar eles de alguma maneira, segundo o contexto dos dados que nós estamos colocando.

Então nós vamos querer, por exemplo, se nós estamos devolvendo um HTML que é baseado em dados que os usuários entraram, nós vamos querer escapar, nós vamos encodar de uma maneira que isso seja escapado e que nós não coloquemos coisas que podem ser interpretadas pelo navegador. Provavelmente não é esse o seu objetivo na aplicação. Então ele cita aqui que hoje em dia nas aplicações modernas isso é mais importante ainda.

Por que é mais importante? Porque existem situações onde é difícil validarmos entrada. Então a saída, encodar a saída para o HTML limpo ou encodar a saída para o HTML onde escaparam caracteres não seguros, é muito importante. Por exemplo: o HTML ou para querys parametrizadas em SQL, em Hibernate, em HQL, em NoSQL, ou o que estivermos utilizando.

Frameworks com “auto-escaping”, tudo isso é importante, por quê? Porque hoje em dia o input ficou mais difícil de nós validarmos em certas situações. Então se nós garantirmos que todo o output foi escapado e foi encodado, nós teremos menos preocupação no input. De qualquer forma, reforçando: nossas preocupações aqui serão tanto com input, quanto com output.

Validation, Sanitization and Enconding Verification Requirements - Input Validation Requirements

Então vamos começar agora com os requerimentos de validação de entrada. Lembrando que os requerimentos de validação de entrada foram discutidos anteriormente, nos cursos do OWASP 1 e 2 e eles realmente protegem muita coisa.

Primeiro, o procedimento de validar a entrada está ligado com diversos processos. Durante o desenvolvimento do código nós estamos atentos a esse tipo de coisa. Em geral, não a tudo, mas, em geral, à entrada e à validação dela.

Durante a criação de teste de unidade, de teste de integração, durante o design, os prints de design do nosso projeto ou até mesmo a definição da arquitetura do projeto, nós estamos atentos aos requerimentos de validação de entrada, à validação da entrada.

Aqui é a definição ele fez em unitário, teste de unidade e integração, mas não importa muito qual o tipo de classificação conceitual você está utilizando para testes. O que importa é que tem muitas fases onde nós estamos atentos a esse tipo de coisa, mas não necessariamente à todas as questões de segurança ligadas à validação.

Aqui, em geral, nós estamos atentos às regras de negócio, não necessariamente de segurança. Mas o que ele diz é que, “uma lista positiva”. Lembrando: o que é uma lista positiva? É aquela lista que fala o que pode ser aceito como valor.

Então uma lista positiva e dados fortes, um tipo de dado forte, nós temos inteiros, temos “floats”, temos que cada um só é aceito no momento adequado e que isso pode eliminar 90% dos ataques de injeção. Eu suponho que são esses 90%. É um número muito redondo. Se é muito redondo, é um que veio da nossa imaginação. Duvido muito que tenha sido da estatística exata.

Os relatórios deles são através de pesquisas, mas um número tão redondo como 90%, não deve ser o número redondo, de 90%. O que ele está querendo passar de mensagem é que a maior parte dos ataques podem ser defendidos através de uma lista positiva e com certeza isso é verdade. Eu não pegaria tanto no pé do 90%. Quer dizer, eu não pegaria no pé do 90%, eu não ficaria batendo 90% para tudo que é lado, dizendo que é 90%. O tamanho dos seus dados.

Então se você está esperando um número de cartão de crédito, são 16 dígitos, não são 352. Por que não 352 dígitos? Porque, vai saber o que acontece com o seu sistema se chegar um número de cartão de 352 dígitos! Talvez nada, talvez algo, talvez estoure a memória e execute um pedaço de código que não era para ser executado e por aí vai. Então são outras quebras de segurança que acontecem com o tamanho dos dados que são enviados. Além do tamanho, o espaço de valores.

Então se você está aceitando uma transferência bancária, o valor tem que ser estritamente positivo, é acima de zero. Ele é acima de zero, não pode ser zero e não pode ser negativo. Então isso diminui mais ainda os ataques e os riscos que você está correndo. Bate nessa primeira tecla de listas positivas e tipagem forte na entrada dos dados. Não necessariamente no seu código e em todo o resto, aí tem outras discussões. Tamanhos e os valores aceitáveis, “range” de valores aceitáveis.

Apesar de nem tudo isso ser encontrado em testes de penetração tradicionais, eles costumam ser encontrados na parte da saída, na hora que você faz um Injection. Injection na hora de sair os dados, podem ser encontrados lá. Então é nos recomendado olharmos isso daqui, porque tudo isso é muito básico e muito importante, por isso “L1”. Para saber que tudo que está aqui, é “L1”. Vamos lá! Primeiro caso: verificar que a aplicação tem defesas para táxis de poluição de parâmetros HTTP.

O que é poluição de parâmetros HTTP? Primeiro pense em uma requisição HTTP. Se você nunca viu uma requisição HTTP por trás dos panos, com certeza é a hora de ver. É pré-requisitos dos cursos saber e entender o protocolo.

Uma requisição HTTP possui os métodos, os verbos que nós utilizamos, o “GET”, o “POST”, o “delete”, o “update” e por aí vai. No navegador por padrão, requisições “GET” e “POST”. No HTTP “GET” e “POST” costumam serem os mais utilizados, até por causa dos navegadores e contexto histórico.

Depois tem os cookies, tem os cabeçalhos do HTTP. Onde estão os cookies? E tem as variáveis de ambiente do seu sistema operacional e às vezes até as variáveis de configuração do seu framer ou do seu servidor e por aí vai. Então temos várias camadas de parâmetros. Parâmetros do sistema operacional, parâmetros da biblioteca, parâmetros do framework, parâmetros do cabeçalho HTTP, parâmetros do cookie dentro do cabeçalho HTTP, parâmetros do “GET” ou do “POST” dentro da requisição HTTP.

Temos vários níveis de parâmetros, dos mais genéricos aos mais específicos a essa requisição. E tem os frameworks, que não fazem distinção em relação a isso, que quando você fala: “me dê um parâmetro IP do servidor”, ele vai procurar esse IP do servidor daqui para lá, em tudo isso ou talvez em mais lugares ainda.

Isso é, se está em uma variável de ambiente, que é onde você esperava encontrar, mas se alguém passar esse parâmetro na sua requisição “GET” vai ser “durante o escopo da requisição dentro do framework, vai sobrescrever aquele escopo de parâmetro de ambiente”. Conseguir fazer algo que você não queria fazer.

Então um ataque de poluição HTTP e de parâmetro, significa manipular os parâmetros HTTP, porque a semântica desses parâmetros e desses tipos de comportamentos não é definida pelo protocolo em si. Então eles podem mudar os parâmetros e colocar valores nos cookies, nos cabeçalhos, tentando extrapolar e descobrir o que vai acontecer.

Aqui ele dá um “GET”, por exemplo, com dois parâmetros. Depois ele tem o “Host” comum no cabeçalho do HTTP e o “User agent” como cabeçalho do HTTP e o “Accept” como cabeçalho HTTP.

Aqui ele deu um exemplo de um “POST” para a mesma página. Não, ele mudou um pouco, aqui é “jsp” e aqui é “asp”. Com o protocolo HTTP 1.1, com o “Host”, que é um cabeçalho, com o “User agent”, que é outro cabeçalho, o “Accept”, que é outro cabeçalho, “Content-Type”, que é outro cabeçalho, “Content-Length”, que é outro cabeçalho e aí os parâmetros no “body”. Então é outra maneira de passar parâmetros. Duas maneiras diferentes de passar parâmetros. Em uma ele usou “jsp” e no outro “asp”.

Mas tem várias maneiras de como isso é parseado. Isso deveria ter parseado como? Ele dá um exemplo: se você passar o mesmo parâmetro “part1=val1,val2”, como isso acontece? Como é interpretado? Se eu passar o mesmo parâmetro duas vezes, como isso é interpretado no servidor? Se eu passar no “GET” o mesmo parâmetro duas vezes, como isso é interpretado no servidor ou no framework?

Tudo isso são questões que não são do protocolo HTTP e tudo isso abre brecha para um ataque. Tome cuidado! Tenha certeza e tenha controle de que o framework ou a biblioteca e o seu código está utilizando o parâmetro de onde eles querem utilizar, do escopo que eles querem utilizar.

Segundo ponto: verificar que os frameworks se protegem contra a “assigment”, a atribuição de parâmetros em massa e que têm medidas para se protegerem de atribuir valores em seguros, como marcar campos privados ou similares. Significa o quê?

Você não quer que o seu framework, por padrão, saia atribuindo qualquer valor em qualquer coisa, porque se você permite qualquer valor em qualquer coisa – “?meuValor=xpto” - isso seta qualquer valor. Se ele descobre que o seu “user.name=xpto” está assim, ele tenta o quê? O “&user.admin=true” e vê se funciona ou não. A primeira coisa que ele tenta ou algo similar, ou “user.admin” ou “user.setadmin”. Eu sei que parece não fazer sentido, parece, mas vamos testar.

E vai explorando, vai tentando ver o que acontece nos parâmetros. Então nós queremos evitar ataques de atribuição de parâmetros em massa ou em valores em seguros. Em geral, o mínimo que você quer é se os campos são privados, isso é uma lista que não deve ser alterada, você só quer que seja alterado os campos públicos. Essa seria de novo uma lista positiva.

A lista positiva são os campos públicos. Porém, se você parar para pensar, não necessariamente, porque os campos públicos de uma orientação a objetos ou de estrutura, podem ser públicos por outros motivos e não por causa do framework ou biblioteca. O framework ou a biblioteca estão assumindo algo que não necessariamente é verdade. Por mais que seja uma convenção interessante e que facilite escrever o código, ela é insegura.

Então talvez nós não queiramos isso, nós queiramos sim colocar uma lista positiva. A lista positiva que nós discutimos resolve basicamente esses dois problemas. Ela vai te dizer quais são os parâmetros que são aceitos e de onde são lidos esses parâmetros. Essa é a lista positiva nas duas dimensões diferentes. O que mais? Verificar que todo input, toda entrada - isso é, campos HTML, requisições “rest”. Não importa como é a requisição, aqui é “rest”, tudo é moda.

“Rest” não é só moda, mas não importa de onde é a requisição. Parâmetros da URL, cabeçalhos HTTP, cookies, arquivos enviados, arquivos de Batch, feeds de RSS, qualquer lugar. Tudo é validado usando uma lista de validação positiva. Sempre a lista de validação positiva, e não uma lista de validação negativa. Por quê? Porque a lista de validação negativa, o que ela nos faz? Quando nós temos um valor novo, um campo novo ou algo novo, por padrão, ela está liberada.

Então se a pessoa que criou esse campo novo, esse espaço novo, e não estiver atenta a essa questão, ela vai abrir uma brecha de segurança. Por padrão, lembra anteriormente? Nós discutimos que o padrão é sempre tudo fechado, então nós queremos que o padrão seja uma lista positiva, e não uma lista negativa. Verificar se os dados estruturados são tipados fortemente e validados contra a definição do esquema. Se é para receber só número, é só número! É só dígito? É só dígito!

O tamanho é “tal”. São 16 dígitos? São 16 dígitos! O CPF é para ter ponto e hífen? É para ter ponto e hífen ou não é para ter ponto e hífen? Não é para ter ponto e hífen! Confira aquilo que você tem que confirmar. Então confirme o esquema de diversas formas, seja o tipo, seja os caracteres válidos, o tamanho e o padrão, tudo isso você vai validar na entrada e o que você não se preocupa, jogue fora, não fique manipulando aquilo que você não precisa, porque é a lista positiva. Lembra?

Você só manipula aquilo que você precisa. O que você vai ignorar, você joga fora e não passa mais para frente. Ou vai validar também. Dois campos relacionados têm uma validação válida que faz sentido, por exemplo: o nome da cidade e o código ZIP code. Então se você tem o seu CEP, o CEP e o nome da cidade estão conectados. Se a pessoa teve que preencher os dois campos, será que faz sentido? Então são dois campos que você tem que dar uma olhada. É um exemplo.

Talvez não seja necessariamente válido para todas as cidades do Brasil, talvez nós tenhamos alguma regra que fuja desse exemplo do ZIP e do postcode, do CEP e do nome da cidade nos Estados Unidos, por exemplo, mas no Brasil não. Não tem problema, mas se você tem dois campos que estão ligados, esses dois campos têm que ser validados juntamente também. Faça a validação cruzada dos campos. Verificar que redirecionamento de URL's e “fowards” somente são feitos para destinos listados.

Listados de forma positiva. Antes ele usa o termo adequado que é o “listagem positiva”, aqui deixaram passar historicamente. Mas destinos positivos, isso é, se você listou em uma lista positiva de você pode redirecionar para esse domínio, tudo bem.

Se não, não redirecione. Por quê? Porque você tem que falar para o usuário: “Eu estou indo para esse outro site que eu não confio, você confirma? Você quer redirecionar para outro site?” Você vai ver e-mails, por exemplo. Serviços de e-mail são muito comuns.

Você clica em um link e ele te fala: “esse link está ‘linkando’ para um site que não é meu, eu não confio. Você quer ir para este site?”. Por quê? Porque a partir de agora pode ser um ataque de “phishing”, pode ser um ataque de qualquer coisa. Isso em um link de um e-mail. Em um link de serviço também. Por quê? Porque quem nos deu esse link foi um usuário. Pode ter sido um administrador, pode não ter sido um administrador, não importa.

Se foi um usuário que nos deu o link e eu vou redirecionar ou fazer um “forwards” para esse link, talvez eu queira dizer: “Você está saindo do nosso site, tem certeza? Tome os seus cuidados. Nós não somos mais responsáveis daqui para frente por isso”. É só para deixar explícito. Não que precise necessariamente, depende da situação, mas com certeza um aviso é positivo. Então aqui é isso que ele pede também.

Porque de novo: de redirecionamento e “forward” de RI podem ser parâmetros enviados pelos usuários e nós temos que estar abertos de novo a um Injection maléfico que vai nos causar algum dano.

E com isso nós fechamos o 5.1, requerimentos de validação na entrada dos dados.

Sobre o curso OWASP: padrão de verificação de segurança de aplicações V5 a V8

O curso OWASP: padrão de verificação de segurança de aplicações V5 a V8 possui 120 minutos de vídeos, em um total de 23 atividades. Gostou? Conheça nossos outros cursos de Segurança em DevOps, ou leia nossos artigos de DevOps.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Segurança acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas