top seguridad que coldfusion coldfusion-9 cfml esapi

seguridad - ¿Cómo implementar el validador ESAPI de OWASP con grupos de intentos de validación en ColdFusion?



owasp top 10 2016 (1)

He estado jugando con las utilidades OWASP ESAPI que se incluyen con ColdFusion 9. API Builtin Enterprise Security de ColdFusion . Las utilidades del encoder son bastante sencillas y creo que las tengo funcionando bien. Mi problema es con las utilidades del validator .

Puedo hacer que trabajen solos . Es decir, si llamo al método validator.getValidInput() con datos "inválidos" arrojará un error que puedo detectar. Sin embargo, cuando trato de llamar al método del validator por lotes , obtengo una excepción de puntero nulo. Por lote me refiero a intentar ejecutar grupos de intentos de validación. Se supone que esto funciona al pasar el método validator.getValidInput() un parámetro ValidationErrorList que debería indicarle que NO arroje un error sino que simplemente agregue el error a la lista de errores. No puedo hacer que funcione en este modo. Mi mejor intento es darme una excepción de puntero nulo.

Aquí está el error específico:

java.lang.NullPointerException

Con este rastro de pila:

java.lang.NullPointerException at org.owasp.esapi.reference.DefaultValidator.getValidInput(DefaultValidator.java:238) at sun.reflect.GeneratedMethodAccessor377.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at coldfusion.runtime.StructBean.invoke(StructBean.java:536) at coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2393) at cftest2ecfm989071068.runPage(D:/Web/internet/fboc/test.cfm:19) at coldfusion.runtime.CfJspPage.invoke(CfJspPage.java:231) at coldfusion.tagext.lang.IncludeTag.doStartTag(IncludeTag.java:416) at coldfusion.runtime.CfJspPage._emptyTcfTag(CfJspPage.java:2722) at cfApplication2ecfc1705903666$funcONREQUEST.runFunction(D:/Web/internet/fboc/Application.cfc:70) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472) at coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405) at coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368) at coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55) at coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:491) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:337) at coldfusion.runtime.AppEventInvoker.invoke(AppEventInvoker.java:88) at coldfusion.runtime.AppEventInvoker.onRequest(AppEventInvoker.java:280) at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:356) at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:48) at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40) at coldfusion.filter.PathFilter.invoke(PathFilter.java:94) at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:70) at coldfusion.filter.BrowserDebugFilter.invoke(BrowserDebugFilter.java:79) at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28) at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38) at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:46) at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38) at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22) at coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62) at coldfusion.filter.RequestThrottleFilter.invoke(RequestThrottleFilter.java:126) at coldfusion.CfmServlet.service(CfmServlet.java:201) at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89) at jrun.servlet.FilterChain.doFilter(FilterChain.java:86) at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42) at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46) at jrun.servlet.FilterChain.doFilter(FilterChain.java:94) at jrun.servlet.FilterChain.service(FilterChain.java:101) at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106) at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42) at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:286) at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543) at jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:203) at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428) at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)

Aquí hay un script de prueba simple. Notarás que tengo una línea comentada. Esa línea funciona sin ErrorList pero arroja un error (como debería). Estoy intentando que el método funcione sin lanzar el error:

<cftry> <cfsilent> <cfparam name="form.TestField" default="" type="string" /> <cfset Esapi = CreateObject("java", "org.owasp.esapi.ESAPI") /> <cfset EsapiEncoder = Esapi.encoder() /> <cfset EsapiValidator = Esapi.validator() /> <cfset Clean = StructNew() /> <cfset Clean.Css = EsapiEncoder.encodeForCss(form.TestField) /> <cfset Clean.Html = EsapiEncoder.encodeForHtml(form.TestField) /> <cfset Clean.HtmlAttribute = EsapiEncoder.encodeForHtmlAttribute(form.TestField) /> <cfset Clean.JavaScript = EsapiEncoder.encodeForJavaScript(form.TestField) /> <cfset Clean.Url = EsapiEncoder.encodeForUrl(form.TestField) /> <cfset Clean.Xml = EsapiEncoder.encodeForXml(form.TestField) /> <cfset ErrorList = CreateObject("java", "org.owasp.esapi.ValidationErrorList") /> <cfset Valid = StructNew() /> <cfset Valid.Input = EsapiValidator.getValidInput("Test Field", form.TestField, "SafeString", 128, false, true, ErrorList) /> <!---<cfset Valid.Input = EsapiValidator.getValidInput("Test Field", form.TestField, "SafeString", 128, false, true) />---> </cfsilent> <!DOCTYPE HTML> <head> <meta charset=''UTF-8'' /> <title>ESAPI Test</title> </head> <body> <div> <h3>ESAPI Test</h3> <cfoutput> <form name="frmtest" id="frmtest" action="#cgi.script_name#" method="post"> <p>Enter text to test:</p> <p><input type="text" name="TestField" id="TestField" size="64" maxlength="128" value="#Clean.HtmlAttribute#" /></p> <p><input type="submit" name="submit" id="submit" value=" Submit " /></p> </form> </cfoutput> <hr /> <cfdump var="#Clean#" label="Clean Structure" /> <hr /> <cfdump var="#Valid#" label="Valid Structure" /> </div> </body> </html> <cfcatch type="any"> <hr /> <div> <h3>ERROR</h3> <cfdump var="#cfcatch#" label="Error" /> </div> </cfcatch> </cftry>

