diff options
author | Norbert Schneider <norbert.schneider@code-intelligence.com> | 2022-03-01 15:58:39 +0100 |
---|---|---|
committer | Norbert Schneider <mail@bertschneider.de> | 2022-03-03 15:07:33 +0100 |
commit | 60776697833d84d968a8b6c403034fb1aa0a472b (patch) | |
tree | ac76964f7b9f91c93812dcc6e1312ebae2cf9447 /sanitizers | |
parent | b2e8a9dca69227f2952ec80020f436789efae887 (diff) | |
download | jazzer-api-60776697833d84d968a8b6c403034fb1aa0a472b.tar.gz |
Report a finding whenever honeypot class is loaded
Whenever external input leads to unrestricted class loading a RCE could
be possible. Report a finding every time and not only in specific
use-cases.
Diffstat (limited to 'sanitizers')
-rw-r--r-- | sanitizers/src/main/java/jaz/Zer.java | 231 |
1 files changed, 179 insertions, 52 deletions
diff --git a/sanitizers/src/main/java/jaz/Zer.java b/sanitizers/src/main/java/jaz/Zer.java index 0b27609c..08ca3d2e 100644 --- a/sanitizers/src/main/java/jaz/Zer.java +++ b/sanitizers/src/main/java/jaz/Zer.java @@ -15,93 +15,220 @@ package jaz; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; -import com.code_intelligence.jazzer.api.FuzzerSecurityIssueMedium; import com.code_intelligence.jazzer.api.Jazzer; -import java.io.IOException; -import java.io.ObjectInputStream; +import java.io.Closeable; +import java.io.Flushable; +import java.io.Serializable; +import java.util.*; +import java.util.concurrent.Callable; +import java.util.function.Function; /** - * A honeypot class that reports an appropriate finding on any interaction with one of its methods - * or initializers. + * A honeypot class that reports a finding on initialization. * - * Note: This class must not be referenced in any way by the rest of the code, not even statically. - * When referring to it, always use its hardcoded class name "jaz.Zer". + * Class loading based on externally controlled data could lead to RCE + * depending on available classes on the classpath. Even if no applicable + * gadget class is available, allowing input to control class loading is a bad + * idea and should be prevented. A finding is generated whenever the class + * is loaded and initialized, regardless of its further use. + * <p> + * This class needs to implement {@link Serializable} to be considered in + * deserialization scenarios. It also implements common constructors, getter + * and setter and common interfaces to increase chances of passing + * deserialization checks. + * <p> + * <b>Note</b>: Jackson provides a nice list of "nasty classes" at + * <a + * href=https://github.com/FasterXML/jackson-databind/blob/2.14/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java>SubTypeValidator</a>. + * <p> + * <b>Note</b>: This class must not be referenced in any way by the rest of the code, not even + * statically. When referring to it, always use its hardcoded class name {@code jaz.Zer}. */ -@SuppressWarnings("unused") -public class Zer implements java.io.Serializable { +@SuppressWarnings({"rawtypes", "unused"}) +public class Zer + implements Serializable, Cloneable, Comparable<Zer>, Comparator, Closeable, Flushable, Iterable, + Iterator, Runnable, Callable, Function, Collection, List { static final long serialVersionUID = 42L; - private static final Throwable staticInitializerCause; - static { - staticInitializerCause = new FuzzerSecurityIssueMedium("finalize call on arbitrary object"); + Jazzer.reportFindingFromHook(new FuzzerSecurityIssueHigh("Remote Code Execution\n" + + "Unrestricted class loading based on externally controlled data may allow\n" + + "remote code execution depending on available classes on the classpath.")); } - public Zer() { - Jazzer.reportFindingFromHook( - new FuzzerSecurityIssueMedium("default constructor call on arbitrary object")); + // Common constructors + + public Zer() {} + + public Zer(String arg1) {} + + public Zer(String arg1, Throwable arg2) {} + + // Getter/Setter + + public Object getJaz() { + return this; } - public Zer(String arg1) { - Jazzer.reportFindingFromHook( - new FuzzerSecurityIssueMedium("String constructor call on arbitrary object")); + public void setJaz(String jaz) {} + + // Common interface stubs + + @Override + public void close() {} + + @Override + public void flush() {} + + @Override + public int compareTo(Zer o) { + return 0; } - public Zer(String arg1, Throwable arg2) { - Jazzer.reportFindingFromHook( - new FuzzerSecurityIssueMedium("(String, Throwable) constructor call on arbitrary object")); + @Override + public int compare(Object o1, Object o2) { + return 0; } - private String jaz; + @Override + public int size() { + return 0; + } - public String getJaz() { - Jazzer.reportFindingFromHook(new FuzzerSecurityIssueMedium("getter call on arbitrary object")); - return jaz; + @Override + public boolean isEmpty() { + return false; } - public void setJaz(String jaz) { - Jazzer.reportFindingFromHook(new FuzzerSecurityIssueMedium("setter call on arbitrary object")); - this.jaz = jaz; + @Override + public boolean contains(Object o) { + return false; } @Override - public int hashCode() { - Jazzer.reportFindingFromHook( - new FuzzerSecurityIssueMedium("hashCode call on arbitrary object")); - return super.hashCode(); + public Object[] toArray() { + return new Object[0]; } @Override - public boolean equals(Object obj) { - Jazzer.reportFindingFromHook(new FuzzerSecurityIssueMedium("equals call on arbitrary object")); - return super.equals(obj); + public boolean add(Object o) { + return false; } @Override - protected Object clone() throws CloneNotSupportedException { - Jazzer.reportFindingFromHook(new FuzzerSecurityIssueMedium("clone call on arbitrary object")); - return super.clone(); + public boolean remove(Object o) { + return false; } @Override - public String toString() { - Jazzer.reportFindingFromHook( - new FuzzerSecurityIssueMedium("toString call on arbitrary object")); - return super.toString(); + public boolean addAll(Collection c) { + return false; } @Override - protected void finalize() throws Throwable { - // finalize is invoked automatically by the GC with an uninformative stack trace. We use the - // stack trace prerecorded in the static initializer. - Jazzer.reportFindingFromHook(staticInitializerCause); - super.finalize(); + public boolean addAll(int index, Collection c) { + return false; } - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - Jazzer.reportFindingFromHook(new FuzzerSecurityIssueHigh("Remote Code Execution\n" - + " Deserialization of arbitrary classes with custom readObject may allow remote\n" - + " code execution depending on the classpath.")); - in.defaultReadObject(); + @Override + public void clear() {} + + @Override + public Object get(int index) { + return this; + } + + @Override + public Object set(int index, Object element) { + return this; + } + + @Override + public void add(int index, Object element) {} + + @Override + public Object remove(int index) { + return this; + } + + @Override + public int indexOf(Object o) { + return 0; + } + + @Override + public int lastIndexOf(Object o) { + return 0; + } + + @Override + @SuppressWarnings("ConstantConditions") + public ListIterator listIterator() { + return null; + } + + @Override + @SuppressWarnings("ConstantConditions") + public ListIterator listIterator(int index) { + return null; + } + + @Override + public List subList(int fromIndex, int toIndex) { + return this; + } + + @Override + public boolean retainAll(Collection c) { + return false; + } + + @Override + public boolean removeAll(Collection c) { + return false; + } + + @Override + public boolean containsAll(Collection c) { + return false; + } + + @Override + public Object[] toArray(Object[] a) { + return new Object[0]; + } + + @Override + public Iterator iterator() { + return this; + } + + @Override + public void run() {} + + @Override + public boolean hasNext() { + return false; + } + + @Override + public Object next() { + return this; + } + + @Override + public Object call() throws Exception { + return this; + } + + @Override + public Object apply(Object o) { + return this; + } + + @Override + @SuppressWarnings("MethodDoesntCallSuperMethod") + public Object clone() { + return this; } } |