Quanto aos falsos positivos, tudo é simples aqui: você pode pegar e olhar diretamente para os locais no código onde as vulnerabilidades foram descobertas com suspeita de falsos positivos. Na verdade, alguns deles podem ser falsos positivos (embora obviamente não metade do total).
Mas sobre o que é crítico e o que não é, gostaria de falar mais substantivamente. Se você entende por que não é mais possível usar SHA-1 e por que escapar ";", talvez este artigo não lhe abra algo novo. Mas se os resultados da varredura das vulnerabilidades encontradas deslumbram, bem-vindo - nós diremos quais "buracos" são mais frequentemente encontrados em aplicativos móveis e da web, como funcionam, como corrigi-los e, o mais importante - como entender o que está à sua frente - uma falha perigosa ou um pequeno erro no código.

Implementação
Bem, tipo tão comum de vulnerabilidade. Eles estão embutidos em todos os lugares: em consultas SQL, LDAP, XML, XPath, XSLT, Xquery ... Todas essas injeções se distinguem pelo uso de dados não confiáveis, graças aos quais um invasor obtém acesso às informações ou altera o comportamento do aplicativo. Por exemplo, com a entrada do usuário que não é validada o suficiente.
De acordo com a classificação internacional de vulnerabilidades OWASP , os ataques que usam o método de "injeção" são classificados em primeiro lugar no nível de criticidade das ameaças à segurança de aplicativos da web. Vamos considerar os tipos de implementações mais típicos.
Injeção SQL . Dados não confiáveis entram na consulta SQL do banco de dados.

Se a consulta ao banco de dados não implementar a autenticação correta dos dados de entrada, um invasor pode corromper a consulta SQL:
- enviar código malicioso para ele;
- adicione o símbolo "-" ou ";" e encerrar o comando SQL correto: tudo após o "-" é interpretado como um comentário e o caractere ";" marca o fim de um comando;
- adivinhe a senha executando sequencialmente uma série de consultas SQL.
Como se defender? Aqui estão algumas recomendações do OWASP :
- Use uma API que forneça uma interface parametrizada ou ferramentas de mapeamento relacional de objeto (ORM).
- Implemente um mecanismo de validação para dados inseridos pelo usuário. Use uma lista de permissões de validação do lado do servidor.
- Caracteres especiais de escape (";", "-", "/ *", "* /", "'"; a lista exata depende do banco de dados).
- Use procedimentos armazenados em conjunto com um mecanismo de filtragem para seus parâmetros para validar a entrada do usuário.
Injeção de XML . Os aplicativos usam XML para armazenar ou trocar dados, portanto, podem conter informações valiosas.