Cuando ejecuto este script con datos "válidos" funciona bien (no se arrojan errores). Si ingreso un carácter "inválido", obtengo la excepción de puntero nulo.

Ejemplo de datos "válidos": this is a safe string 0123456789
Ejemplo de datos "no válidos": this is a safe string 0123456789- (observe el guión al final)

Aquí hay un enlace a la documentación para el método validator.getValidInput que estoy tratando de implementar .

Aquí hay un enlace a la documentación que muestra lo que estoy tratando de implementar .

Por lo que vale, las "reglas" de validación se definen en el archivo validation.properties que viene con ColdFusion. Ese archivo se encuentra en el directorio {cfusion lib}. Aquí están los contenidos de ese archivo de mi servidor:

# The ESAPI validator does many security checks on input, such as canonicalization # and whitelist validation. Note that all of these validation rules are applied *after* # canonicalization. Double-encoded characters (even with different encodings involved, # are never allowed. # # To use: # # First set up a pattern below. You can choose any name you want, prefixed by the word # "Validation." For example: # Validation.Email=^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+//.[a-zA-Z]{2,4}$ # # Then you can validate in your code against the pattern like this: # ESAPI.validator().isValidInput("User Email", input, "Email", maxLength, allowNull); # Where maxLength and allowNull are set for you needs, respectively. # # But note, when you use boolean variants of validation functions, you lose critical # canonicalization. It is preferable to use the "get" methods (which throw exceptions) and # and use the returned user input which is in canonical form. Consider the following: # # try { # someObject.setEmail(ESAPI.validator().getValidInput("User Email", input, "Email", maxLength, allowNull)); # 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]?)$ Validator.URL=^(ht|f)tp(s?)//://////[0-9a-zA-Z]([-.//w]*[0-9a-zA-Z])*(:(0-9)*)*(///?)([a-zA-Z0-9//-//.//?//,//://'/////////+=&amp;%//$#_]*)?$ Validator.CreditCard=^(//d{4}[- ]?){3}//d{4}$ Validator.SSN=^(?!000)([0-6]//d{2}|7([0-6]//d|7[012]))([ -]?)(?!00)//d//d//3(?!0000)//d{4}$ Validator.CFContainerID=^[//p{Alnum}_//-//.:]+$ Validator.GOOGLEMAPAPI=^[//p{Alnum}_//+=/////-]+$ Validator.CFFORMSCRIPTSRC=^[^//*//?/"''<>|%]*$

Supongo que la idea es agregar reglas a este archivo para sus propias aplicaciones.

¿Alguien ha conseguido que el método validator.getValidInput() funcione en lotes (grupos de intentos de validación)?


Actualización 1

Noté que lo siguiente se está escribiendo en mi cfusion-out.log en el servidor cada vez que obtengo la excepción del puntero nulo. Me lleva a creer que está funcionando hasta cierto punto, pero luego obtiene un puntero nulo al intentar asignar la excepción de validación:

