Este artigo foi compartilhado na comunidade Huawei Cloud " Application Security Protection ESAPI " por Uncle_Tom.
1. Introdução ao ESAPI
OWASP Enterprise Security API (ESAPI) é uma biblioteca gratuita e de código aberto de controles de segurança de aplicativos da web que torna mais fácil para os programadores escreverem aplicativos de baixo risco. A biblioteca ESAPI foi projetada para facilitar aos programadores a atualização de aplicativos existentes para segurança. A biblioteca ESAPI também é uma base sólida para novos desenvolvimentos.
Levando em consideração diferenças específicas de idioma, todas as versões do OWASP ESAPI têm o mesmo design básico:
- Existe um conjunto de interfaces de controle de segurança. Por exemplo, define os tipos de parâmetros passados para tipos de controle de segurança.
- Cada controle de segurança possui uma implementação de referência. Por exemplo: validação de entrada baseada em string. Por exemplo, ESAPI org.owasp.ESAPI.reference.FileBasedAuthenticator de Java, enquanto outras implementações de referência são implementações de referência maduras de nível empresarial, como org.oasp.ESAPI.reference.DefaultEncoder ou org.owasp.ESAPI.reference.DefaultValidator .
- Cada controle de segurança possui sua própria implementação (opcional). Essas classes podem conter lógica de aplicação, que pode ser desenvolvida por ou para sua organização. Por exemplo: Autenticação Corporativa.
- Para tornar este projeto o mais fácil de divulgar possível e permitir que mais pessoas o utilizem livremente, o código-fonte deste projeto utiliza a licença BSD. A documentação deste projeto está licenciada sob uma Licença Creative Commons Attribution. Você é livre para usar, modificar e até incluir ESAPI em produtos comerciais.
2. Estrutura ESAPI
OWASP ESAPI implementou os seguintes controles de segurança
- Autenticação
- Controle de acesso
- Validação de entrada
- Codificação/escape de saída
- senha
- Tratamento e registro de erros
- segurança de comunicação
- Segurança HTTP
- Configuração de segurança
Estrutura ESAPI
OWASP Top 10 cobertos pela ESAPI
3. Uso de ESAPI
3.1. Configuração ESAPI em pom.xml
A última versão é: 2.5.3.1, que pode ser encontrada diretamente no repositório Maven.
<!-- https://mvnrepository.com/artifact/org.owasp.esapi/esapi --> <dependency> <groupId>org.owasp.esapi</groupId> <artifactId>esapi</artifactId> <versão> 2.5.3.1</versão> <exclusões> <exclusão> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusão> < /exclusões > </dependency> < !-- https ://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <versão>3.1 .0</version> <scope>fornecido</scope> </dependency>
3.2. Proteção contra problemas de injeção
Grande parte dos problemas de segurança de rede são causados por problemas de injeção. Esse tipo de problema é causado principalmente por transcodificação inadequada durante o uso de entradas externas, como injeção de SQL, injeção de comando, script entre sites, etc.
Encode (interface do codificador) contém muitos métodos para decodificar a entrada e codificar a saída para que os caracteres processados sejam seguros para vários intérpretes.
3.2.1. Proteção: ataque de script entre sites XSS
Codificador HTML (encodeForHTML)
@Test void testEncodeForHTML() { String input = "<a href='sdfs'></a> < script > alert('xss'); </ script >"; String encodedString = ESAPI.encoder().encodeForHTML(input); LOG.info("EncodeForHTML: {}", encodedString); }
Saída:
EncodeForHTML: <a href='xss'></a> < roteiro> alerta('xss'); </ roteiro>
Codificador de URL (encodeForURL)
@Test void testEncodeForURL() { String input = "/?callback=<script>alert('xss')</script>"; String codificadaString; tente { encodedString = ESAPI.encoder().encodeForURL(input); LOG.info("EncodeForURL: {}", encodedString); } catch (EncodingException e) { fail("Não deve obter exceção:" + e.getMessage()); } }
Saída:
EncodeForURL: %2F%3Fcallback%3D%3Cscript%3Ealert%28%27xss%27%29%3C%2Fscript%3E
3.2.2. Proteção: injeção de SQL
@Test void testEncodeForSQL() { String userId = "tom' ou '1=1'"; String sql = "select * from user where user='" + ESAPI.encoder().encodeForSQL(new MySQLCodec(MySQLCodec.Mode.STANDARD), userId) + "'"; LOG.info("sql = {}",sql); }
Saída:
sql = selecione * do usuário onde usuário='tom\' ou \'1\=1\''
3.2.3. Proteção: Injeção de Comando
@Test void testEncodeForOS() { String input = "dir & dir /s"; String cmd = ESAPI.encoder().encodeForOS(new WindowsCodec(), entrada); LOG.info("cmd = {}",cmd); }
Saída:
cmd = diretório^ ^&^ diretório^ ^/s
3.3. Proteção contra problemas de validação de entrada
A maior ameaça à segurança da rede são as entradas externas, portanto a verificação das entradas externas desempenha o maior papel protetor na segurança das aplicações.
3.3.1. Verificação de entrada ESAPI
ESAPI possui uma configuração de validação de entrada: validação.properties fornece validações comumente usadas.
validação.propriedades
Validator.SafeString=^[.\\p{Alnum}\\p{Space}]{0,1024}$ Validator.Email=^[A-Za-z0-9._%'-]+@[A- Za-z0-9.-]+\\.[a-zA-Z]{2,4}$ Validator.IPAddress=^(?:(?:25[0-5]|2[0-4][ 0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]| [01]?[0-9][0-9]?)$ Validador.URL=^(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z] ([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\ .\\?\\,\\:\\'\\/\\\\\\+=&;%\\$#_]*)?$ Validator.CreditCard=^(\\d{4}[ - ]?){3}\\d{4}$ Validador.SSN=^(?!000)([0-6]\\d{2}|7([0-6]\\d|7[ 012]))([ -]?)(?!00)\\d\\d\\3(?!0000)\\d{4}$
Interface de verificação
/** * Verificação de entrada * * @param conteúdo de verificação de contexto * @param entrada de verificação de entrada * @param tipo tipo de verificação, correspondente ao tipo em validação.properties * @param maxLength verificação do comprimento máximo do caracter de entrada * @ param permitirNull Caractere de entrada Nulo verificação de valor, falso - não permitido; verdadeiro - permitido * @return Retorna falso se a verificação falhar, retorna verdadeiro se a verificação for bem-sucedida */ boolean ESAPI.validator().getValidInput(String context, String input, String type , int maxLength, boolean permitirNull );
@Test void testValidatorEmail() { String input = "xxxx.com"; if (!ESAPI.validator().isValidInput("", input, "Email", 11, false)) { LOG.error("E-mail validado falhou!"); } else { LOG.info("Email validado."); } }
Saída:
Falha na validação do e-mail!
4. Problemas comuns encontrados durante o uso e atualização do ESAPI
4.1.org.owasp.esapi.reference.DefaultEncoder CTOR lançou exceção causada por ExceptionInInitializerError
org.owasp.esapi.errors.ConfigurationException: java.lang.reflect.InvocationTargetException Classe codificadora (org.owasp.esapi.reference.DefaultEncoder) CTOR lançou exceção. em org.owasp.esapi.util.ObjFactory.make(ObjFactory.java:129) em org.owasp.esapi.ESAPI.encoder(ESAPI.java:101) em com.test.esapi.EsapiTest.testUpdateJulietInfo_good(EsapiTest.java :19) em java.base/java.util.ArrayList.forEach(ArrayList.java:1511) em java.base/java.util.ArrayList.forEach(ArrayList.java:1511) Causado por: java.lang.reflect. InvocationTargetException em org.owasp.esapi.util.ObjFactory.make(ObjFactory.java:86) ... 71 mais Causado por: java.lang.ExceptionInInitializerError em java.base/java.lang.Class.forName0(Native Method) em java.base/java.lang.Class.forName(Class.java:375) em org.owasp.esapi.util.ObjFactory.loadClassByStringName(ObjFactory.java:158) em org.owasp.esapi.util.ObjFactory.make( ObjFactory.java:81) em org.owasp.esapi.ESAPI.logFactory(ESAPI.java:139) em org.owasp.esapi.ESAPI.getLogger(ESAPI.java:155) em org.owasp.esapi.reference.DefaultEncoder .(DefaultEncoder.java:85) em org.owasp.esapi.reference.DefaultEncoder.(DefaultEncoder.java:109) em org.owasp.esapi.reference.DefaultEncoder.getInstance(DefaultEncoder.java:68) ... 76 mais Causado por: org.owasp.esapi.errors.ConfigurationException: Não foi possível localizar o recurso: esapi-java-logging.properties em org.owasp.esapi.logging.java.JavaLogFactory.readLoggerConfiguration(JavaLogFactory.java:128) em org.owasp .esapi.logging.java.JavaLogFactory.(JavaLogFactory.java:96) ... 85 mais
Este é o problema mais comum encontrado ao atualizar ESAPI para versões posteriores a 2.5.0.0.
2.5.0.0 é uma versão alterada importante da ESAPI, podemos ver nas informações de alteração de versão:
- Esta versão do ESAPI abandona completamente o suporte para Log4J, que é afetado pelas constantes vulnerabilidades do Log4J, e em vez disso usa SLF4J. Se sua propriedade ESAPI.Logger estiver configurada para usar Log4J, exceções ou erros obscuros serão lançados, geralmente ExceptionInInitializerError, se você não alterá-la.
- O AntiSamy foi atualizado para 1.7.0 e o arquivo AntiSamy-sapi.xml personalizado do AntiSamy é compatível.
- A partir da versão anterior, esta versão suporta apenas Java 8 ou superior.
A partir daqui você pode ver que ExceptionInInitializerError deve ser causado pelo componente de log de alterações. Amigos familiares pensarão imediatamente no arquivo de configuração da ESAPI, ESAPI.properties, que fornece a configuração de todos os componentes.
Como você pode ver nas linhas 69 a 72 da figura, linha 69:
ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory
Ainda aponta para org.owasp.esapi.logging.java.JavaLogFactory. Os comentários a seguir também nos lembram que precisamos alterá-lo para a linha 71:
ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory
O problema é resolvido após a modificação.
4.2. java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest
java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest em java.base/java.lang.Class.getDeclaredMethods0(Método Nativo) em java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3402) em java .base/java.lang.Class.getMethodsRecursive(Class.java:3543) em java.base/java.lang.Class.getMethod0(Class.java:3529) em java.base/java.lang.Class.getMethod(Class .java:2225) em org.owasp.esapi.util.ObjFactory.loadMethodByStringName(ObjFactory.java:196) em org.owasp.esapi.util.ObjFactory.findSingletonCreateMethod(ObjFactory.java:173) em org.owasp.esapi. util.ObjFactory.make(ObjFactory.java:84) em org.owasp.esapi.ESAPI.validator(ESAPI.java:192) em com.huawei.hwe.esapi.EsapiTest.testEsapi_encodeForURL(EsapiTest.java:23) em java .base/java.util.ArrayList.forEach(ArrayList.java:1511) em java.base/java.util.ArrayList.forEach(ArrayList.java:1511) Causado por: java.lang.ClassNotFoundException: javax.servlet.http .HttpServletRequest em java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) em java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) em java.base /java.lang.ClassLoader.loadClass(ClassLoader.java:525) ... 79 mais
Este problema obviamente está faltando bibliotecas dependentes. Podemos visualizar a definição da biblioteca Maven e informações de dependência sobre ESAPI.
https://mvnrepository.com/artifact/org.owasp.esapi/esapi/2.5.3.1
Dependências de compilação
Dependências de tempo de execução

Nas dependências em execução, você pode ver os requisitos: javax.servlet » javax.servlet-api.
Clique no número da versão: 3.1.0 para obter a configuração da dependência mvn de javax.servlet-api 3.1.0. Adicione esta configuração a o arquivo pom.xml do projeto nele.
Depois de adicionar a configuração javax.servlet-api em pom.xml, o problema está resolvido.
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId > <version>3.1.0</version> <scope>fornecido</scope> </dependency>
Clique para seguir e conhecer as novas tecnologias da Huawei Cloud o mais rápido possível~