Se um invasor puder gravar dados em um documento XML, ele poderá alterar sua semântica. Nesse caso, o cenário mais inofensivo permitirá que você injete tags extras no documento e, como resultado, o analisador XML será encerrado com um erro. Mas você pode enfrentar um incidente mais sério: por exemplo, com a substituição dos dados de autenticação na base de clientes ou do preço no banco de dados de produtos da loja. A injeção de XML também pode levar a cross-site scripting (XSS) - a injeção de código malicioso que é executado no navegador do usuário quando a página é aberta.
O que podemos aconselhar?
- Não crie tags e atributos cujos nomes sejam derivados de dados de uma fonte não confiável (por exemplo, inseridos por um usuário).
- Codifique (codificação de entidade XML) os dados inseridos pelo usuário antes de gravá-los em um documento XML.
A injeção de XQuery é uma forma de injeção de SQL clássica, mas, neste caso, o ataque terá como alvo o banco de dados XML e os dados não confiáveis acabarão na expressão XQuery.
No exemplo abaixo, o aplicativo cria e executa uma expressão XQuery com base em parâmetros
username
e a password
partir de uma solicitação HTTP (fonte não confiável):
XQDataSource xqs = new XQDataSource();
XQConnection conn = xqs.getConnection();
String query = "for \$user in doc(users.xml)//user[username='" + request.getParameter("username") + "'and pass='" + request.getParameter("password") + "'] return \$user";
XQPreparedExpression xqpe = conn.prepareExpression(query);
XQResultSequence rs = xqpe.executeQuery();
Se os dados estiverem corretos, a solicitação retornará informações sobre o usuário com o nome e senha apropriados:
for \$user in doc(users.xml)//user[username='test_user' and pass='pass123'] return \$user
Se um invasor especificar uma string contendo caracteres especiais (por exemplo,
admin' or 1=1 or ''='
) como parâmetro , a semântica da solicitação mudará:
//user[username='admin']
A solicitação recebida retornará dados sobre todos os usuários.
Opção segura (usa
prepared statements
):
XQDataSource xqs = new XQDataSource();
XQConnection conn = xqs.getConnection();
String query = "declare variable $username as xs:string external; declare variable $password as xs:string external; for \$user in doc(users.xml)//user[username='$username' and pass='$password'] return \$user";
XQPreparedExpression xqpe = conn.prepareExpression(query);
xqpe.bindString(new QName("username"), request.getParameter("username"), null);
xqpe.bindString(new QName("password"), request.getParameter("password"), null);
XQResultSequence rs = xqpe.executeQuery();
A incorporação em XSLT (XML Document Transformation Language) é possível se o aplicativo usar dados de uma fonte não confiável ao trabalhar com XSL.
Os aplicativos usam XSL para transformar documentos XML. Os arquivos de estilo XSL contêm funções que descrevem a transformação e, se não implementados corretamente, podem incluir vulnerabilidades. Nesse caso, há um risco maior de cenários de ataque em que um invasor altera a estrutura e o conteúdo do arquivo de estilo XSL e, portanto, do arquivo XML correspondente. O que podemos obter na saída?
Primeiro, um ataque XSS: injetar código malicioso em uma página emitida por um sistema da web e interagir esse código com o servidor do invasor. Em segundo lugar, o hacker obtém acesso aos recursos do sistema. Terceiro, a execução de código arbitrário. E para sobremesa - ataque XXE (XML eXternal Entity - injeção de uma entidade externa em XML).
A incorporação do protocolo LDAP (Lightweight Directory Access Protocol ) em comandos pode resultar em perda ou modificação de dados. Nesse caso, dados não confiáveis chegam à solicitação LDAP.
Injeção de um comando de intérprete malicioso.Dados não confiáveis chegam ao comando do interpretador. Um invasor pode escolher tal entrada para que o comando seja executado com êxito e permissões adicionais no aplicativo sejam disponibilizadas para ele.
No exemplo abaixo, o aplicativo executa um script para criar um backup do banco de dados. O aplicativo usa o tipo de backup como parâmetro e executa o script com privilégios elevados:
String btype = request.getParameter("backuptype");
String cmd = new String("cmd.exe /K
\"c:\\util\\rmanDB.bat "+btype+"&&c:\\utl\\cleanup.bat\"")
System.Runtime.getRuntime().exec(cmd);
O problema aqui é que o parâmetro
backuptype
não é validado. Normalmente Runtime.exec()
não executa vários comandos, mas, neste caso, cmd.exe é iniciado primeiro para executar vários comandos invocando Runtime.exec()
. Uma vez que o shell da linha de comando é iniciado, ele pode executar vários comandos, separados por caracteres " &&
". Se um invasor && del c:\\dbms\\*.*
especificar a string " " como parâmetro , o aplicativo excluirá o diretório especificado.
Dicas para desenvolvedores:
- Não permita que os usuários controlem diretamente os comandos que o aplicativo executa. Se o comportamento do aplicativo depender dos dados inseridos pelo usuário, ofereça ao usuário uma escolha de uma determinada lista de comandos permitidos.
- , . , . , .
- , , . . .
Upload de arquivo inseguro. Nesse caso, não apenas os dados individuais vêm de uma fonte não confiável, mas o arquivo inteiro. Portanto, um invasor pode carregar dados ou códigos maliciosos no servidor de destino. Por exemplo, se os usuários em uma rede corporativa têm permissão para carregar arquivos em diretórios acessíveis ao público, um hacker pode executar remotamente um código malicioso no servidor da empresa.
Inclusão insegura de arquivo externo em HTML.Vulnerabilidades de inclusão de arquivo ocorrem quando o usuário insere o caminho para um arquivo incluído. O fato é que as linguagens de script modernas permitem vincular dinamicamente o código de arquivos de terceiros para reutilizá-lo. Este mecanismo é usado para uma aparência uniforme das páginas ou para dividir o código em pequenos módulos. No entanto, essa inclusão pode ser explorada por um invasor alterando o caminho e conectando seu arquivo.
Recomendamos que os profissionais de segurança da informação corporativa criem uma "lista branca" de caminhos de conexão de arquivos válidos para que os funcionários possam adicionar arquivos apenas de acordo com os scripts dessa lista.
Favoritos
Marcadores são partes que são introduzidas intencionalmente no código do aplicativo, com a ajuda dos quais, sob certas condições, você pode executar ações não incluídas no aplicativo. Vamos considerar os tipos mais comuns de marcadores.
Contas especiais. Se o aplicativo comparar o valor de uma senha ou variável de login com um valor inalterado, cuidado: esta conta pode fazer parte de um marcador. Vamos ver como isso acontece.

