Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #2 from dcepler/master

Fixed Canonicalize, added Functions, and Unit Testing
  • Loading branch information...
commit b5caa475b06d17e6d59ab9bb03f5e9095399a3aa 2 parents a0f68e9 + 8d83447
@misterdai authored
View
36 README
@@ -8,8 +8,8 @@
Author: David "Mister Dai" Boyer
Website: http://misterdai.wordpress.com
-Version: 0.6
-Contributors: Henry Ho
+Version: 0.7
+Contributors: Henry Ho, David Epler
----------------------
| Description |
@@ -30,6 +30,12 @@ aren't loaded if the version already supports them.
Functions should work in at least ColdFusion 8+. Where possible I've tried to
avoid using newer syntax or functions
+If ColdFusion is patched with APSB11-04 or higher, ESAPI is available for
+Encode and Decode functions.
+
+APSB11-04+ installs ESAPI 1.4.4 for CF8.0.x and ESAPI 2.0_rc10 for CF9.0.0/1
+CF9.0.2 already has ESAPI 2.0_rc10 installed
+
----------------------
| Usage |
----------------------
@@ -44,21 +50,41 @@ there to make use of them.
| Functions |
----------------------
- * Backported from CF10
+ * Backported from CF10 for CF9 and CF8
ArraySlice
CallStackDump
CallStackGet
- Canoncicalize
+ Canonicalize
CsrfGenerateToken
CsrfVerifyToken
+ DecodeForHTML (David Epler) [requires ESAPI 2.0+]
+ DecodeFromURL (David Epler)
EncodeForCSS (Henry Ho)
EncodeForHTML
EncodeForHTMLAttribute (Henry Ho)
EncodeForJavaScript (Henry Ho)
EncodeForURL (Henry Ho)
+ EncodeForXML (David Epler)
GetApplicationMetadata
+ HMac (David Epler)
IsClosure
ReEscape
SessionInvalidate
- SessionStartTime
+ SessionStartTime
+
+ * Backported from CF9 for CF8
+ throw (David Epler) [required for DecodeFromURL]
+
+----------------------
+| Unit Tests |
+----------------------
+
+Unit tests were created with MXUnit 2.1.1
+
+ * As written (of course) CF10 passes them all
+ * CF9.0.x with APSB11-04+ - 13 success, 0 error, 1 failure
+ * Failure is due to ESAPI version difference
+ * CF8.0.x with APSB11-04+ - 9 success, 1 error, 4 failure
+ * Failure and Error is due to ESAPI version difference
+
View
251 cf10.cfm
@@ -196,81 +196,226 @@
<cfreturn ReReplace(arguments.string, "([\[\]\(\)\^\$\.\+\?\*\-\|])", "\$1", "all") />
</cffunction>
-<cffunction name="Canoncicalize" output="false" returntype="string">
- <cfargument name="inputString" type="string" required="true" />
- <cfargument name="restrictMultiple" type="boolean" required="true" />
- <cfargument name="restrictMixed" type="boolean" required="true" />
- <cfreturn CreateObject("java", "org.owasp.esapi.ESAPI").encoder().canonicalize(arguments.string, arguments.restrictMultiple, arguments.restrictMixed) />
+<cffunction name="Canonicalize" output="false" returntype="string" hint="Canonicalize or decode the input string, returns Decoded form of input string">
+ <cfargument name="inputString" type="string" required="true" hint="Required. String to be encode" />
+ <cfargument name="restrictMultiple" type="boolean" required="true" hint="Required. If set to true, multiple encoding is restricted" />
+ <cfargument name="restrictMixed" type="boolean" required="true" hint="Required. If set to true, mixed encoding is restricted (Ignored with ESAPI <2.0.0)" />
+
+ <cfscript>
+ var lc = StructNew();
+ var canonicalizedString = "";
+
+ lc.encoder = CreateObject("java", "org.owasp.esapi.ESAPI").encoder();
+
+ /*
+ * ESAPI 2.0.0+ (r1630) supports String canonicalize( String input, boolean restrictMultiple, boolean restrictMixed )
+ * unfortunately APSB11-04+ installs ESAPI 1.4.4 for CF8.0.x and ESAPI 2.0_rc10 for CF9.0.x and CF9.0.2 which don't have it
+ * try ESAPI 2.0.0+ call then fall back
+ */
+ try {
+ canonicalizedString = lc.encoder.canonicalize(JavaCast("string", arguments.inputString), JavaCast("boolean", arguments.restrictMultiple), JavaCast("boolean", arguments.restrictMixed));
+ }
+ catch(Any excpt) {
+ canonicalizedString = lc.encoder.canonicalize(JavaCast("string", arguments.inputString), JavaCast("boolean", arguments.restrictMultiple));
+ }
+
+ return canonicalizedString;
+ </cfscript>
</cffunction>
-<cffunction name="EncodeForCSS" output="false" returntype="string">
- <cfargument name="inputString" type="string" required="true" />
- <cfargument name="strict" type="boolean" required="false" default="false" />
- <cfscript>
- var lc = StructNew();
- lc.encoder = CreateObject("java", "org.owasp.esapi.ESAPI").encoder();
- return lc.encoder.encodeForCSS(lc.encoder.canoncicalize(arguments.inputString, arguments.strict));
- </cfscript>
+<cffunction name="EncodeForCSS" output="false" returntype="string" hint="Encodes the input string for use in CSS, returns Encoded string">
+ <cfargument name="inputString" type="string" required="true" hint="Required. String to encode" />
+ <cfargument name="strict" type="boolean" default="false" hint="Optional. If set to true, restricts multiple and mixed encoding" />
+
+ <cfscript>
+ var lc = StructNew();
+ var encodedString = "";
+
+ lc.encoder = CreateObject("java", "org.owasp.esapi.ESAPI").encoder();
+ encodedString = lc.encoder.encodeForCSS(lc.encoder.canonicalize(JavaCast("string", arguments.inputString), JavaCast("boolean", arguments.strict)));
+
+ return encodedString;
+ </cfscript>
</cffunction>
-<cffunction name="EncodeForHTML" output="false" returntype="string">
- <cfargument name="inputString" type="string" required="true" />
- <cfargument name="strict" type="boolean" required="false" default="false" />
- <cfscript>
- var lc = StructNew();
- lc.encoder = CreateObject("java", "org.owasp.esapi.ESAPI").encoder();
- return lc.encoder.encodeForHTML(lc.encoder.canoncicalize(arguments.inputString, arguments.strict));
- </cfscript>
+<cffunction name="DecodeForHTML" output="false" returntype="string" hint="Decodes an HTML encoded string, returns Decoded HTML string">
+ <cfargument name="inputString" type="string" required="true" hint="Required. Encoded string to decode" />
+
+ <cfscript>
+ var lc = StructNew();
+ var decodedString = "";
+
+ lc.encoder = CreateObject("java", "org.owasp.esapi.ESAPI").encoder();
+ decodedString = lc.encoder.DecodeForHTML(JavaCast("string", arguments.inputString));
+
+ return decodedString;
+ </cfscript>
</cffunction>
-<cffunction name="EncodeForHTMLAttribute" output="false" returntype="string">
- <cfargument name="inputString" type="string" required="true" />
- <cfargument name="strict" type="boolean" required="false" default="false" />
- <cfscript>
- var lc = StructNew();
- lc.encoder = CreateObject("java", "org.owasp.esapi.ESAPI").encoder();
- return lc.encoder.encodeForHTMLAttribute(lc.encoder.canoncicalize(arguments.inputString, arguments.strict));
- </cfscript>
+<cffunction name="EncodeForHTML" output="false" returntype="string" hint="Encodes the input string for use in HTML, returns Encoded string">
+ <cfargument name="inputString" type="string" required="true" hint="Required. String to encode" />
+ <cfargument name="strict" type="boolean" default="false" hint="Optional. If set to true, restricts multiple and mixed encoding" />
+
+ <cfscript>
+ var lc = StructNew();
+ var encodedString = "";
+
+ lc.encoder = CreateObject("java", "org.owasp.esapi.ESAPI").encoder();
+ encodedString = lc.encoder.encodeForHTML(lc.encoder.canonicalize(JavaCast("string", arguments.inputString), JavaCast("boolean", arguments.strict)));
+
+ return encodedString;
+ </cfscript>
</cffunction>
-<cffunction name="EncodeForJavaScript" output="false" returntype="string">
- <cfargument name="inputString" type="string" required="true" />
- <cfargument name="strict" type="boolean" required="false" default="false" />
- <cfscript>
- var lc = StructNew();
- lc.encoder = CreateObject("java", "org.owasp.esapi.ESAPI").encoder();
- return lc.encoder.encodeForJavaScript(lc.encoder.canoncicalize(arguments.inputString, arguments.strict));
- </cfscript>
+<cffunction name="EncodeForHTMLAttribute" output="false" returntype="string" hint="Encodes the input string for use in HTML attribute, returns Encoded string">
+ <cfargument name="inputString" type="string" required="true" hint="Required. String to encode" />
+ <cfargument name="strict" type="boolean" default="false" hint="Optional. If set to true, restricts multiple and mixed encoding" />
+
+ <cfscript>
+ var lc = StructNew();
+ var encodedString = "";
+
+ lc.encoder = CreateObject("java", "org.owasp.esapi.ESAPI").encoder();
+ encodedString = lc.encoder.encodeForHTMLAttribute(lc.encoder.canonicalize(JavaCast("string", arguments.inputString), JavaCast("boolean", arguments.strict)));
+
+ return encodedString;
+ </cfscript>
</cffunction>
-<cffunction name="EncodeForURL" output="false" returntype="string">
- <cfargument name="inputString" type="string" required="true" />
- <cfargument name="strict" type="boolean" required="false" default="false" />
- <cfscript>
- var lc = StructNew();
- lc.encoder = CreateObject("java", "org.owasp.esapi.ESAPI").encoder();
- return lc.encoder.encodeForURL(lc.encoder.canoncicalize(arguments.inputString, arguments.strict));
- </cfscript>
+<cffunction name="EncodeForJavaScript" output="false" returntype="string" hint="Encodes the input string for use in JavaScript, returns Encoded string">
+ <cfargument name="inputString" type="string" required="true" hint="Required. String to encode" />
+ <cfargument name="strict" type="boolean" default="false" hint="Optional. If set to true, restricts multiple and mixed encoding" />
+
+ <cfscript>
+ var lc = StructNew();
+ var encodedString = "";
+
+ lc.encoder = CreateObject("java", "org.owasp.esapi.ESAPI").encoder();
+ encodedString = lc.encoder.encodeForJavaScript(lc.encoder.canonicalize(JavaCast("string", arguments.inputString), JavaCast("boolean", arguments.strict)));
+
+ return encodedString;
+ </cfscript>
+</cffunction>
+
+
+<cffunction name="DecodeFromURL" output="false" returntype="string" hint="">
+ <cfargument name="inputString" type="string" required="true" hint="Required. String to decode" />
+
+ <cfscript>
+ var lc = StructNew();
+
+ local.encoding = createObject("java", "java.lang.System").getProperty("file.encoding");
+ try {
+ return createObject("java", "java.net.URLDecoder").decode(javaCast("string", canonicalize(arguments.inputString, false, false)), local.encoding);
+ }
+ // throw the same errors as CF10
+ catch(java.io.UnsupportedEncodingException ex) {
+ // Character encoding not supported
+ throw("There was an error while encoding.", "Application", "For more details check logs.");
+ }
+ catch(java.lang.Exception e) {
+ // Problem URL decoding input
+ throw("There was an error while encoding.", "Application", "For more details check logs.");
+ }
+ </cfscript>
+
+ </cffunction>
+
+
+<cffunction name="EncodeForURL" output="false" returntype="string" hint="Encodes the input string for use in URLs, returns Encoded string">
+ <cfargument name="inputString" type="string" required="true" hint="Required. String to encode" />
+ <cfargument name="strict" type="boolean" default="false" hint="Optional. If set to true, restricts multiple and mixed encoding" />
+
+ <cfscript>
+ var lc = StructNew();
+ var encodedString = "";
+
+ lc.encoder = CreateObject("java", "org.owasp.esapi.ESAPI").encoder();
+ encodedString = lc.encoder.encodeForURL(lc.encoder.canonicalize(JavaCast("string", arguments.inputString), JavaCast("boolean", arguments.strict)));
+
+ return encodedString;
+ </cfscript>
+</cffunction>
+
+<cffunction name="EncodeForXML" output="false" returntype="string" hint="Encodes the input string for use in XML, returns Encoded string">
+ <cfargument name="inputString" type="string" required="true" hint="Required. String to encode" />
+ <cfargument name="strict" type="boolean" default="false" hint="Optional. If set to true, restricts multiple and mixed encoding" />
+
+ <cfscript>
+ var lc = StructNew();
+ var encodedString = "";
+
+ lc.encoder = CreateObject("java", "org.owasp.esapi.ESAPI").encoder();
+ encodedString = lc.encoder.encodeForXML(lc.encoder.canonicalize(JavaCast("string", arguments.inputString), JavaCast("boolean", arguments.strict)));
+
+ return encodedString;
+ </cfscript>
+</cffunction>
+
+<!---
+Based upon code from http://www.coldfusiondeveloper.com.au/go/note/2008/01/18/hmac-sha1-using-java/
+ --->
+<cffunction name="HMac" output="false" returntype="string" description="Creates Hash-based Message Authentication Code for the given string or byte array based on the algorithm and encoding">
+ <cfargument name="message" type="any" required="true" hint="can be string or byte array" />
+ <cfargument name="key" type="any" required="true" hint="can be string or byte array" />
+ <cfargument name="algorithm" type="string" default="HMACMD5" hint="HMACMD5, HMACSHA1, HMACSHA256, HMACSHA384, HMACSHA512, HMACRIPEMD160, HMACSHA224" />
+ <cfargument name="encoding" type="string" default="#createObject('java', 'java.lang.System').getProperty('file.encoding')#" hint="encoding to use" />
+
+ <cfset var byteArray = {} />
+ <cfset var javaObject = {} />
+
+ <cfif NOT IsBinary(arguments.message)>
+ <cfset byteArray.Message = CharsetDecode(arguments.message, arguments.encoding) />
+ <cfelse>
+ <cfset byteArray.Message = arguments.message />
+ </cfif>
+
+ <cfif NOT IsBinary(arguments.key)>
+ <cfset byteArray.Key = CharsetDecode(arguments.key, arguments.encoding) />
+ <cfelse>
+ <cfset byteArray.Key = arguments.key />
+ </cfif>
+
+ <cfset javaObject.Key = createObject("java","javax.crypto.spec.SecretKeySpec").init(byteArray.Key, arguments.algorithm) />
+ <cfset javaObject.Mac = createObject("java","javax.crypto.Mac") />
+
+ <cfset javaObject.Mac = javaObject.Mac.getInstance(arguments.algorithm) />
+ <cfset javaObject.Mac.init(javaObject.Key) />
+
+ <cfreturn BinaryEncode(javaObject.Mac.doFinal(byteArray.Message), "hex") />
</cffunction>
<!---
- ESAPI library requires CF9.0.1+ or have the library added manually.
+ Hopefully, ColdFusion is patched and therefore ESAPI is available
+ APSB11-04+ installs ESAPI 1.4.4 for CF8.0.x and ESAPI 2.0_rc10 for CF9.0.x and CF9.0.2
- Function tags cannot be wrapped in "if" statements to exclude creation.
- Instead, test for the required ESAPI class and destroy if missing.
+ Test for ESAPI existance by calling canonicalize, if exception is thrown
+ remove the functions that are dependent upon it
--->
-<cfset cfbackport.temp = ArrayNew(1) />
<cftry>
- <!--- If the Java class doesn't exist, catch the exception --->
- <cfset cfbackport.temp.getClass().forName("org.owasp.esapi.ESAPI", false, JavaCast("null", "")) />
+ <cfset canonicalize("", false, false) />
+
<cfcatch type="any">
- <cfset StructDelete(variables, "Canoncicalize") />
+ <cfset StructDelete(variables, "Canonicalize") />
+ <cfset StructDelete(variables, "DecodeFromURL") />
<cfset StructDelete(variables, "EncodeForCSS") />
<cfset StructDelete(variables, "EncodeForHTML") />
<cfset StructDelete(variables, "EncodeForHTMLAttribute") />
<cfset StructDelete(variables, "EncodeForJavaScript") />
<cfset StructDelete(variables, "EncodeForURL") />
+ <cfset StructDelete(variables, "EncodeForXML") />
+ </cfcatch>
+</cftry>
+
+<!---
+ ESAPI 1.4.4 does not have DecodeForHTML
+ --->
+<cftry>
+ <cfset decodeForHTML("") />
+
+ <cfcatch type="any">
+ <cfset StructDelete(variables, "DecodeForHTML") />
</cfcatch>
</cftry>
-<cfset StructDelete(variables, "cfbackport") />
+<cfset StructDelete(variables, "cfbackport") />
View
19 cf9.cfm
@@ -0,0 +1,19 @@
+
+<!---
+Based upon http://cflib.org/udf/Throw, modified to match CF9 throw() argument order
+--->
+<cffunction returnType="void" name="throw" output="false" hint="CFML Throw wrapper">
+ <cfargument name="message" type="string" default="" hint="Message for Exception">
+ <cfargument name="type" type="string" default="Application" hint="Type for Exception">
+ <cfargument name="detail" type="string" default="" hint="Detail for Exception">
+ <cfargument name="errorCode" type="string" default="" hint="Error Code for Exception">
+ <cfargument name="extendedInfo" type="string" default="" hint="Extended Info for Exception">
+ <cfargument name="object" type="any" hint="Object for Exception">
+
+ <cfif NOT IsDefined("arguments.object")>
+ <cfthrow message="#arguments.message#" type="#arguments.type#" detail="#arguments.detail#" errorCode="#arguments.errorCode#" extendedInfo="#arguments.extendedInfo#">
+ <cfelse>
+ <cfthrow object="#arguments.object#">
+ </cfif>
+
+</cffunction>
View
3  cfbackport.cfm
@@ -4,6 +4,9 @@
cfbackport.major = ListFirst(server.coldfusion.productVersion);
cfbackport.minor = ListFirst(Replace(ListDeleteAt(server.coldfusion.productVersion, 1), ",", "."));
</cfscript>
+ <cfif cfbackport.major lt 9>
+ <cfinclude template="cf9.cfm" />
+ </cfif>
<cfif cfbackport.major lt 10>
<cfinclude template="cf10.cfm" />
</cfif>
View
7 test/Application.cfc
@@ -0,0 +1,7 @@
+<cfcomponent output="false">
+
+ <cfscript>
+ this.name = "cfbackport" & hash(getCurrentTemplatePath());
+ </cfscript>
+
+</cfcomponent>
View
16 test/TestSuite.cfm
@@ -0,0 +1,16 @@
+<!---<cfsetting showdebugoutput="true" requesttimeout="180"/>--->
+
+<cfscript>
+ startTime = getTickCount();
+ results = createObject("component", "mxunit.runner.DirectoryTestSuite").run(expandPath("."), "cfbackport.test");
+</cfscript>
+
+<cfoutput>
+ #results.getResultsOutput("html")#
+ <p>
+ Total Test Time:
+ #(getTickCount() - startTime) / 1000#
+ seconds
+ </p>
+ <br/>
+</cfoutput>
View
404 test/cfbackportTest.cfc
@@ -0,0 +1,404 @@
+<cfcomponent displayname="cfbackportTest" extends="mxunit.framework.TestCase">
+
+ <cfinclude template="../cfbackport.cfm" />
+
+ <cffunction name="setUp" access="public" returntype="void" output="false">
+
+ <cfscript>
+ // none
+ </cfscript>
+
+ </cffunction>
+
+ <cffunction name="tearDown" access="public" returntype="void" output="false">
+
+ <cfscript>
+ // none
+ </cfscript>
+
+ </cffunction>
+
+<!---
+ Tests for canonicalize, encodeforHTML, encodeForHTMLAttribute, encodeForCSS, encodeForJavaScript, encodeForXML
+ based from CFESAPI EncoderTest.cfc (https://github.com/damonmiller/cfesapi/raw/master/test/org/owasp/esapi/reference/EncoderTest.cfc)
+--->
+
+ <cffunction name="testCanonicalize" access="public" returntype="void" output="false" hint="Test of canonicalize">
+ <cfset var local = {}/>
+
+ <cfscript>
+ // Test null paths
+ assertEquals("", canonicalize("", true, true));
+ assertEquals("", canonicalize("", true, false));
+ assertEquals("", canonicalize("", false, true));
+ assertEquals("", canonicalize("", false, false));
+
+ // test exception paths
+ assertEquals("%", canonicalize("%25", true, true));
+ assertEquals("%", canonicalize("%25", false, true));
+
+ assertEquals("%", canonicalize("%25", false, false));
+ assertEquals("%F", canonicalize("%25F", false, false));
+ assertEquals("<", canonicalize("%3c", false, false));
+ assertEquals("<", canonicalize("%3C", false, false));
+ assertEquals("%X1", canonicalize("%X1", false, false));
+
+ assertEquals("<", canonicalize("&lt", false, false));
+ assertEquals("<", canonicalize("&LT", false, false));
+ assertEquals("<", canonicalize("&lt;", false, false));
+ assertEquals("<", canonicalize("&LT;", false, false));
+
+ assertEquals("%", canonicalize("&##37;", false, false));
+ assertEquals("%", canonicalize("&##37", false, false));
+ assertEquals("%b", canonicalize("&##37b", false, false));
+
+ assertEquals("<", canonicalize("&##x3c", false, false));
+ assertEquals("<", canonicalize("&##x3c;", false, false));
+ assertEquals("<", canonicalize("&##x3C", false, false));
+ assertEquals("<", canonicalize("&##X3c", false, false));
+ assertEquals("<", canonicalize("&##X3C", false, false));
+ assertEquals("<", canonicalize("&##X3C;", false, false));
+
+ // percent encoding
+ assertEquals("<", canonicalize("%3c", false, false));
+ assertEquals("<", canonicalize("%3C", false, false));
+
+ // html entity encoding
+ assertEquals("<", canonicalize("&##60", false, false));
+ assertEquals("<", canonicalize("&##060", false, false));
+ assertEquals("<", canonicalize("&##0060", false, false));
+ assertEquals("<", canonicalize("&##00060", false, false));
+ assertEquals("<", canonicalize("&##000060", false, false));
+ assertEquals("<", canonicalize("&##0000060", false, false));
+ assertEquals("<", canonicalize("&##60;", false, false));
+ assertEquals("<", canonicalize("&##060;", false, false));
+ assertEquals("<", canonicalize("&##0060;", false, false));
+ assertEquals("<", canonicalize("&##00060;", false, false));
+ assertEquals("<", canonicalize("&##000060;", false, false));
+ assertEquals("<", canonicalize("&##0000060;", false, false));
+ assertEquals("<", canonicalize("&##x3c", false, false));
+ assertEquals("<", canonicalize("&##x03c", false, false));
+ assertEquals("<", canonicalize("&##x003c", false, false));
+ assertEquals("<", canonicalize("&##x0003c", false, false));
+ assertEquals("<", canonicalize("&##x00003c", false, false));
+ assertEquals("<", canonicalize("&##x000003c", false, false));
+ assertEquals("<", canonicalize("&##x3c;", false, false));
+ assertEquals("<", canonicalize("&##x03c;", false, false));
+ assertEquals("<", canonicalize("&##x003c;", false, false));
+ assertEquals("<", canonicalize("&##x0003c;", false, false));
+ assertEquals("<", canonicalize("&##x00003c;", false, false));
+ assertEquals("<", canonicalize("&##x000003c;", false, false));
+ assertEquals("<", canonicalize("&##X3c", false, false));
+ assertEquals("<", canonicalize("&##X03c", false, false));
+ assertEquals("<", canonicalize("&##X003c", false, false));
+ assertEquals("<", canonicalize("&##X0003c", false, false));
+ assertEquals("<", canonicalize("&##X00003c", false, false));
+ assertEquals("<", canonicalize("&##X000003c", false, false));
+ assertEquals("<", canonicalize("&##X3c;", false, false));
+ assertEquals("<", canonicalize("&##X03c;", false, false));
+ assertEquals("<", canonicalize("&##X003c;", false, false));
+ assertEquals("<", canonicalize("&##X0003c;", false, false));
+ assertEquals("<", canonicalize("&##X00003c;", false, false));
+ assertEquals("<", canonicalize("&##X000003c;", false, false));
+ assertEquals("<", canonicalize("&##x3C", false, false));
+ assertEquals("<", canonicalize("&##x03C", false, false));
+ assertEquals("<", canonicalize("&##x003C", false, false));
+ assertEquals("<", canonicalize("&##x0003C", false, false));
+ assertEquals("<", canonicalize("&##x00003C", false, false));
+ assertEquals("<", canonicalize("&##x000003C", false, false));
+ assertEquals("<", canonicalize("&##x3C;", false, false));
+ assertEquals("<", canonicalize("&##x03C;", false, false));
+ assertEquals("<", canonicalize("&##x003C;", false, false));
+ assertEquals("<", canonicalize("&##x0003C;", false, false));
+ assertEquals("<", canonicalize("&##x00003C;", false, false));
+ assertEquals("<", canonicalize("&##x000003C;", false, false));
+ assertEquals("<", canonicalize("&##X3C", false, false));
+ assertEquals("<", canonicalize("&##X03C", false, false));
+ assertEquals("<", canonicalize("&##X003C", false, false));
+ assertEquals("<", canonicalize("&##X0003C", false, false));
+ assertEquals("<", canonicalize("&##X00003C", false, false));
+ assertEquals("<", canonicalize("&##X000003C", false, false));
+ assertEquals("<", canonicalize("&##X3C;", false, false));
+ assertEquals("<", canonicalize("&##X03C;", false, false));
+ assertEquals("<", canonicalize("&##X003C;", false, false));
+ assertEquals("<", canonicalize("&##X0003C;", false, false));
+ assertEquals("<", canonicalize("&##X00003C;", false, false));
+ assertEquals("<", canonicalize("&##X000003C;", false, false));
+ assertEquals("<", canonicalize("&lt", false, false));
+ assertEquals("<", canonicalize("&lT", false, false));
+ assertEquals("<", canonicalize("&Lt", false, false));
+ assertEquals("<", canonicalize("&LT", false, false));
+ assertEquals("<", canonicalize("&lt;", false, false));
+ assertEquals("<", canonicalize("&lT;", false, false));
+ assertEquals("<", canonicalize("&Lt;", false, false));
+ assertEquals("<", canonicalize("&LT;", false, false));
+
+ assertEquals('<script>alert("hello");</script>', canonicalize("%3Cscript%3Ealert%28%22hello%22%29%3B%3C%2Fscript%3E", false, false));
+ assertEquals('<script>alert("hello");</script>', canonicalize("%3Cscript&##x3E;alert%28%22hello&##34%29%3B%3C%2Fscript%3E", false, false));
+
+ </cfscript>
+ </cffunction>
+
+
+ <cffunction access="public" returntype="void" name="testDoubleEncodingCanonicalization" output="false" hint="Test of canonicalize">
+ <cfset var local = {}/>
+
+ <cfscript>
+ // note these examples use the strict=false flag on canonicalize to allow
+ // full decoding without throwing an IntrusionException. Generally, you
+ // should use strict mode as allowing double-encoding is an abomination.
+ // double encoding examples
+ assertEquals("<", canonicalize("&##x26;lt&##59", false, false)); //double entity
+ assertEquals("\", canonicalize("%255c", false, false)); //double percent
+ assertEquals("%", canonicalize("%2525", false, false)); //double percent
+
+ // double encoding with multiple schemes example
+ assertEquals("<", canonicalize("%26lt%3b", false, false)); //first entity, then percent
+ assertEquals("&", canonicalize("&##x25;26", false, false)); //first percent, then entity
+
+ // enforce neither mixed nor multiple encoding detection -should canonicalize but not throw an error
+ assertEquals("< < < < < < <", canonicalize("%26lt; %26lt; &##X25;3c &##x25;3c %2526lt%253B %2526lt%253B %2526lt%253B", false, false));
+
+ // nested encoding examples
+ assertEquals("<", canonicalize("%253c", false, false)); //nested encode % with percent
+ assertEquals("<", canonicalize("%%33%63", false, false)); //nested encode both nibbles with percent
+ assertEquals("<", canonicalize("%%33c", false, false)); // nested encode first nibble with percent
+ assertEquals("<", canonicalize("%3%63", false, false)); //nested encode second nibble with percent
+ assertEquals("<", canonicalize("&&##108;t;", false, false)); //nested encode l with entity
+ assertEquals("<", canonicalize("%2&##x35;3c", false, false)); //triple percent, percent, 5 with entity
+
+ // nested encoding with multiple schemes examples
+ assertEquals("<", canonicalize("&%6ct;", false, false)); // nested encode l with percent
+ assertEquals("<", canonicalize("%&##x33;c", false, false)); //nested encode 3 with entity
+
+ // multiple encoding tests
+ assertEquals("% & <script> <script>", canonicalize("%25 %2526 %26##X3c;script&##x3e; &##37;3Cscript%25252525253e", false, false));
+ assertEquals("< < < < < < <", canonicalize("%26lt; %26lt; &##X25;3c &##x25;3c %2526lt%253B %2526lt%253B %2526lt%253B", false, false));
+
+ </cfscript>
+
+ </cffunction>
+
+
+ <cffunction access="public" returntype="void" name="testCanonicalizationMultipleTrue" output="false" hint="Test of canonicalize">
+ <cfset var local = {}/>
+
+ <cfscript>
+ // enforce multiple but not mixed encoding detection
+ try {
+ canonicalize("%252525253C", true, false);
+ fail("Multiple encoding not detected");
+ }
+ catch(org.owasp.esapi.errors.IntrusionException except) {
+ }
+ </cfscript>
+
+ </cffunction>
+
+
+ <cffunction access="public" returntype="void" name="testCanonicalizationMixedTrue" output="false" hint="Test of canonicalize">
+ <cfset var local = {}/>
+
+ <cfscript>
+ // enforce mixed but not multiple encoding detection
+ try {
+ canonicalize("%25 %2526 %26##X3c;script&##x3e; &##37;3Cscript%25252525253e", false, true);
+ fail("Mixed encoding not detected. Needs ESAPI 2.0.0GA+");
+ }
+ catch(org.owasp.esapi.errors.IntrusionException except) {
+ }
+ </cfscript>
+
+ </cffunction>
+
+
+ <cffunction access="public" returntype="void" name="testCanonicalizationMultipleAndMixedTrue" output="false" hint="Test of canonicalize">
+ <cfset var local = {}/>
+
+ <cfscript>
+ // enforce multiple and mixed encoding detection
+ try {
+ canonicalize("%26lt; %26lt; &##X25;3c &##x25;3c %2526lt%253B %2526lt%253B %2526lt%253B", true, true);
+ fail("Multiple and mixed encoding not detected");
+ }
+ catch(org.owasp.esapi.errors.IntrusionException except) {
+ }
+
+ // test strict mode with both mixed and multiple encoding
+ try {
+ assertEquals("< < < < < < <", canonicalize("%26lt; %26lt; &##X25;3c &##x25;3c %2526lt%253B %2526lt%253B %2526lt%253B", true, true));
+ }
+ catch(org.owasp.esapi.errors.IntrusionException except) {
+ // expected
+ }
+
+ try {
+ assertEquals("<script", canonicalize("%253Cscript", true, true));
+ }
+ catch(org.owasp.esapi.errors.IntrusionException except) {
+ // expected
+ }
+
+ try {
+ assertEquals("<script", canonicalize("&##37;3Cscript", true, true));
+ }
+ catch(org.owasp.esapi.errors.IntrusionException except) {
+ // expected
+ }
+ </cfscript>
+
+ </cffunction>
+
+ <cffunction access="public" returntype="void" name="testDecodeForHTML" output="false" hint="Test of decodeForHTML">
+ <cfset var local = {}/>
+
+ <cfscript>
+ assertEquals("", decodeForHTML(""));
+ assertEquals("<script>", decodeForHTML("&lt;script&gt;"));
+ assertEquals(",.-_ ", decodeForHTML(",.-_ "));
+ assertEquals("!@$%()=+{}[]", decodeForHTML("&##x21;&##x40;&##x24;&##x25;&##x28;&##x29;&##x3d;&##x2b;&##x7b;&##x7d;&##x5b;&##x5d;"));
+ assertEquals("one&two", decodeForHTML("one&amp;two"));
+ </cfscript>
+
+ </cffunction>
+
+
+ <cffunction name="testEncodeForHTML" access="public" returntype="void" output="false" hint="Test of encodeForHTML">
+ <cfset var local = {}/>
+
+ <cfscript>
+ assertEquals("", encodeForHTML(""));
+ // test invalid characters are replaced with spaces
+ assertEquals("a&##xfffd;b&##xfffd;c&##xfffd;d&##xfffd;e&##xfffd;f&##x9;g", encodeForHTML("a" & chr(1) & "b" & chr(4) & "c" & chr(128) & "d" & chr(150) & "e" & chr(159) & "f" & chr(9) & "g"));
+
+ assertEquals("&lt;script&gt;", encodeForHTML("<script>"));
+
+ // CF10 and CF9 return original string
+ // assertEquals("&amp;lt&##x3b;script&amp;gt&##x3b;", encodeForHTML("&lt;script&gt;"));
+
+ assertEquals("&##x21;&##x40;&##x24;&##x25;&##x28;&##x29;&##x3d;&##x2b;&##x7b;&##x7d;&##x5b;&##x5d;", encodeForHTML("!@$%()=+{}[]"));
+ assertEquals("&##x21;&##x40;&##x24;&##x25;&##x28;&##x29;&##x3d;&##x2b;&##x7b;&##x7d;&##x5b;&##x5d;", encodeForHTML("&##33;&##64;&##36;&##37;&##40;&##41;&##61;&##43;&##123;&##125;&##91;&##93;"));
+ assertEquals(",.-_ ", encodeForHTML(",.-_ "));
+ assertEquals("dir&amp;", encodeForHTML("dir&"));
+ assertEquals("one&amp;two", encodeForHTML("one&two"));
+ assertEquals("" & chr(12345) & chr(65533) & chr(1244), "" & chr(12345) & chr(65533) & chr(1244));
+ </cfscript>
+
+ </cffunction>
+
+ <cffunction access="public" returntype="void" name="testEncodeForHTMLAttribute" output="false" hint="Test of encodeForHTMLAttribute">
+ <cfset var local = {}/>
+
+ <cfscript>
+ assertEquals("", encodeForHTMLAttribute(""));
+ assertEquals("&lt;script&gt;", encodeForHTMLAttribute("<script>"));
+ assertEquals(",.-_", encodeForHTMLAttribute(",.-_"));
+ assertEquals("&##x20;&##x21;&##x40;&##x24;&##x25;&##x28;&##x29;&##x3d;&##x2b;&##x7b;&##x7d;&##x5b;&##x5d;", encodeForHTMLAttribute(" !@$%()=+{}[]"));
+ </cfscript>
+
+ </cffunction>
+
+ <cffunction access="public" returntype="void" name="testEncodeForCSS" output="false" hint="Test of encodeForCSS">
+ <cfset var local = {}/>
+
+ <cfscript>
+ assertEquals("\3c script\3e ", encodeForCSS("<script>"));
+ assertEquals("\21 \40 \24 \25 \28 \29 \3d \2b \7b \7d \5b \5d ", encodeForCSS("!@$%()=+{}[]"));
+ </cfscript>
+
+ </cffunction>
+
+ <cffunction access="public" returntype="void" name="testEncodeForJavascript" output="false" hint="Test of encodeForJavaScript">
+ <cfset var local = {}/>
+
+ <cfscript>
+ assertEquals("", encodeForJavaScript(""));
+ assertEquals("\x3Cscript\x3E", encodeForJavaScript("<script>"));
+ assertEquals(",.\x2D_\x20", encodeForJavaScript(",.-_ "));
+ assertEquals("\x21\x40\x24\x25\x28\x29\x3D\x2B\x7B\x7D\x5B\x5D", encodeForJavaScript("!@$%()=+{}[]"));
+ assertEquals( "\x00", encodeForJavaScript("\0"));
+ assertEquals( "\x08", encodeForJavaScript("\b"));
+ assertEquals( "\x09", encodeForJavaScript("\t"));
+ assertEquals( "\x0a", encodeForJavaScript("\n"));
+ assertEquals( "\x0b", encodeForJavaScript("\v"));
+ assertEquals( "\x0c", encodeForJavaScript("\f"));
+ assertEquals( "\x0d", encodeForJavaScript("\r"));
+ assertEquals( "\x27", encodeForJavaScript("\'"));
+ assertEquals( '\x22', encodeForJavaScript('\"'));
+ assertEquals( "\x5c", encodeForJavaScript("\\"));
+ </cfscript>
+
+ </cffunction>
+
+
+ <cffunction access="public" returntype="void" name="testDecodeFromURL" output="false" hint="Test of decodeFromURL">
+ <cfset var local = {}/>
+
+ <cfscript>
+ assertEquals("", decodeFromURL(""));
+ assertEquals("<script>", decodeFromURL("%3Cscript%3E"));
+ assertEquals(" ", decodeFromURL("+++++"));
+
+ try {
+ decodeFromURL("%3xridiculous");
+ }
+ catch(Application AppExcept) {
+ // expected
+ }
+ </cfscript>
+
+ </cffunction>
+
+ <cffunction access="public" returntype="void" name="testEncodeForURL" output="false" hint="Test of encodeForURL">
+ <cfset var local = {}/>
+
+ <cfscript>
+ assertEquals("", encodeForURL(""));
+ assertEquals("%3Cscript%3E", encodeForURL("<script>"));
+ </cfscript>
+
+ </cffunction>
+
+
+ <cffunction access="public" returntype="void" name="testEncodeForXML" output="false" hint="Test of encodeForXML">
+ <cfset var local = {}/>
+
+ <cfscript>
+ assertEquals("", encodeForXML(""));
+ assertEquals(" ", encodeForXML(" "));
+ assertEquals("&##x3c;script&##x3e;", encodeForXML("<script>"));
+ assertEquals(",.-_", encodeForXML(",.-_"));
+ assertEquals("&##x21;&##x40;&##x24;&##x25;&##x28;&##x29;&##x3d;&##x2b;&##x7b;&##x7d;&##x5b;&##x5d;", encodeForXML("!@$%()=+{}[]"));
+ assertEquals("&##xa3;", encodeForXML("\u00A3"));
+ </cfscript>
+
+ </cffunction>
+
+
+ <cffunction access="public" returntype="void" name="testHMAC" output="false" hint="Test of HMAC">
+ <cfset var local = {}/>
+
+ <cfscript>
+ // test various algorithms
+ assertEquals("80070713463E7749B90C2DC24911E275", HMAC("The quick brown fox jumps over the lazy dog", "key", "HMACMD5", "UTF-8"));
+ assertEquals("DE7C9B85B8B78AA6BC8A7A36F70A90701C9DB4D9", HMAC("The quick brown fox jumps over the lazy dog", "key", "HMACSHA1", "UTF-8"));
+ assertEquals("F7BC83F430538424B13298E6AA6FB143EF4D59A14946175997479DBC2D1A3CD8", HMAC("The quick brown fox jumps over the lazy dog", "key", "HMACSHA256", "UTF-8"));
+ assertEquals("D7F4727E2C0B39AE0F1E40CC96F60242D5B7801841CEA6FC592C5D3E1AE50700582A96CF35E1E554995FE4E03381C237", HMAC("The quick brown fox jumps over the lazy dog", "key", "HMACSHA384", "UTF-8"));
+ assertEquals("B42AF09057BAC1E2D41708E48A902E09B5FF7F12AB428A4FE86653C73DD248FB82F948A549F7B791A5B41915EE4D1EC3935357E4E2317250D0372AFA2EBEEB3A", HMAC("The quick brown fox jumps over the lazy dog", "key", "HMACSHA512", "UTF-8"));
+ assertEquals("50278A77D4D7670561AB72E867383AEF6CE50B3E", HMAC("The quick brown fox jumps over the lazy dog", "key", "HMACRIPEMD160", "UTF-8"));
+ assertEquals("88FF8B54675D39B8F72322E65FF945C52D96379988ADA25639747E69", HMAC("The quick brown fox jumps over the lazy dog", "key", "HMACSHA224", "UTF-8"));
+
+ // test sending binary arrays
+ assertEquals("DE7C9B85B8B78AA6BC8A7A36F70A90701C9DB4D9", HMAC(CharsetDecode("The quick brown fox jumps over the lazy dog", "UTF-8"), "key", "HMACSHA1", "UTF-8"));
+ assertEquals("DE7C9B85B8B78AA6BC8A7A36F70A90701C9DB4D9", HMAC("The quick brown fox jumps over the lazy dog", CharsetDecode("key", "UTF-8"), "HMACSHA1", "UTF-8"));
+ assertEquals("DE7C9B85B8B78AA6BC8A7A36F70A90701C9DB4D9", HMAC(CharsetDecode("The quick brown fox jumps over the lazy dog", "UTF-8"), CharsetDecode("key", "UTF-8"), "HMACSHA1", "UTF-8"));
+
+ // using default encoding of system and HMACMD5, could fail since test is based on UTF-8 encoding
+ assertEquals("63530468A04E386459855DA0063B6596", HMAC("", "key"));
+ assertEquals("80070713463E7749B90C2DC24911E275", HMAC("The quick brown fox jumps over the lazy dog", "key"));
+ </cfscript>
+
+ </cffunction>
+
+
+</cfcomponent>
Please sign in to comment.
Something went wrong with that request. Please try again.