Skip to content

Commit

Permalink
Polishing #470
Browse files Browse the repository at this point in the history
  • Loading branch information
decebals committed Oct 27, 2018
1 parent c6b2655 commit 3f1aacc
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 83 deletions.
2 changes: 2 additions & 0 deletions pippo-core/src/main/java/ro/pippo/core/PippoConstants.java
Expand Up @@ -23,6 +23,8 @@ public final class PippoConstants {


public static final String LOCATION_OF_PIPPO_BUILTIN_PROPERTIES = "pippo/pippo-builtin.properties"; public static final String LOCATION_OF_PIPPO_BUILTIN_PROPERTIES = "pippo/pippo-builtin.properties";


public static final String LOCATION_OF_PIPPO_WHITELIST_SERIALIZATION = "/pippo/whitelist-serialization.txt";

public static final String LOCATION_OF_PIPPO_CLASSPATH_PROPERTIES = "conf/application.properties"; public static final String LOCATION_OF_PIPPO_CLASSPATH_PROPERTIES = "conf/application.properties";


public static final String APPLICATION_PROPERTIES = "application.properties"; public static final String APPLICATION_PROPERTIES = "application.properties";
Expand Down
@@ -1,83 +1,104 @@
/* /*
* Copyright (C) 2016 the original author or authors. * Copyright (C) 2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ro.pippo.core.util; package ro.pippo.core.util;


import java.io.IOException; import ro.pippo.core.PippoConstants;
import java.io.InputStream;
import java.io.InvalidClassException; import java.io.IOException;
import java.io.ObjectInputStream; import java.io.InputStream;
import java.io.ObjectStreamClass; import java.io.InvalidClassException;
import java.util.ArrayList; import java.io.ObjectInputStream;
import java.util.Collections; import java.io.ObjectStreamClass;
import java.util.List; import java.util.ArrayList;
import java.util.Properties; import java.util.List;


import static ro.pippo.core.util.StringUtils.isNullOrEmpty; /**

* When deserializing objects, first check that the class being deserialized is in the allowed whitelist.
/** *
* @author idealzh * @author idealzh
*/ */
public class WhitelistObjectInputStream extends ObjectInputStream { public class WhitelistObjectInputStream extends ObjectInputStream {
private static List<String> whiteClassNames = new ArrayList<String>();

private static List<String> whiteClassNames;
public WhitelistObjectInputStream(InputStream in) throws IOException {
super(in); static {

loadWhitelist(WhitelistObjectInputStream.class.getResourceAsStream(PippoConstants.LOCATION_OF_PIPPO_WHITELIST_SERIALIZATION));
whiteClassNames.add("ro.pippo.session.DefaultSessionData"); }
whiteClassNames.add("java.util.HashMap");
whiteClassNames.add("ro.pippo.core.Flash"); public WhitelistObjectInputStream(InputStream in) throws IOException {
whiteClassNames.add("java.util.ArrayList"); super(in);
} }


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


private boolean isWhiteListed(String className) { private boolean isWhiteListed(String className) {
for (Object name : whiteClassNames) { for (String name : whiteClassNames) {
if (name.equals(className)) return true; if (name.equals(className)) {
} return true;
return false; }
} }


/** return false;
* Load the whitelist from the properties file }
*/
static void loadWhitelist() { /**
Properties whitelistProperties = new Properties(); * Load the whitelist from an {@link InputStream}.
InputStream stream = null; * The content of the {@code InputStream} is in format:
try { * {@code
stream = WhitelistObjectInputStream.class.getResourceAsStream("src/main/resources/pippo/whitelist-serialization.txt"); * # Java
whitelistProperties.load(stream); * java.util.ArrayList
} catch (IOException e) { * java.util.HashMap
throw new RuntimeException("Error loading the whitelist-serialization.properties file", e); *
} finally { * # Pippo
if (stream != null) { * ro.pippo.session.DefaultSessionData
try { * ro.pippo.core.Flash
stream.close(); * }
} catch (IOException e) { *
throw new RuntimeException("Error closing the resource-serialization.properties file", e); * A line that starts with {@code #} is a comment and will be ignored.
} */
} private static void loadWhitelist(InputStream input) {
} String content;
Collections.addAll(whiteClassNames, whitelistProperties.getProperty("whitelist").split(",")); try {
} content = IoUtils.toString(input);
} } catch (IOException e) {
throw new RuntimeException("Error loading the whitelist input", e);
}

whiteClassNames = new ArrayList<>();

String[] lines = content.split("[\\r\\n]+");
for (String line : lines) {
if (line.startsWith("#")) {
// it's a comment; ignore line
continue;
}

addWhiteClassName(line);
}
}

private static void addWhiteClassName(String className) {
whiteClassNames.add(className);
}

}
@@ -0,0 +1,7 @@
# Java
java.util.ArrayList
java.util.HashMap

# Pippo
ro.pippo.session.DefaultSessionData
ro.pippo.core.Flash

0 comments on commit 3f1aacc

Please sign in to comment.