O desenvolvedor do aplicativo usa uma conta especial (possivelmente com privilégios elevados) ao depurar e deixa as seções correspondentes do código na versão final, retendo o acesso ao aplicativo. Um invasor pode restaurar o código original do aplicativo, extrair os valores constantes da conta especial e obter acesso ao aplicativo.
É categoricamente impossível armazenar logins, senhas, chaves no código-fonte do aplicativo.Funcionalidade oculta (NDV). O código de funcionalidade oculto é executado quando um gatilho específico é disparado. Em aplicativos da web, o gatilho geralmente é um parâmetro de consulta "invisível". Às vezes, além disso, é feita uma verificação de qual IP veio a solicitação com o gatilho, de forma que apenas seu autor poderia ativar o marcador. Essas verificações servem como um sinal para possíveis marcadores.
Atividade de rede não documentada. Esse tipo de atividade inclui: conexão com recursos de terceiros em segundo plano, escuta em portas não documentadas, transferência de informações via SMTP, HTTP, UDP, ICMP.
Se você encontrar uma conexão suspeita no código com um endereço que não está na lista de endereços seguros conhecidos, é altamente recomendável excluí-la.Altere as configurações de segurança . O aplicativo contém código que altera o valor da variável que armazena o sucesso da autenticação. Um erro comum é usar atribuição (=) em vez de comparação (==). Em métodos de autenticação, é especialmente perigoso porque pode fazer parte de uma porta dos fundos:
if (isAuthenticated = true)
{
someDangerousAction();
}
Gatilho de tempo (bomba de tempo). Um marcador que dispara em um momento específico. O aplicativo compara a data atual com um ano, mês e dia específicos: em 1º de janeiro de 2021, uma surpresa espera a todos:
Date now = java.util.Date(); // current time
if ((now.getYear() == 2021) && (now.getMonth() == 1) && (now.getDate() == 1))
{
activateNewYearBackdoor();
}
Ou talvez não ... Na prática, ao procurar gatilhos temporários, freqüentemente ocorrem falsos positivos. Por exemplo, se a API de tempo for usada para a finalidade pretendida: registro, cálculo do tempo de execução, carimbos de data / hora para respostas do servidor a solicitações HTTP.
Mas! Ainda assim, recomendamos não fechar os olhos a todos esses alarmes, pois conhecemos exemplos reais de tais vulnerabilidades.
Código morto. Pedaços de código injetado que não fazem nada de útil. O código morto em si não é perigoso, mas pode ser parte de um marcador que foi espalhado por vários arquivos. Ou o gatilho do marcador está planejado para ser implementado posteriormente. Em qualquer caso, o código morto deve ser suspeito.
Falta de criptografia e uso de algoritmos de criptografia fracos
Os principais problemas com a criptografia são que ela não é usada ou algoritmos fracos são usados e as chaves e o salt são muito simples ou armazenados de forma insegura. A consequência de todas essas vulnerabilidades é a mesma - é mais fácil roubar dados confidenciais.
O exemplo mostra a inicialização da criptografia usando o algoritmo DES legado:
Cipher cipher = Cipher.getInstance("DES");
Exemplos de algoritmos de criptografia vulneráveis: RC2, RC4, DES. Opção segura:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
De acordo com a classificação internacional OWASP , vulnerabilidades como “vazamento de dados confidenciais” estão classificadas em terceiro lugar em termos de gravidade das ameaças à segurança de aplicativos da web.
Nossa recomendação para desenvolvedores: certifique-se de usar criptografia tendo a segurança em mente.
Usar o protocolo HTTP inseguro em vez de HTTPS é repleto de um ataque Man in the middle.
O protocolo HTTPS seguro é baseado em HTTP, mas também suporta criptografia por meio de protocolos criptográficos SSL / TLS. HTTPS criptografa todos os dados transmitidos através dele, em particular, páginas de login e entrada de senha ou dados do cartão do banco do usuário, protegendo-os de acessos não autorizados e alterações. Ao contrário do HTTP, que não protege os dados transmitidos. Como resultado, um invasor pode falsificar um site informativo via HTTP e forçar o usuário a inserir dados em uma página falsa (ataque de phishing).
A chave de criptografia é especificada no código-fonte . Como resultado, essas chaves estão disponíveis para todos os desenvolvedores de aplicativos. Além disso, depois de instalar o aplicativo, você só pode remover a chave do código usando uma atualização.
Em geral, strings constantes são facilmente extraídas de um arquivo executável usando um programa de recuperação de código-fonte (descompilador). Portanto, um invasor não precisa ter acesso ao código-fonte para descobrir o valor da chave que está sendo usada. Em nossa prática, frequentemente encontramos casos em que os desenvolvedores especificam
null
uma string vazia como o valor da chave , o que é simplesmente inaceitável.
Nosso conselho: Gere chaves com geradores de números pseudo-aleatórios (PRNGs) criptograficamente fortes e armazene-as usando módulos especiais.
Algoritmo de preenchimento inseguro para criptografia . Se o algoritmo de criptografia RSA for usado sem o preenchimento OAEP, os dados criptografados se tornarão vulneráveis .
O algoritmo OAEP é necessário para processar mensagens antes de usar RSA. A mensagem é primeiro preenchida com um comprimento fixo usando OAEP e, em seguida, criptografada usando RSA. Este esquema de criptografia é denominado RSA-OAEP e faz parte do padrão atual .
Este é um exemplo de inicialização da criptografia RSA sem preenchimento:
rsa = javax.crypto.Cipher.getInstance("RSA/NONE/NoPadding");
Opção segura:
rsa = javax.crypto.Cipher.getInstance("RSA/ECB/OAEPWithMD5AndMGF1Padding");
Tamanho de chave de criptografia insuficiente . Se você usar uma chave curta, essa criptografia é vulnerável a ataques de força bruta.
A criptoanálise não pára, novos algoritmos de ataque surgem constantemente, os computadores ganham cada vez mais poder. As configurações de criptografia que antes eram consideradas seguras foram descontinuadas e não são mais recomendadas para uso. Portanto, o RSA com um comprimento de chave de 1024 bits não era mais considerado seguro em 2010-2015.
Algoritmo de hash fraco . Pelas razões descritas no parágrafo anterior, as funções hash MD2, MD5, SHA1 são inseguras. Para localizar colisões para as funções MD2 e MD5, nenhum recurso significativo é necessário.
Para SHA1, existem exemplos de dois arquivos diferentes com os mesmos hashes. Algoritmo de hacking sugeridofuncionários do Google e do Centro de Matemática e Ciência da Computação em Amsterdã.

