From a3086cfc95ca651d283ab639b1ace0b0ecc90ea3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Reimar=20D=C3=B6ffinger?= Date: Tue, 15 Dec 2015 07:17:22 +0100 Subject: [PATCH] Add whitelist for deserialization. --- .../dictionary/DictionaryApplication.java | 2 +- .../android/util/PersistentObjectCache.java | 34 ++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/com/hughes/android/dictionary/DictionaryApplication.java b/src/com/hughes/android/dictionary/DictionaryApplication.java index a94ed53..d73d613 100644 --- a/src/com/hughes/android/dictionary/DictionaryApplication.java +++ b/src/com/hughes/android/dictionary/DictionaryApplication.java @@ -276,7 +276,7 @@ public class DictionaryApplication extends Application { } - static final class DictionaryConfig implements Serializable { + public static final class DictionaryConfig implements Serializable { private static final long serialVersionUID = -1444177164708201263L; // User-ordered list, persisted, just the ones that are/have been // present. diff --git a/src/com/hughes/android/util/PersistentObjectCache.java b/src/com/hughes/android/util/PersistentObjectCache.java index 150e3e6..56c546e 100644 --- a/src/com/hughes/android/util/PersistentObjectCache.java +++ b/src/com/hughes/android/util/PersistentObjectCache.java @@ -18,12 +18,21 @@ import android.content.Context; import android.os.Environment; import android.util.Log; +import com.hughes.android.dictionary.DictionaryApplication; +import com.hughes.android.dictionary.DictionaryInfo; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InvalidClassException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -32,6 +41,29 @@ public class PersistentObjectCache { private final File dir; private final Map objects = new LinkedHashMap(); + class ConstrainedOIS extends ObjectInputStream { + public ConstrainedOIS(InputStream in) throws IOException { + super(in); + } + + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { + String name = desc.getName(); + // Note: try to avoid adding more classes. + // LinkedHashMap is already more than enough for a DoS + if (!name.equals(ArrayList.class.getName()) && + !name.equals(HashMap.class.getName()) && + !name.equals(LinkedHashMap.class.getName()) && + !name.equals(String.class.getName()) && + !name.equals(DictionaryApplication.DictionaryConfig.class.getName()) && + !name.equals(DictionaryInfo.class.getName()) && + !name.equals(DictionaryInfo.IndexInfo.class.getName())) + { + throw new InvalidClassException("Not allowed to deserialize class", name); + } + return super.resolveClass(desc); + } + } + public synchronized T read(final String filename, final Class resultClass) { try { Object object = (objects.get(filename)); @@ -45,7 +77,7 @@ public class PersistentObjectCache { return null; } try { - final ObjectInputStream in = new ObjectInputStream(new FileInputStream(src)); + final ObjectInputStream in = new ConstrainedOIS(new FileInputStream(src)); object = in.readObject(); in.close(); } catch (Exception e) { -- 2.43.0