diff --git a/core/src/main/java/hudson/util/XStream2.java b/core/src/main/java/hudson/util/XStream2.java index 6602e53405ab477b76280afd9228a0ea23890190..6fb63ae35dfccc0df61ce1a53329d3826421c0a5 100644 --- a/core/src/main/java/hudson/util/XStream2.java +++ b/core/src/main/java/hudson/util/XStream2.java @@ -29,6 +29,7 @@ import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.mapper.AnnotationMapper; import com.thoughtworks.xstream.mapper.Mapper; import com.thoughtworks.xstream.mapper.MapperWrapper; +import com.thoughtworks.xstream.converters.ConversionException; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.ConverterMatcher; import com.thoughtworks.xstream.converters.DataHolder; @@ -36,6 +37,7 @@ import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.SingleValueConverter; import com.thoughtworks.xstream.converters.SingleValueConverterWrapper; import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.converters.extended.DynamicProxyConverter; import com.thoughtworks.xstream.core.JVM; import com.thoughtworks.xstream.io.HierarchicalStreamDriver; import com.thoughtworks.xstream.io.HierarchicalStreamReader; @@ -155,6 +157,15 @@ public class XStream2 extends XStream { // this should come after all the XStream's default simpler converters, // but before reflection-based one kicks in. registerConverter(new AssociatedConverterImpl(this), -10); + + registerConverter(new DynamicProxyConverter(getMapper()) { // SECURITY-105 defense + @Override public boolean canConvert(Class type) { + return /* this precedes NullConverter */ type != null && super.canConvert(type); + } + @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { + throw new ConversionException(" not supported"); + } + }, PRIORITY_VERY_HIGH); } @Override diff --git a/core/src/test/java/hudson/util/XStream2Test.java b/core/src/test/java/hudson/util/XStream2Test.java index 6804bfec7617b5324afe432294863220fc88b0c4..4f818442e3819bd9848837340d11e118934ee3ad 100644 --- a/core/src/test/java/hudson/util/XStream2Test.java +++ b/core/src/test/java/hudson/util/XStream2Test.java @@ -25,6 +25,7 @@ package hudson.util; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.thoughtworks.xstream.XStreamException; import hudson.XmlFile; import hudson.matrix.MatrixRun; import hudson.model.Result; @@ -312,6 +313,21 @@ public class XStream2Test extends TestCase { assertEquals("def",map.m.get("abc")); } + public void testDynamicProxyBlocked() throws Exception { // SECURITY-105 + try { + ((Runnable) new XStream2().fromXML("java.lang.Runnableoops")).run(); + } catch (XStreamException x) { + // good + } + assertFalse("should never have run that", Hacked.tripped); + } + public static final class Hacked { + static boolean tripped; + public void oops() { + tripped = true; + } + } + public void testTrimVersion() throws Exception { assertEquals("3.2", XStream2.trimVersion("3.2")); assertEquals("3.2.1", XStream2.trimVersion("3.2.1"));