1616package org .owasp .esapi .reference ;
1717
1818import static org .junit .Assert .assertEquals ;
19+ import static org .junit .Assert .assertNotEquals ;
1920
2021import java .io .IOException ;
2122import java .io .UnsupportedEncodingException ;
2223import java .net .URI ;
24+ import java .util .List ;
2325import java .util .ArrayList ;
2426import java .util .Arrays ;
2527import java .util .HashMap ;
4143import org .owasp .esapi .codecs .WindowsCodec ;
4244import org .owasp .esapi .errors .EncodingException ;
4345import org .owasp .esapi .errors .IntrusionException ;
46+ import org .owasp .esapi .SecurityConfiguration ;
47+ import org .owasp .esapi .SecurityConfigurationWrapper ;
4448
4549import junit .framework .Test ;
4650import junit .framework .TestCase ;
5256 * @author Jeff Williams (jeff.williams@aspectsecurity.com)
5357 */
5458public class EncoderTest extends TestCase {
55-
59+
60+ private static class Conf extends SecurityConfigurationWrapper
61+ {
62+ private final List <String > codecList ;
63+
64+ /**
65+ * @param orig The original {@code SecurityConfiguration} to use as a basis.
66+ * Generally, that will just be: {@code ESAPI.securityConfiguration()}
67+ * @param codecsList List of {@code Codec}s to replace {@code Encoder.DefaultCodecList}
68+ */
69+ Conf (SecurityConfiguration orig , List <String > codecList )
70+ {
71+ super (orig );
72+ this .codecList = codecList ;
73+ }
74+
75+ @ Override
76+ public List <String > getDefaultCanonicalizationCodecs ()
77+ {
78+ return codecList ;
79+ }
80+ }
5681 private static final String PREFERRED_ENCODING = "UTF-8" ;
5782
5883 /**
@@ -78,7 +103,7 @@ protected void setUp() throws Exception {
78103 * @throws Exception
79104 */
80105 protected void tearDown () throws Exception {
81- // none
106+ ESAPI . override ( null ); // Restore
82107 }
83108
84109 /**
@@ -395,21 +420,25 @@ public void testencodeForCSS() {
395420 }
396421
397422 public void testCSSTripletLeadString () {
423+ System .out .println ("CSSTripletLeadString" );
398424 Encoder instance = ESAPI .encoder ();
399425 assertEquals ("rgb(255,255,255)\\ 21 " , instance .encodeForCSS ("rgb(255,255,255)!" ));
400426 assertEquals ("rgb(25%,25%,25%)\\ 21 " , instance .encodeForCSS ("rgb(25%,25%,25%)!" ));
401427 }
402428 public void testCSSTripletTailString () {
429+ System .out .println ("CSSTripletTailString" );
403430 Encoder instance = ESAPI .encoder ();
404431 assertEquals ("\\ 24 field\\ 3d rgb(255,255,255)\\ 21 " , instance .encodeForCSS ("$field=rgb(255,255,255)!" ));
405432 assertEquals ("\\ 24 field\\ 3d rgb(25%,25%,25%)\\ 21 " , instance .encodeForCSS ("$field=rgb(25%,25%,25%)!" ));
406433 }
407434 public void testCSSTripletStringPart () {
435+ System .out .println ("CSSTripletStringPart" );
408436 Encoder instance = ESAPI .encoder ();
409437 assertEquals ("\\ 24 field\\ 3d rgb(255,255,255)\\ 21 " , instance .encodeForCSS ("$field=rgb(255,255,255)!" ));
410438 assertEquals ("\\ 24 field\\ 3d rgb(25%,25%,25%)\\ 21 " , instance .encodeForCSS ("$field=rgb(25%,25%,25%)!" ));
411439 }
412440 public void testCSSTripletStringMultiPart () {
441+ System .out .println ("CSSTripletMultiPart" );
413442 Encoder instance = ESAPI .encoder ();
414443 assertEquals ("\\ 24 field\\ 3d rgb(255,255,255)\\ 21 \\ 20 \\ 24 field\\ 3d rgb(255,255,255)\\ 21 " , instance .encodeForCSS ("$field=rgb(255,255,255)! $field=rgb(255,255,255)!" ));
415444 assertEquals ("\\ 24 field\\ 3d rgb(25%,25%,25%)\\ 21 \\ 20 \\ 24 field\\ 3d rgb(25%,25%,25%)\\ 21 " , instance .encodeForCSS ("$field=rgb(25%,25%,25%)! $field=rgb(25%,25%,25%)!" ));
@@ -487,6 +516,7 @@ public void testEncodeForSQL() {
487516 }
488517
489518 public void testMySQLANSIModeQuoteInjection () {
519+ System .out .println ("mySQLANSIModeQuoteInjection" );
490520 Encoder instance = ESAPI .encoder ();
491521 Codec c = new MySQLCodec (MySQLCodec .Mode .ANSI );
492522 //No special handling is required for double quotes in ANSI_Quotes mode
@@ -539,22 +569,26 @@ public void testEncodeForDN() {
539569 * Longstanding issue of always lowercasing named HTML entities. This will be set right now.
540570 */
541571 public void testNamedUpperCaseDecoding (){
572+ System .out .println ("namedUpperCaseDecoding" );
542573 String input = "Ü" ;
543574 String expected = "Ü" ;
544575 assertEquals (expected , ESAPI .encoder ().decodeForHTML (input ));
545576 }
546577
547578 public void testEncodeForXMLNull () {
579+ System .out .println ("encodeFormXMLNull" );
548580 Encoder instance = ESAPI .encoder ();
549581 assertEquals (null , instance .encodeForXML (null ));
550582 }
551583
552584 public void testEncodeForXMLSpace () {
585+ System .out .println ("encodeFormXMLSpace" );
553586 Encoder instance = ESAPI .encoder ();
554587 assertEquals (" " , instance .encodeForXML (" " ));
555588 }
556589
557590 public void testEncodeForXMLScript () {
591+ System .out .println ("encodeForXMLScript" );
558592 Encoder instance = ESAPI .encoder ();
559593 assertEquals ("<script>" , instance .encodeForXML ("<script>" ));
560594 }
@@ -566,42 +600,49 @@ public void testEncodeForXMLImmune() {
566600 }
567601
568602 public void testEncodeForXMLSymbol () {
603+ System .out .println ("encodeForXMLSymbol" );
569604 Encoder instance = ESAPI .encoder ();
570605 assertEquals ("!@$%()=+{}[]" , instance .encodeForXML ("!@$%()=+{}[]" ));
571606 }
572607
573608 public void testEncodeForXMLPound () {
574- System .out .println ("encodeForXML " );
609+ System .out .println ("encodeForXMLPound " );
575610 Encoder instance = ESAPI .encoder ();
576611 assertEquals ("£" , instance .encodeForXML ("\u00A3 " ));
577612 }
578613
579614 public void testEncodeForXMLAttributeNull () {
615+ System .out .println ("encodeForXMLAttributeNull" );
580616 Encoder instance = ESAPI .encoder ();
581617 assertEquals (null , instance .encodeForXMLAttribute (null ));
582618 }
583619
584620 public void testEncodeForXMLAttributeSpace () {
621+ System .out .println ("encodeForXMLAttributeSpace" );
585622 Encoder instance = ESAPI .encoder ();
586623 assertEquals (" " , instance .encodeForXMLAttribute (" " ));
587624 }
588625
589626 public void testEncodeForXMLAttributeScript () {
627+ System .out .println ("encodeForXMLAttributeScript" );
590628 Encoder instance = ESAPI .encoder ();
591629 assertEquals ("<script>" , instance .encodeForXMLAttribute ("<script>" ));
592630 }
593631
594632 public void testEncodeForXMLAttributeImmune () {
633+ System .out .println ("encodeFormXMLAttributeImmune" );
595634 Encoder instance = ESAPI .encoder ();
596635 assertEquals (",.-_" , instance .encodeForXMLAttribute (",.-_" ));
597636 }
598637
599638 public void testEncodeForXMLAttributeSymbol () {
639+ System .out .println ("encodeFormXMLAttributeSymbol" );
600640 Encoder instance = ESAPI .encoder ();
601641 assertEquals (" !@$%()=+{}[]" , instance .encodeForXMLAttribute (" !@$%()=+{}[]" ));
602642 }
603643
604644 public void testEncodeForXMLAttributePound () {
645+ System .out .println ("encodeFormXMLAttributePound" );
605646 Encoder instance = ESAPI .encoder ();
606647 assertEquals ("£" , instance .encodeForXMLAttribute ("\u00A3 " ));
607648 }
@@ -859,6 +900,7 @@ public String javaScriptEncode(String str) {
859900 }
860901
861902 public void testGetCanonicalizedUri () throws Exception {
903+ System .out .println ("getCanonicalizedUri" );
862904 Encoder e = ESAPI .encoder ();
863905
864906 String expectedUri = "http://palpatine@foo bar.com/path_to/resource?foo=bar#frag" ;
@@ -873,6 +915,7 @@ public void testGetCanonicalizedUri() throws Exception {
873915 }
874916
875917 public void testGetCanonicalizedUriPiazza () throws Exception {
918+ System .out .println ("getCanonicalizedUriPiazza" );
876919 Encoder e = ESAPI .encoder ();
877920
878921 String expectedUri = "http://127.0.0.1:3000/campaigns?goal=all§ion=active&sort-by=-id&status=Draft,Launched" ;
@@ -887,6 +930,7 @@ public void testGetCanonicalizedUriPiazza() throws Exception {
887930 }
888931
889932 public void testGetCanonicalizedUriWithMailto () throws Exception {
933+ System .out .println ("getCanonicalizedUriWithMailto" );
890934 Encoder e = ESAPI .encoder ();
891935
892936 String expectedUri = "http://palpatine@foo bar.com/path_to/resource?foo=bar#frag" ;
@@ -901,6 +945,7 @@ public void testGetCanonicalizedUriWithMailto() throws Exception {
901945
902946 public void testHtmlEncodeStrSurrogatePair ()
903947 {
948+ System .out .println ("htmlEncodeStrSurrogatePair" );
904949 Encoder enc = ESAPI .encoder ();
905950 String inStr = new String (new int []{0x2f804 }, 0 , 1 );
906951 assertEquals (false , Character .isBmpCodePoint (inStr .codePointAt (0 )));
@@ -914,13 +959,15 @@ public void testHtmlEncodeStrSurrogatePair()
914959
915960 public void testHtmlDecodeHexEntititesSurrogatePair ()
916961 {
962+ System .out .println ("htmlDecodeHexEntitiesSurrogatePair" );
917963 HTMLEntityCodec htmlCodec = new HTMLEntityCodec ();
918964 String expected = new String (new int []{0x2f804 }, 0 , 1 );
919965 assertEquals ( expected , htmlCodec .decode ("你" ) );
920966 assertEquals ( expected , htmlCodec .decode ("你" ) );
921967 }
922968
923969 public void testUnicodeCanonicalize () {
970+ System .out .println ("UnicodeCanonicalize" );
924971 Encoder e = ESAPI .encoder ();
925972 String input = "测试" ;
926973 String expected = "测试" ;
@@ -929,6 +976,7 @@ public void testUnicodeCanonicalize() {
929976 }
930977
931978 public void testUnicodeCanonicalizePercentEncoding () {
979+ System .out .println ("UnicodeCanonicalizePercentEncoding" );
932980 //TODO: We need to find a way to specify the encoding type for percent encoding.
933981 //I believe by default we're doing Latin-1 and we really should be doing UTF-8
934982 Encoder e = ESAPI .encoder ();
@@ -937,5 +985,66 @@ public void testUnicodeCanonicalizePercentEncoding() {
937985 String output = e .canonicalize (input );
938986 assertNotSame (expected , output );
939987 }
940- }
941988
989+ // Test for GitHub Issue 686.
990+ public void testGetDefaultCanonicalizationCodecs () {
991+ System .out .println ("getDefaultCanonicalizationCodecs" );
992+
993+ // This test input has mixed encoding. It is encoded using %-encoding (e.g.,
994+ // the %20 representing spaces) and the '\\o' representing backslash
995+ // encoding. This particular backslash encoding (the "e\\tc") should
996+ // match *both* JavaScriptCodec and the UnixCodec.
997+ String testInput = "echo%20\" Hello%20$(id)\" ;%20echo \" Today is: \\ $(date)\" && cat \\ .\\ .\\ ///..///..///..//../e\\ tc///passwd" ;
998+
999+ // SecurityConfiguration before we change it later to tweak the Encoder.DefaultCodecList property
1000+ SecurityConfiguration scOrig = ESAPI .securityConfiguration ();
1001+
1002+ // We only use the 3 standard (default) Codecs here:
1003+ // HTMLEntityCodec, PercentCodec, and JavaScriptCodec.
1004+ // Since testInput only has one of these encodings (the PercentCodec),
1005+ // it will not fire off an IntrustionDetectionException here.
1006+ Encoder ecOrig = new DefaultEncoder ( scOrig .getDefaultCanonicalizationCodecs () );
1007+ String canonOrig = null ;
1008+ boolean caughtExpected = false ;
1009+ try {
1010+ ecOrig .canonicalize ( testInput );
1011+ } catch ( IntrusionException iex ) {
1012+ caughtExpected = true ;
1013+ }
1014+ assertEquals ( true , caughtExpected ); // Verify it threw an IntrusionException
1015+
1016+ // Now set up a case where (via the Encoder.DefaultCodecList property)
1017+ // where "UnixCodec" is added on to the standard list of 3 normal codecs
1018+ // used. Since we also have encoding using '\' encoding that should be
1019+ // recognized by UnixCodec, we should now get an
1020+ // IntrusionException as we have mixed and mulitple encoding
1021+ // both that should be recognized here.
1022+ List <String > myCodecs = new ArrayList <String >();
1023+ myCodecs .add ( "HTMLEntityCodec" );
1024+ myCodecs .add ( "PercentCodec" );
1025+ // myCodecs.add( "JavaScriptCodec" ); // Don't use this or we will have to parse exception message
1026+ // to see if test was successful or not.
1027+ // Instead of JavaScriptCodec, we will use UnixCodec to detect the backslash encoding here.
1028+ myCodecs .add ( "UnixCodec" );
1029+
1030+ // Finally override ESAPI to use the new SecurityConfiguration
1031+ ESAPI .override ( new Conf ( ESAPI .securityConfiguration (), myCodecs ) );
1032+
1033+ SecurityConfiguration scAltered = ESAPI .securityConfiguration ();
1034+ List <String > origCodecs = scOrig .getDefaultCanonicalizationCodecs ();
1035+ List <String > alteredCodecs = scAltered .getDefaultCanonicalizationCodecs ();
1036+
1037+ // First, let's confirm we've actually overridden the SecurityConfiguration.
1038+ assertNotEquals ( origCodecs , alteredCodecs );
1039+
1040+ // Now do the canonicalization w/ the new list of codecs
1041+ caughtExpected = true ;
1042+ try {
1043+ String canonAltered = ESAPI .encoder ().canonicalize ( testInput );
1044+ } catch ( IntrusionException iex ) {
1045+ caughtExpected = true ;
1046+ }
1047+
1048+ assertEquals ( true , caughtExpected ); // Verify it threw an IntrusionException
1049+ }
1050+ }
0 commit comments