View Javadoc
1   package ch.qos.logback.core.net;
2   
3   import java.io.IOException;
4   import java.io.InputStream;
5   import java.io.InvalidClassException;
6   import java.io.ObjectInputStream;
7   import java.io.ObjectStreamClass;
8   import java.util.ArrayList;
9   import java.util.List;
10  
11  /**
12   * HardenedObjectInputStream restricts the set of classes that can be deserialized to a set of 
13   * explicitly whitelisted classes. This prevents certain type of attacks from being successful.
14   * 
15   * <p>It is assumed that classes in the "java.lang" and  "java.util" packages are 
16   * always authorized.</p>
17   * 
18   * @author Ceki G&uuml;lc&uuml;
19   * @since 1.2.0
20   */
21  public class HardenedObjectInputStream extends ObjectInputStream {
22  
23      final List<String> whitelistedClassNames;
24      final static String[] JAVA_PACKAGES = new String[] { "java.lang", "java.util" };
25  
26      public HardenedObjectInputStream(InputStream in, String[] whilelist) throws IOException {
27          super(in);
28  
29          this.whitelistedClassNames = new ArrayList<String>();
30          if (whilelist != null) {
31              for (int i = 0; i < whilelist.length; i++) {
32                  this.whitelistedClassNames.add(whilelist[i]);
33              }
34          }
35      }
36  
37      public HardenedObjectInputStream(InputStream in, List<String> whitelist) throws IOException {
38          super(in);
39  
40          this.whitelistedClassNames = new ArrayList<String>();
41          this.whitelistedClassNames.addAll(whitelist);
42      }
43  
44      @Override
45      protected Class<?> resolveClass(ObjectStreamClass anObjectStreamClass) throws IOException, ClassNotFoundException {
46          
47          String incomingClassName = anObjectStreamClass.getName();
48          
49          if (!isWhitelisted(incomingClassName)) {
50              throw new InvalidClassException("Unauthorized deserialization attempt", anObjectStreamClass.getName());
51          }
52  
53          return super.resolveClass(anObjectStreamClass);
54      }
55  
56      private boolean isWhitelisted(String incomingClassName) {
57          for (int i = 0; i < JAVA_PACKAGES.length; i++) {
58              if (incomingClassName.startsWith(JAVA_PACKAGES[i]))
59                  return true;
60          }
61          for (String whiteListed : whitelistedClassNames) {
62              if (incomingClassName.equals(whiteListed))
63                  return true;
64          }
65          return false;
66      }
67  
68      protected void addToWhitelist(List<String> additionalAuthorizedClasses) {
69          whitelistedClassNames.addAll(additionalAuthorizedClasses);
70      }
71  }