Se as senhas dos usuários forem armazenadas como hashes, mas usando uma função hash insegura, um invasor pode facilmente obter acesso a elas implementando o seguinte cenário. Conhecendo o hash da senha e explorando a vulnerabilidade do algoritmo de hashing, é possível calcular uma string para a qual o hash é o mesmo da senha. O invasor autentica usando a string computada.
A função hash para armazenar senhas deve ser resistente a colisões e não muito rápida para que um ataque de força bruta não possa ser implementado. Os algoritmos seguros PBKDF2, bcrypt, scrypt devem ser usados.
Alguns números interessantes: com PBKDF2a velocidade de busca de chaves foi reduzida para 70 peças por segundo para Intel Core2 e cerca de 1 mil para FPGA Virtex-4 FX60. Em comparação, as funções clássicas de hash de senha do LANMAN têm uma velocidade de pesquisa de cerca de centenas de milhões de opções por segundo.
Algoritmo de criptografia fraco . Tal como acontece com os algoritmos de hash, a segurança de um algoritmo de criptografia é determinada pelo tempo e recursos que terão de ser gastos para descriptografá-lo. RC2, RC4, DES são considerados algoritmos vulneráveis. Este último, devido ao pequeno comprimento da chave (56 bits), pode ser quebrado por força bruta.
Um gerador de números pseudo-aleatórios (PRNG) fraco gera sequências previsíveis. Um hacker pode ignorar a autenticação e sequestrar a sessão de um usuário.
Vamos nos aprofundar um pouco mais na natureza dos PRNGs. Eles geram sequências de números com base no valor inicial do parâmetro
seed
. Existem dois tipos de PRNGs - estatísticos e criptográficos.
Os PRNGs estatísticos geram sequências previsíveis que são estatisticamente semelhantes às aleatórias. Eles não podem ser usados para fins de segurança.
O resultado da operação de PRNGs criptográficos, ao contrário, não pode ser previsto se o valor do parâmetro for
seed
obtido de uma fonte com alta entropia. O valor de tempo atual tem pouca entropia e também não é seguro em qualidade seed
. Em Java, PRNGs a partir de classes java.util.Random
e java.lang.Math
gerar seqüências previsíveis e não deve ser utilizado para fins de segurança da informação.
Semente fraca de um gerador de números pseudo-aleatórios . Não é
seed
seguro usar um valor de uma fonte não confiável, pois ele gera uma sequência previsível.
O trabalho de muitos algoritmos criptográficos é baseado no uso de um PRNG resistente à criptoanálise. Alguns algoritmos podem tomar um valor como um argumento adicional
seed
e gerar uma sequência previsível para cada valor desse parâmetro. Nesse caso, a segurança do sistema é baseada na premissa de que os valores seed
serão imprevisíveis.
O sal é fornecido no código-fonte... Vamos lembrar para que serve o sal. Para quebrar uma senha pelo método de força bruta, tabelas pré-compiladas com valores de funções hash de senhas populares são usadas. Salt é uma string arbitrária que é fornecida à entrada da função hash junto com a senha para tornar esse ataque mais difícil.
Se o sal for armazenado no código-fonte, surgem exatamente os mesmos problemas que ocorrem com senhas e chaves. O valor do salt está disponível para desenvolvedores e pode ser facilmente obtido por invasores, e o salt pode ser removido da versão final do aplicativo apenas com a próxima atualização do aplicativo.
Manipulação com registros
Vários erros nos logs são repletos de introdução de código malicioso nos aplicativos. As vulnerabilidades mais comuns associadas ao registro são a violação do arquivo de registro e o registro não estruturado.
A violação do arquivo de log ocorre quando um aplicativo grava dados não confiáveis no log de eventos (log). Um hacker pode falsificar entradas de log ou injetar código malicioso nelas.
Normalmente, os aplicativos gravam o histórico de transações no log para processamento adicional, depuração ou coleta de estatísticas. Os registros podem ser analisados manualmente ou automaticamente.
Se os dados forem gravados no log "como estão", um invasor pode injetar registros falsos no log, violar a estrutura do arquivo, fazendo com que o processador de log falhe, ou injetar código malicioso que explora vulnerabilidades conhecidas no processador.
Neste exemplo, um aplicativo da web tenta ler um valor inteiro de um parâmetro de solicitação. Se o valor inserido não puder ser convertido em um número inteiro, o aplicativo registrará esse valor junto com uma mensagem de erro:
String val = request.getParameter("val");
try {
int value = Integer.parseInt(val);
}
catch (NumberFormatException nfe) {
log.info("Failed to parse val = " + val);
}
Um invasor pode adicionar uma entrada arbitrária ao log, por exemplo, a linha
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
será refletida no log da seguinte forma:
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
Da mesma forma, registros arbitrários podem ser incorporados ao log.
Opção segura (usa
NumberFormatException
):
public static final String NFE = "Failed to parse val. The input is required to be an integer value."
String val = request.getParameter("val");
try {
int value = Integer.parseInt(val);
}
catch (NumberFormatException nfe) {
log.info(NFE);
}
O registro não estruturado , ou seja, a saída de mensagens de erro para os fluxos de saída padrão ou errados é um método inseguro. É recomendável usar o log estruturado em vez disso. Este último permite que você gere um log com níveis, carimbos de data / hora e formatação padrão. Se o programa implementar um mecanismo de log estruturado, mas as mensagens de erro forem enviadas para fluxos padrão, o log pode não conter informações críticas.
A saída de mensagens de erro para fluxos padrão é aceitável apenas nos estágios iniciais de desenvolvimento.
Manuseio inseguro de cookies
As vulnerabilidades associadas à coleta de cookies do usuário são muito diversas.
Manuseio inseguro de cookies . O aplicativo inclui dados de uma fonte não confiável no cookie, o que pode levar ao envenenamento do cache, XSS (script entre sites) e ataques de divisão de resposta.
Se um código malicioso (script entre sites) for injetado em um aplicativo, um invasor poderá modificar o cookie do usuário.
Como os cookies são definidos no cabeçalho de resposta HTTP, a falha em reconhecer os dados incluídos no cookie pode levar a um ataque de resposta dividida. "Divisão de resposta HTTP" é um ataque em que um hacker envia uma solicitação HTTP, cuja resposta será aceita pela vítima em duas respostas HTTP de uma vez (em vez da correta).
Se o invasor especificar uma
author
string do formulário como parâmetro Hacker \r\nHTTP/1.1 200 OK\r\n...
, a resposta será dividida em duas da seguinte maneira:
HTTP/1.1 200 OK
...
Set-Cookie: author=Hacker
HTTP/1.1 200 OK
...
O conteúdo da segunda resposta está completamente sob controle do invasor, levando ao envenenamento do cache, XSS, redirecionamentos maliciosos e outros ataques.
Cookies sem HttpOnly . O aplicativo cria cookies sem uma bandeira
httpOnly
. Se httpOnly
incluído no cabeçalho da resposta http
, um invasor não poderá obter cookies usando o código JavaScript. E se um usuário abrir uma página com uma vulnerabilidade de script entre sites (XSS), o navegador não divulgará os cookies a terceiros. Se o sinalizador httpOnly
não for definido, os cookies (geralmente cookies de sessão) podem ser roubados usando um script.
Um exemplo de criação de um cookie sem um sinalizador
httpOnly
:
Cookie cookie = new Cookie("emailCookie", email);
response.addCookie(cookie);
Defina o sinalizador
httpOnly
ao criar cookies. Lembre-se, entretanto, de que há maneiras de contornar os ataques, httpOnly
portanto , você também deve validar cuidadosamente a entrada.
NB De acordo com a classificação internacional OWASP , as vulnerabilidades de "vazamento de dados confidenciais" estão classificadas em terceiro lugar no nível de criticidade das ameaças à segurança de aplicativos da web.
Cookies para um domínio muito geral . Se o domínio para cookies for muito geral (por exemplo
.example.com
), uma vulnerabilidade em um aplicativo expõe outros aplicativos no mesmo domínio a vulnerabilidades.
No exemplo a seguir, um aplicativo da web seguro instalado em um endereço
http://secure.example.com
define um cookie com um valor de domínio .example.com
:
Cookie cookie = new Cookie("sessionID", sessionID);
cookie.setDomain(".example.com");
Se
http://insecure.example.com
um aplicativo que contém, por exemplo, XSS for instalado no endereço , os cookies do usuário autorizado do aplicativo seguro que foi para o endereço http://insecure.example.com
podem ser comprometidos.
Um invasor também pode realizar um ataque de envenenamento de cookie: os cookies com um domínio compartilhado criado
http://insecure.example.com
sobrescreverão o cookie http://secure.example.com
.
Opção segura:
Cookie cookie = new Cookie("sessionID", sessionID);
cookie.setDomain("secure.example.com");
Cookies com parâmetros muito gerais
path
. Se o caminho no cookie for impreciso (por exemplo, /), surge o mesmo problema do domínio compartilhado: uma vulnerabilidade em um aplicativo expõe outros aplicativos no mesmo domínio.
No exemplo a seguir, um aplicativo instalado em um URL
http://pages.example.com/forum
define um cookie com o caminho /:
Cookie cookie = new Cookie("sessionID", sessionID);
cookie.setPath("/");
Então, um aplicativo malicioso instalado no endereço
http://pages.example.com/evil
pode comprometer os cookies do usuário. Um invasor também pode realizar um ataque de envenenamento de cookie: um cookie com um caminho comum criado /evil
substituirá o cookie /forum
.
Opção segura:
Cookie cookie = new Cookie("sessionID", sessionID);
cookie.setPath("/forum");
Os cookies não são sobre SSL . O aplicativo cria cookies sem definir o sinalizador
secure
igual true
. Esses cookies podem ser transmitidos sem criptografia por HTTP. A vulnerabilidade "Usando o protocolo HTTP inseguro" é imediatamente recuperada.
No exemplo a seguir, o aplicativo cria cookies sem um sinalizador
secure
:
Cookie cookie = new Cookie("emailCookie", email);
response.addCookie(cookie);
Se o aplicativo usar HTTPS e HTTP, na ausência do sinalizador seguro, os cookies criados como parte da solicitação HTTPS serão transmitidos não criptografados em solicitações HTTP subsequentes, o que pode levar ao comprometimento do aplicativo. Isso é especialmente perigoso se o cookie contiver dados valiosos, em particular o ID da sessão.
Opção segura:
Cookie cookie = new Cookie("emailCookie", email);
cookie.setSecure(true);
response.addCookie(cookie);
Cookies com validade ilimitada . Se você armazenar cookies valiosos por muito tempo, um invasor pode ter tempo para obter acesso a eles.
Por padrão, são usados cookies não persistentes (sessão), que não são salvos no disco e são excluídos após fechar o navegador. No entanto, o desenvolvedor do aplicativo da web pode especificar por quanto tempo os cookies são mantidos - neste caso, eles serão gravados no disco e salvos entre a reinicialização do navegador e a reinicialização do computador. Isso dá ao invasor muito tempo para desenvolver um plano de ataque.
Recomendações do desenvolvedor: certifique-se de que o aplicativo não crie cookies de longa duração:
Cookie cookie = new Cookie("longCookie", cookie);
cookie.setMaxAge(5*365*24*3600); // 5 !
Fornece um limite de tempo máximo razoável de acordo com as diretrizes OWASP .
Vazamento de informação
Talvez o tipo de vulnerabilidade mais sensível para usuários de aplicativos.
Vazamento de informações externas através de páginas de erro . O aplicativo usa páginas de erro padrão, que podem conter informações sobre a configuração do sistema.
Mensagens de erro e informações de depuração são gravadas no log, exibidas no console ou transmitidas ao usuário. A partir das mensagens de erro, um invasor pode aprender sobre as vulnerabilidades do sistema, o que tornará sua vida mais fácil. Por exemplo, um erro de banco de dados pode indicar insegurança contra injeção de SQL. As informações sobre a versão do sistema operacional, o servidor de aplicativos e a configuração do sistema tornarão mais fácil para um hacker planejar um ataque a um aplicativo.
Vazamento externo de informações valiosas... Neste caso, estamos falando do vazamento de informações técnicas sobre o aplicativo ao transferi-lo pela rede para outro computador. Em geral, os vazamentos externos são mais perigosos do que os internos.