06/25 16:08:14 [jrpp-3225] WARN [SECURITY FAILURE Anonymous:null@unknown -> /IntrusionDetector] Invalid input: context=Test Field, type(SafeString)=^[./p{Alnum}/p{Space}]{0,1024}$, input=this is a safe string 0123456789- org.owasp.esapi.errors.ValidationException: Test Field: Invalid input. Please conform to regex ^[./p{Alnum}/p{Space}]{0,1024}$ with a maximum length of 128 at org.owasp.esapi.reference.validation.StringValidationRule.checkWhitelist(StringValidationRule.java:144) at org.owasp.esapi.reference.validation.StringValidationRule.checkWhitelist(StringValidationRule.java:160) at org.owasp.esapi.reference.validation.StringValidationRule.getValid(StringValidationRule.java:284) at org.owasp.esapi.reference.DefaultValidator.getValidInput(DefaultValidator.java:199) at org.owasp.esapi.reference.DefaultValidator.getValidInput(DefaultValidator.java:236) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at coldfusion.runtime.StructBean.invoke(StructBean.java:508) at coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2393) at cftest2ecfm989071068.runPage(D:/Web/internet/fboc/test.cfm:19) at coldfusion.runtime.CfJspPage.invoke(CfJspPage.java:231) at coldfusion.tagext.lang.IncludeTag.doStartTag(IncludeTag.java:416) at coldfusion.runtime.CfJspPage._emptyTcfTag(CfJspPage.java:2722) at cfApplication2ecfc1705903666$funcONREQUEST.runFunction(D:/Web/internet/fboc/Application.cfc:70) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472) at coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405) at coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368) at coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55) at coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:491) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:337) at coldfusion.runtime.AppEventInvoker.invoke(AppEventInvoker.java:88) at coldfusion.runtime.AppEventInvoker.onRequest(AppEventInvoker.java:280) at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:356) at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:48) at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40) at coldfusion.filter.PathFilter.invoke(PathFilter.java:94) at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:70) at coldfusion.filter.BrowserDebugFilter.invoke(BrowserDebugFilter.java:79) at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28) at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38) at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:46) at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38) at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22) at coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62) at coldfusion.filter.RequestThrottleFilter.invoke(RequestThrottleFilter.java:126) at coldfusion.CfmServlet.service(CfmServlet.java:201) at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89) at jrun.servlet.FilterChain.doFilter(FilterChain.java:86) at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42) at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46) at jrun.servlet.FilterChain.doFilter(FilterChain.java:94) at jrun.servlet.FilterChain.service(FilterChain.java:101) at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106) at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42) at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:286) at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543) at jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:203) at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428) at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)


Actualización 2

He estado investigando la implementación de Damon Miller de los métodos ESAPI de OWASP para ColdFusion. Noté en su código que no llama al método getValidInput() con el atributo ValidationErrorList . Más bien escribió el código para detectar el error generado y luego agregar el error a la lista él mismo. Hmmm? Pensé que se suponía que el método haría eso por ti ???

Como un aparte, estoy tratando de no usar una biblioteca como la suya para evitar la hinchazón adicional que no necesito.

Extracto de su código:

if(structKeyExists( arguments, "errorList" )) { try { return getValidInput( arguments.context, arguments.input, arguments.type, arguments.maxLength, arguments.allowNull ); } catch(esapi4cf.org.owasp.esapi.errors.ValidationException e) { arguments.errorList.addError( arguments.context, e ); } return arguments.input; } else { ...


Esto parece ser un error en la implementación de ColdFusion de ESAPI: tenemos pruebas de cobertura completa del método getValidInput en su conjunto de pruebas unitarias para ESAPI que demuestran que el método funciona según lo anunciado.

Basado en su segunda actualización anterior, supongo que en el código de implementación de CF hay una variable no inicializada a la que se accede (quizás errorList no se haya inicializado en este contexto)

Soy el líder del proyecto OAPASP ESAPI y estoy muy familiarizado con este código en ESAPI, pero no soy desarrollador de CF y no he visto todo el código de implementación para CF9.

** Editar **

Para que los métodos de validación funcionen en lote utilizando ColdFusion, se requiere una llamada al método init() para la clase org.owasp.esapi.ValidationErrorList antes de llamar a los métodos del validator . Agregue la siguiente línea al script de prueba y funcionará:

<cfset ErrorList = ErrorList.init() />

En contexto:

<cfset ErrorList = CreateObject("java", "org.owasp.esapi.ValidationErrorList") /> <cfset ErrorList = ErrorList.init() /> <cfset Valid.TestField = EsapiValidator.getValidInput("Test Field", form.TestField, "SafeString", 128, true, true, ErrorList) />

Ahora cuando se ingresa una entrada no válida, el error se agregará a la variable ErrorList lugar de arrojar un error.