Skip to content

Commit 86c89a2

Browse files
committed
Close issue #354.
1 parent c2585ac commit 86c89a2

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

src/main/java/org/owasp/esapi/codecs/Base64.java

+26-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// I think that really depends on how much OWASP ESAPI plans on tracking changes to this
99
// version vs. if the plan was just to fork from it and maintain OWASP's own version.
1010
// At this point, I think I prefer split from tracking Harder's original, but I'm easily
11-
// persuaded otherwise. - Kevin Wall
11+
// persuaded otherwise. (In fact, we have already done so w/ decodeToObject().) - Kevin Wall
1212

1313
/**
1414
* <p>Encodes and decodes to and from Base64 notation.</p>
@@ -136,6 +136,12 @@ public class Base64
136136
*/
137137
public final static int ORDERED = 32;
138138

139+
/**
140+
* System property name that must be set to true in order to invoke {@code Base64.decodeToObject()}.
141+
* @see https://github.com/ESAPI/esapi-java-legacy/issues/354
142+
* @see http://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/
143+
*/
144+
public final static String ENABLE_UNSAFE_SERIALIZATION = "org.owasp.esapi.enableUnsafeSerialization"; // Do NOT change!
139145

140146
/* ******** P R I V A T E F I E L D S ******** */
141147

@@ -1091,6 +1097,15 @@ public static byte[] decode( String s, int options )
10911097
* untrusted data from a string and deserialize it into
10921098
* an object can potentially result in remote command
10931099
* injection vulnerabilities. Use at your own risk!
1100+
* </p><p><b>IMPORTANT BACKWARD COMPATIBILITY NOTICE</b></br>
1101+
* Because this static method can easily be used as an attack vector
1102+
* for those passing in deserialized objects, in a manner similar to the
1103+
* <a href="https://issues.apache.org/jira/browse/COLLECTIONS-580">Apache Commons Collections InvokerTransformer</a>
1104+
* issue, we are requiring that the system property
1105+
* {@code org.owasp.esapi.enableUnsafeSerialization}
1106+
* be set to "true" in order for this method to be successfully invoked.
1107+
* We apologize for the inconvenience this may cause in breaking anyone's
1108+
* application, but we feel that it is for the greater good.
10941109
* </p>
10951110
*
10961111
* @param encodedObject The Base64 data to decode
@@ -1110,6 +1125,16 @@ public static byte[] decode( String s, int options )
11101125
@Deprecated
11111126
public static Object decodeToObject( String encodedObject )
11121127
{
1128+
// We will do better when we attempt this again, allowing for a second argument
1129+
// to specify some sort of a collection of white-listed classes. Until then...
1130+
// See: http://www.ibm.com/developerworks/library/se-lookahead/ for how-to.
1131+
if ( ! "true".equalsIgnoreCase( System.getProperty( ENABLE_UNSAFE_SERIALIZATION ) ) ) {
1132+
throw new UnsupportedOperationException(
1133+
"Deserialization by Base64.decodeToObject(String) is disabled for security reasons. " +
1134+
"To re-enable it, set the system property '" + ENABLE_UNSAFE_SERIALIZATION + "' to 'true'." +
1135+
"For details, see: https://github.com/ESAPI/esapi-java-legacy/issues/354");
1136+
}
1137+
11131138
// Decode and gunzip if necessary
11141139
byte[] objBytes = decode( encodedObject );
11151140

src/test/java/org/owasp/esapi/reference/EncoderTest.java

+56
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import java.io.UnsupportedEncodingException;
2020
import java.util.ArrayList;
2121
import java.util.Arrays;
22+
import java.io.ByteArrayOutputStream;
23+
import java.io.ObjectOutputStream;
2224

2325
import junit.framework.Test;
2426
import junit.framework.TestCase;
@@ -27,6 +29,7 @@
2729
import org.owasp.esapi.ESAPI;
2830
import org.owasp.esapi.Encoder;
2931
import org.owasp.esapi.EncoderConstants;
32+
import org.owasp.esapi.codecs.Base64;
3033
import org.owasp.esapi.codecs.Codec;
3134
import org.owasp.esapi.codecs.MySQLCodec;
3235
import org.owasp.esapi.codecs.OracleCodec;
@@ -632,6 +635,59 @@ public void testDecodeFromBase64() {
632635
}
633636
}
634637

638+
/**
639+
* Test of Base64.decodeToObject() method. Should really be put into a
640+
* separate Base64Test.java class, but this method has been deprecated
641+
* so hopefully, we can kill it off soon.
642+
*/
643+
public void testBase64decodToObject() {
644+
try {
645+
System.out.println("testBase64decodeToObject");
646+
647+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
648+
ObjectOutputStream dout = new ObjectOutputStream(baos);
649+
650+
// If you don't get the joke, google John Draper. (And, BTW, you should
651+
// be ashamed of yourself if you call yourself a hacker!)
652+
String cerealizeThis = new String("Cap'n Crunch - every hacker's favorite cereal");
653+
dout.writeObject( cerealizeThis );
654+
byte[] serializedData = baos.toByteArray();
655+
dout.close();
656+
657+
String b64serialized = Base64.encodeBytes( serializedData );
658+
final String propName = Base64.ENABLE_UNSAFE_SERIALIZATION;
659+
660+
// Make sure the property is not set.
661+
try { System.clearProperty( propName ); } catch(Throwable t) { ; }
662+
String capnCrunch = null;
663+
664+
try {
665+
capnCrunch = (String)Base64.decodeToObject( b64serialized );
666+
fail("Case 1: Did not throw UnsupportedOperationException");
667+
} catch(UnsupportedOperationException uoex) {
668+
; // Expected case
669+
}
670+
671+
try {
672+
System.setProperty( propName, "false" );
673+
capnCrunch = (String)Base64.decodeToObject( b64serialized );
674+
fail("Case 2: Did not throw UnsupportedOperationException");
675+
} catch(UnsupportedOperationException uoex) {
676+
; // Expected case
677+
}
678+
679+
try {
680+
// This case should work.
681+
System.setProperty( propName, "true" );
682+
capnCrunch = (String)Base64.decodeToObject( b64serialized );
683+
assertTrue( capnCrunch.equals( cerealizeThis ) );
684+
} catch(Throwable t) {
685+
fail("Case 3: Caught unexpected exception: " + t);
686+
}
687+
} catch(Throwable t) {
688+
fail("Caught unexpected exception: " + t);
689+
}
690+
}
635691

636692
/**
637693
* Test of WindowsCodec

0 commit comments

Comments
 (0)