Ameaças
Ataques DoS (Denial of Service)
Sintomas
- Usuários legítimos não conseguindo acessar a aplicação.
- Consumo excessivo de recursos impede o funcionamento da aplicação.
Causas
- Sobrecarregar sua aplicação com dados ou código que ela não está preparada para lidar.
- Um serviço ou conexão é sobrecarregado com requisições falsas.
Prevenção
- Restringir acesso a código que consome recursos vulneráveis através de permissões.
- Validar todo input da aplicação.
- Garantir que um recurso é liberado o mais rápido possível. (e.g. encerrar uma conexão com o banco de dados assim que conseguir os dados necessários.)
- Monitorar consumo desproporcional ao utilizado para requerer um serviço. Essa medida serve para identificar quando o problema está ocorrendo, para que uma ação possa ser tomada.
- Vazamento de dados são causados por falta de encriptação ou redução de informação.
- Corrupção de código é causada por falta de encapsulamento e imutabilidade.
- Injeção de código ocorrem por falta de validação e sanitização em input.
Boas Práticas
- De-serialização de recursos externos é extremamente perigoso. Esse processo não passa por nenhum tipo de construtor e é carregado diretamente na memória. Dessa forma o objeto ignora qualquer tipo de validação de segurança. Para mitigar o risco os valores devem ser validados antes de qualquer operação com os dados de-serializados.
- Forçar um rígido encapsulamento. Métodos, atributos, classes aninhadas, etc. devem requerer o nível de acesso mais privado possível. Também é importante proteger as classes de acesso por reflexão através do sistema de modulagem.
- Objetos devem ser o mais imutáveis possível. O objeto a que uma referência imutável está relacionada deve ser também imutável sempre que possível. A clonagem de objetos é uma ótima maneira de garantir a imutabilidade.
- Não quebre a lógica de código herdado. A utilização de métodos herdados deve ser feita com a noção de que possíveis mudanças podem ocorrer à esses métodos. Também pode ocorrer de um método que contradiz a semântica da classe seja adicionado a classe-mãe e ao herda-lo sua classe perde coesão.
- Ao sobrescrever um método de forma que a semântica dele não seja a mesma da classe-mãe, o método passa a ser ambíguo e pode causar problemas ao ser utilizado de maneira incorreta.
- Faça o design de classes e métodos adeptos a herança ou não-herdáveis. Métodos que não são
final
ouprivate
podem ser sobrescritos por invasores. Por isso, métodos que podem ser sobrescritos não devem ser chamados durante no construtor. Também é podem ser feitas validações antes da criação de um objeto através de métodos fábrica (factory methods).
- Proteja código binário contra alterações. Jamais desabilite a verificação de código binário.
- Codifique ciente de valores inválidos. Utilizar a classe
Optional
como empacotadora de referências ajuda a lidar com valoresnull
. Também realize operações matemáticas levando em consideração a capacidade do tipo de dado, números flutuantes infinitos, divisões por zero, ...
- Proteja dados sensíveis. Considere codificar esses dados, limpá-los da memória o mais rápido possível, remove-los de exceções e jamais serializa-los ou escreve-los em arquivos de log.
// encriptar dados sensíveis MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] digest = md.digest(value.getBytes()); String hash = (new BigInteger(1, digest)).toString(16); // remover de exceções try { /* ações que podem resultar em erros contendo dados sensíveis */ } catch (SQLException e) { logger.error("Não foi possível validar cartão de crédito."); } // criptografia com javax.crypto String text = "Value that requires encryption"; // a chave normalmente é carregada de um arquivo SecretKey key = KeyGenerator.getInstance("AES").generateKey(); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] value = text.getBytes(); byte[] encryptedValue = cipher.doFinal(value); GCMParameterSpec ps = cipher.getParameters().getParameterSpec(GCMParameterSpec.class); cipher.init(Cipher.DECRYPT_MODE, key, ps); byte[] decryptedValue = cipher.doFinal(ecryptedValue);
- Sanitização de input previne injeção de SQL. A classe
Statement
permite a execução de uma query montada com concatenação deString
s. EssasString
s precisam ser limpas com o métodoenquoteLiteral(param)
para evitar injeção de SQL. Outra opção é utilizar a classePreparedStatement
que faz isso por padrão.
- Prevenção a injeção de código JavaScript e XML. Todo valor processado pelo navegador deve passar pelo processo de sanitização. Uma biblioteca que ajuda nesse processo é a
OWASP
. Além dessa biblioteca, injeções de XML podem ser prevenidas ao utilizar a classeDocumentBuilderFactory
com a funcionalidadeFEATURE_SECURE_PROCESSING
habilitada.