Vazamento interno de informações valiosas . O mecanismo de operação é semelhante aos dois tipos anteriores de vazamentos, mas, neste caso, as informações sobre o sistema são gravadas no log ou exibidas na tela do usuário.
Vazamento de dados confidenciais . Dados pessoais valiosos dos usuários entram no aplicativo de diferentes fontes: do próprio usuário, de vários bancos de dados, de armazenamentos de terceiros. Às vezes, esses dados não são marcados como confidenciais ou acabam sendo valiosos não por si só, mas apenas em um determinado contexto.
Este é exatamente o caso quando a segurança do aplicativo e a privacidade dos dados pessoais se contradizem. Por motivos de segurança, é aconselhável registrar informações detalhadas sobre a atividade no sistema para detectar atividades maliciosas. Do ponto de vista da privacidade dos dados, ao contrário, no registro de informações confidenciais, o risco de vazamento é maior. Em geral, garantir a confidencialidade dos dados pessoais dos usuários do aplicativo é uma prioridade mais alta.
Posfácio
Os tipos de vulnerabilidades considerados neste artigo cobrem a maioria das lacunas "universais" em aplicativos escritos em diferentes linguagens de programação. No entanto, alguns idiomas têm suas próprias vulnerabilidades específicas. Mas este já é um assunto para um artigo separado. E por último, lembre-se: ao criar aplicativos, não se esqueça de seguir as recomendações acima, leia atentamente a documentação e verifique os aplicativos quanto a vulnerabilidades usando um software especializado.
Autor: Elizaveta Kharlamova, Chefe do Departamento de Análise, Solar appScreener