Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to implement the OWASP ESAPI validator with groups of validation attempts in ColdFusion?
    primarykey
    data
    text
    <p>I have been playing around with the OWASP ESAPI utilities that are included with ColdFusion 9. <a href="http://www.petefreitag.com/item/788.cfm" rel="nofollow">ColdFusion's Builtin Enterprise Security API</a>. The <code>encoder</code> utilities are pretty straight forward and I believe I have them working fine. My problem is with the <code>validator</code> utilities.</p> <p>I can get them to work <em>singly</em>. That is, if I call the <code>validator.getValidInput()</code> method with "invalid" data it will throw an error that I can catch. However, when I try to call the <code>validator</code> method in <em>batch</em> I get a null pointer exception. By <em>batch</em> I mean attempting to execute groups of validation attempts. This is supposed to work by passing the <code>validator.getValidInput()</code> method a <code>ValidationErrorList</code> parameter which should tell it NOT to throw an error but instead just add the error to the error list. I cannot get it to work in this mode. My best attempt is giving me a null pointer exception.</p> <p>Here is the specific error:</p> <pre><code>java.lang.NullPointerException </code></pre> <p>With this stack trace:</p> <pre><code>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) </code></pre> <p>Here is a simple test script. You will notice that I have one line commented out. That line works without the <code>ErrorList</code> but throws an error (as it should). I am trying to get the method to work without throwing the error:</p> <pre><code>&lt;cftry&gt; &lt;cfsilent&gt; &lt;cfparam name="form.TestField" default="" type="string" /&gt; &lt;cfset Esapi = CreateObject("java", "org.owasp.esapi.ESAPI") /&gt; &lt;cfset EsapiEncoder = Esapi.encoder() /&gt; &lt;cfset EsapiValidator = Esapi.validator() /&gt; &lt;cfset Clean = StructNew() /&gt; &lt;cfset Clean.Css = EsapiEncoder.encodeForCss(form.TestField) /&gt; &lt;cfset Clean.Html = EsapiEncoder.encodeForHtml(form.TestField) /&gt; &lt;cfset Clean.HtmlAttribute = EsapiEncoder.encodeForHtmlAttribute(form.TestField) /&gt; &lt;cfset Clean.JavaScript = EsapiEncoder.encodeForJavaScript(form.TestField) /&gt; &lt;cfset Clean.Url = EsapiEncoder.encodeForUrl(form.TestField) /&gt; &lt;cfset Clean.Xml = EsapiEncoder.encodeForXml(form.TestField) /&gt; &lt;cfset ErrorList = CreateObject("java", "org.owasp.esapi.ValidationErrorList") /&gt; &lt;cfset Valid = StructNew() /&gt; &lt;cfset Valid.Input = EsapiValidator.getValidInput("Test Field", form.TestField, "SafeString", 128, false, true, ErrorList) /&gt; &lt;!---&lt;cfset Valid.Input = EsapiValidator.getValidInput("Test Field", form.TestField, "SafeString", 128, false, true) /&gt;---&gt; &lt;/cfsilent&gt; &lt;!DOCTYPE HTML&gt; &lt;head&gt; &lt;meta charset='UTF-8' /&gt; &lt;title&gt;ESAPI Test&lt;/title&gt; &lt;/head&gt; &lt;body&gt; &lt;div&gt; &lt;h3&gt;ESAPI Test&lt;/h3&gt; &lt;cfoutput&gt; &lt;form name="frmtest" id="frmtest" action="#cgi.script_name#" method="post"&gt; &lt;p&gt;Enter text to test:&lt;/p&gt; &lt;p&gt;&lt;input type="text" name="TestField" id="TestField" size="64" maxlength="128" value="#Clean.HtmlAttribute#" /&gt;&lt;/p&gt; &lt;p&gt;&lt;input type="submit" name="submit" id="submit" value=" Submit " /&gt;&lt;/p&gt; &lt;/form&gt; &lt;/cfoutput&gt; &lt;hr /&gt; &lt;cfdump var="#Clean#" label="Clean Structure" /&gt; &lt;hr /&gt; &lt;cfdump var="#Valid#" label="Valid Structure" /&gt; &lt;/div&gt; &lt;/body&gt; &lt;/html&gt; &lt;cfcatch type="any"&gt; &lt;hr /&gt; &lt;div&gt; &lt;h3&gt;ERROR&lt;/h3&gt; &lt;cfdump var="#cfcatch#" label="Error" /&gt; &lt;/div&gt; &lt;/cfcatch&gt; &lt;/cftry&gt; </code></pre> <p>When I run this script with "valid" data it works fine (no errors thrown). If I enter an "invalid" character then I get the null pointer exception.</p> <p>Example of "valid" data: <code>this is a safe string 0123456789</code><br> Example of "invalid" data: <code>this is a safe string 0123456789-</code> (notice the hyphen at the end)</p> <p><a href="http://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/org/owasp/esapi/reference/DefaultValidator.html#getValidInput%28java.lang.String,%20java.lang.String,%20java.lang.String,%20int,%20boolean,%20org.owasp.esapi.ValidationErrorList%29" rel="nofollow">Here is a link to the documentation for the validator.getValidInput method that I am trying to implement</a>.</p> <p><a href="http://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/org/owasp/esapi/ValidationErrorList.html" rel="nofollow">Here is a link to the documentation that shows what I am trying to implement</a>.</p> <p>For what it's worth, the validation "rules" are defined in the <code>validation.properties</code> file that comes with ColdFusion. That file is located in the {cfusion lib} directory. Here are the contents of that file from my server:</p> <pre><code># 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;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=^[^\\*\\?\"'&lt;&gt;|%]*$ </code></pre> <p>I presume that the idea is to add rules to this file for your own applications.</p> <p>Has anyone gotten the <code>validator.getValidInput()</code> method to work in <em>batch</em> (groups of validation attempts)?</p> <p><br> <strong>Update 1</strong></p> <p>I noticed that the following is being written to my <code>cfusion-out.log</code> on the server every time I get the null pointer exception. It leads me to believe that it is working to a point but then gets a null pointer while attempting to assign the validation exception:</p> <pre><code>06/25 16:08:14 [jrpp-3225] WARN [SECURITY FAILURE Anonymous:null@unknown -&gt; /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) </code></pre> <p><br> <strong>Update 2</strong></p> <p>I have been digging through <a href="https://github.com/damonmiller/esapi4cf/blob/master/esapi4cf/org/owasp/esapi/reference/DefaultValidator.cfc" rel="nofollow">Damon Miller's implementation of the OWASP ESAPI</a> methods for ColdFusion. I noticed in his code that he does not call the <code>getValidInput()</code> method with the <code>ValidationErrorList</code> attribute. Rather he wrote the code to catch the generated error and then add the error to the list himself. Hmmm? I thought the method was supposed to do that for you????</p> <p>As an aside, I am trying not to use a library such as his to avoid the additional bloat that I do not need.</p> <p>Excerpt from his code:</p> <pre><code>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 { ... </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload