Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pippo-content-type-parent/pippo-xstream/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<description>XStream integration</description>

<properties>
<xstream.version>1.4.9</xstream.version>
<xstream.version>1.4.11.1</xstream.version>
</properties>

<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
import ro.pippo.core.HttpConstants;

import com.thoughtworks.xstream.XStream;
import ro.pippo.core.util.WhitelistObjectInputStream;

import java.util.regex.Pattern;

/**
* An XmlEngine based on XStream.
Expand All @@ -45,6 +48,10 @@ private XStream xstream() {
xstream.autodetectAnnotations(true);
// prevent xstream from creating complex XML graphs
xstream.setMode(XStream.NO_REFERENCES);

//setup security
xstream.allowTypes((String[]) WhitelistObjectInputStream.getWhitelistedClassNames().toArray());
xstream.allowTypesByRegExp((Pattern[]) WhitelistObjectInputStream.getWhitelistedRegExp().toArray());
return xstream;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.io.ObjectStreamClass;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
* When deserializing objects, first check that the class being deserialized is in the allowed whitelist.
Expand All @@ -33,6 +34,7 @@
public class WhitelistObjectInputStream extends ObjectInputStream {

private static List<String> whiteClassNames;
private static List<Pattern> whiteRegExp;

static {
loadWhitelist(WhitelistObjectInputStream.class.getResourceAsStream(PippoConstants.LOCATION_OF_PIPPO_WHITELIST_SERIALIZATION));
Expand All @@ -44,7 +46,7 @@ public WhitelistObjectInputStream(InputStream in) throws IOException {

protected Class<?> resolveClass(ObjectStreamClass descriptor) throws ClassNotFoundException, IOException {
String className = descriptor.getName();
if (!isWhiteListed(className)) {
if ((!isWhiteListed(className)) && (!isWhiteListedRegex(className))) {
throw new InvalidClassException("Unauthorized deserialization attempt", className);
}

Expand All @@ -61,20 +63,33 @@ private boolean isWhiteListed(String className) {
return false;
}

private boolean isWhiteListedRegex(String className) {
for (Pattern pattern : whiteRegExp) {
if (pattern.matcher(className).matches()) {
return true;
}
}

return false;
}

/**
* Load the whitelist from an {@link InputStream}.
* The content of the {@code InputStream} is in format:
* {@code
* # Java
* java.util.ArrayList
* java.util.HashMap
* A regular expression whitelisting the whole java.lang package and its sub-packages.
* /java.lang.* /
*
* # Pippo
* ro.pippo.session.DefaultSessionData
* ro.pippo.core.Flash
* }
*
* A line that starts with {@code #} is a comment and will be ignored.
* A line that starts and ends with {@code /} is interpreted as a regular expression.
*/
private static void loadWhitelist(InputStream input) {
String content;
Expand All @@ -91,6 +106,8 @@ private static void loadWhitelist(InputStream input) {
if (line.startsWith("#")) {
// it's a comment; ignore line
continue;
} else if (line.startsWith("/") && (line.endsWith("/"))) {
addWhiteRegExp(Pattern.compile(line.substring(1, line.length() - 2)));
}

addWhiteClassName(line);
Expand All @@ -101,4 +118,24 @@ private static void addWhiteClassName(String className) {
whiteClassNames.add(className);
}

private static void addWhiteRegExp(Pattern pattern) {
whiteRegExp.add(pattern);
}

/**
* Returns the whitelisted class names.
* @return the whitelisted class names.
*/
public static List<String> getWhitelistedClassNames() {
return whiteClassNames;
}

/**
* Returns the whitelisted regular expressions.
* @return the whitelisted regular expressions.
*/
public static List<Pattern> getWhitelistedRegExp() {
return whiteRegExp;
}

}