Este artículo es compartido por Uncle_Tom de la comunidad de la nube de Huawei " Protección de seguridad de aplicaciones ESAPI ".
1. Introducción a ESAPI
OWASP Enterprise Security API (ESAPI) es una biblioteca gratuita y de código abierto de controles de seguridad de aplicaciones web que facilita a los programadores la escritura de aplicaciones de menor riesgo. La biblioteca ESAPI está diseñada para facilitar a los programadores la actualización de aplicaciones existentes por motivos de seguridad. La biblioteca ESAPI también es una base sólida para nuevos desarrollos.
Teniendo en cuenta las diferencias específicas del idioma, todas las versiones de OWASP ESAPI tienen el mismo diseño básico:
- Hay un conjunto de interfaces de control de seguridad. Por ejemplo, define los tipos de parámetros pasados a los tipos de control de seguridad.
- Cada control de seguridad tiene una implementación de referencia. Por ejemplo: validación de entrada basada en cadenas. Por ejemplo, ESAPI org.owasp.ESAPI.reference.FileBasedAuthenticator de Java, mientras que otras implementaciones de referencia son implementaciones de referencia maduras a nivel empresarial, como org.oasp.ESAPI.reference.DefaultEncoder u org.owasp.ESAPI.reference.DefaultValidator.
- Cada control de seguridad tiene su propia implementación (opcional). Estas clases pueden contener lógica de aplicación, que puede ser desarrollada por o para su organización. Por ejemplo: autenticación empresarial.
- Para que este proyecto sea lo más fácil de difundir posible y permitir que más personas lo utilicen libremente, el código fuente de este proyecto utiliza la licencia BSD. La documentación de este proyecto tiene una licencia de atribución Creative Commons. Eres libre de utilizar, modificar e incluso incluir ESAPI en productos comerciales.
2. Marco ESAPI
OWASP ESAPI ha implementado los siguientes controles de seguridad
- Autenticación
- Control de acceso
- Validación de entrada
- Codificación/escape de salida
- contraseña
- Manejo de errores y registro
- seguridad de las comunicaciones
- seguridad HTTP
- Configuración de seguridad
Marco ESAPI
OWASP Top 10 cubiertos por ESAPI
3. Uso de ESAPI
3.1 Configuración de ESAPI en pom.xml
La última versión es: 2.5.3.1, que se puede encontrar directamente en el repositorio de Maven.
<!-- https://mvnrepository.com/artifact/org.owasp.esapi/esapi --> <dependencia> <groupId>org.owasp.esapi</groupId> <artifactId>esapi</artifactId> <versión> 2.5.3.1</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusion> </exclusions> </dependency> <!-- https ://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependencia> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <versión>3.1 .0</versión> <ámbito>proporcionado</ámbito> </dependencia>
3.2 Protección contra problemas de inyección
Gran parte de los problemas de seguridad de la red se deben a problemas de inyección. Este tipo de problema se debe principalmente a una transcodificación incorrecta durante el uso de entradas externas, como inyección de SQL, inyección de comandos, secuencias de comandos entre sitios, etc.
Encode (interfaz de codificador) contiene muchos métodos para decodificar la entrada y codificar la salida para que los caracteres procesados sean seguros para varios intérpretes.
3.2.1 Protección: ataque de secuencias de comandos entre sitios XSS
Codificador HTML (encodeForHTML)
@Test void testEncodeForHTML() { String input = "<a href='sdfs'></a> < script > alert('xss'); </ script >"; Cadena codificadaString = ESAPI.encoder().encodeForHTML(entrada); LOG.info("EncodeForHTML: {}", cadena codificada); }
Producción:
EncodeForHTML: <a href='xss'></a> < guión > alerta('xss'); </ guión >
Codificador de URL (encodeForURL)
@Test void testEncodeForURL() { String input = "/?callback=<script>alert('xss')</script>"; Cadena codificadaCadena; intente { encodedString = ESAPI.encoder().encodeForURL(entrada); LOG.info("EncodeForURL: {}", cadena codificada); } catch (EncodingException e) { fail("No debería obtenerse una excepción:" + e.getMessage()); } }
Producción:
CodificarParaURL: %2F%3Fcallback%3D%3Cscript%3Ealert%28%27xss%27%29%3C%2Fscript%3E
3.2.2 Protección: inyección SQL
@Test void testEncodeForSQL() { String userId = "tom' o '1=1'"; String sql = "seleccione * del usuario donde usuario='" + ESAPI.encoder().encodeForSQL(new MySQLCodec(MySQLCodec.Mode.STANDARD), userId) + "'"; LOG.info("sql = {}", sql); }
Producción:
sql = seleccionar * del usuario donde usuario='tom\' o \'1\=1\''
3.2.3 Protección: Inyección de Comandos
@Test void testEncodeForOS() { Entrada de cadena = "dir & dir /s"; String cmd = ESAPI.encoder().encodeForOS(nuevo WindowsCodec(), entrada); LOG.info("cmd = {}", cmd); }
Producción:
cmd = directorio^ ^&^ directorio^ ^/s
3.3 Protección contra problemas de validación de entradas
La mayor amenaza para la seguridad de la red son las entradas externas, por lo que la verificación de las entradas externas desempeña el mayor papel protector en la seguridad de las aplicaciones.
3.3.1 Verificación de entrada ESAPI
ESAPI tiene una configuración de validación de entrada: validation.properties proporciona validaciones de uso común.
propiedades.validación
Validator.SafeString=^[.\\p{Alnum}\\p{Espacio}]{0,1024}$ Validator.Email=^[A-Za-z0-9._%'-]+@[A- Za-z0-9.-]+\\.[a-zA-Z]{2,4}$ Validador.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\\-\\ .\\?\\,\\:\\'\\/\\\\\\+=&;%\\$#_]*)?$ Validador.TarjetaCredit=^(\\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}$
Interfaz de verificación
/** * Verificación de entrada * * @param contenido de verificación de contexto * @param entrada entrada de verificación * @param tipo tipo de verificación, correspondiente al tipo en validation.properties * @param maxLength carácter de entrada verificación de longitud máxima * @ param enableNull Carácter de entrada nulo verificación de valor, falso - no permitido; verdadero - permitido * @return Devuelve falso si la verificación falla, devuelve verdadero si la verificación se realiza correctamente */ boolean ESAPI.validator().getValidInput(Contexto de cadena, entrada de cadena, tipo de cadena, int maxLength, boolean enableNull );
@Test void testValidatorEmail() { Entrada de cadena = "xxxx.com"; if (!ESAPI.validator().isValidInput("", input, "Email", 11, false)) { LOG.error("¡Error en la validación del correo electrónico!"); } else { LOG.info("El correo electrónico se valida."); } }
Producción:
¡Falló la validación del correo electrónico!
4. Problemas comunes encontrados durante el uso y actualización de ESAPI
4.1 org.owasp.esapi.reference.DefaultEncoder CTOR lanzó una excepción causada por ExceptionInInitializerError
org.owasp.esapi.errors.ConfigurationException: java.lang.reflect.InvocationTargetException Clase de codificador (org.owasp.esapi.reference.DefaultEncoder) CTOR arrojó una excepción. en org.owasp.esapi.util.ObjFactory.make(ObjFactory.java:129) en org.owasp.esapi.ESAPI.encoder(ESAPI.java:101) en com.test.esapi.EsapiTest.testUpdateJulietInfo_good(EsapiTest.java :19) en java.base/java.util.ArrayList.forEach(ArrayList.java:1511) en java.base/java.util.ArrayList.forEach(ArrayList.java:1511) Causado por: java.lang.reflect. InvocationTargetException en org.owasp.esapi.util.ObjFactory.make(ObjFactory.java:86) ... 71 más Causado por: java.lang.ExceptionInInitializerError en java.base/java.lang.Class.forName0(Native Method) en java.base/java.lang.Class.forName(Class.java:375) en org.owasp.esapi.util.ObjFactory.loadClassByStringName(ObjFactory.java:158) en org.owasp.esapi.util.ObjFactory.make( ObjFactory.java:81) en org.owasp.esapi.ESAPI.logFactory(ESAPI.java:139) en org.owasp.esapi.ESAPI.getLogger(ESAPI.java:155) en org.owasp.esapi.reference.DefaultEncoder .(DefaultEncoder.java:85) en org.owasp.esapi.reference.DefaultEncoder.(DefaultEncoder.java:109) en org.owasp.esapi.reference.DefaultEncoder.getInstance(DefaultEncoder.java:68) ... 76 más Causado por: org.owasp.esapi.errors.ConfigurationException: no se puede localizar el recurso: esapi-java-logging.properties en org.owasp.esapi.logging.java.JavaLogFactory.readLoggerConfiguration(JavaLogFactory.java:128) en org.owasp .esapi.logging.java.JavaLogFactory.(JavaLogFactory.java:96) ... 85 más
Este es el problema más común que se encuentra al actualizar ESAPI a versiones posteriores a la 2.5.0.0.
2.5.0.0 es una versión modificada importante de ESAPI. Podemos ver en la información de cambio de versión:
- Esta versión de ESAPI abandona por completo el soporte para Log4J, que está plagado de constantes vulnerabilidades de Log4J, y en su lugar utiliza SLF4J. Si su propiedad ESAPI.Logger está configurada para usar Log4J, se generarán excepciones o errores oscuros, generalmente ExceptionInInitializerError, si no lo cambia.
- AntiSamy se ha actualizado a 1.7.0 y se admite el archivo AntiSamy-sapi.xml personalizado de AntiSamy.
- A partir de la versión anterior, esta versión sólo soporta Java 8 o superior.
Desde aquí puede ver que ExceptionInInitializerError debería ser causado por el componente de registro de cambios. Los amigos familiares pensarán inmediatamente en el archivo de configuración de ESAPI, ESAPI.properties, que proporciona la configuración de todos los componentes.
Como puede ver en las líneas 69 a 72 de la figura, línea 69:
ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory
Todavía apunta a org.owasp.esapi.logging.java.JavaLogFactory. Los siguientes comentarios también nos recuerdan que debemos cambiarlo a la línea 71:
ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory
El problema se resuelve después de la modificación.
4.2. java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest
java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest en java.base/java.lang.Class.getDeclaredMethods0 (método nativo) en java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3402) en java .base/java.lang.Class.getMethodsRecursive(Class.java:3543) en java.base/java.lang.Class.getMethod0(Class.java:3529) en java.base/java.lang.Class.getMethod(Class .java:2225) en org.owasp.esapi.util.ObjFactory.loadMethodByStringName(ObjFactory.java:196) en org.owasp.esapi.util.ObjFactory.findSingletonCreateMethod(ObjFactory.java:173) en org.owasp.esapi. util.ObjFactory.make(ObjFactory.java:84) en org.owasp.esapi.ESAPI.validator(ESAPI.java:192) en com.huawei.hwe.esapi.EsapiTest.testEsapi_encodeForURL(EsapiTest.java:23) en java .base/java.util.ArrayList.forEach(ArrayList.java:1511) en java.base/java.util.ArrayList.forEach(ArrayList.java:1511) Causado por: java.lang.ClassNotFoundException: javax.servlet.http .HttpServletRequest en java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) en java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) en java.base /java.lang.ClassLoader.loadClass(ClassLoader.java:525) ... 79 más
Obviamente, a este problema le faltan bibliotecas dependientes. Podemos ver la definición de la biblioteca Maven y la información de dependencia sobre ESAPI.
https://mvnrepository.com/artifact/org.owasp.esapi/esapi/2.5.3.1
Dependencias de compilación
Dependencias de tiempo de ejecución

Desde las dependencias en ejecución, puede ver los requisitos: javax.servlet » javax.servlet-api.
Haga clic en el número de versión: 3.1.0 para obtener la configuración de dependencia mvn de javax.servlet-api 3.1.0. Agregue esta configuración a el archivo del proyecto pom.xml que contiene.
Después de agregar la configuración javax.servlet-api en pom.xml, el problema se resuelve.
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependencia> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId > <versión>3.1.0</versión> <ámbito>proporcionado</ámbito> </dependencia>
Haga clic para seguir y conocer las nuevas tecnologías de Huawei Cloud lo antes posible ~