Skip to content

Commit 18972bd

Browse files
committed
Merge pull request ServiceStack#447 from voloda/DeserializeActivationFix
Security fix: Explicitly specified __type should not be even activated when not appropriate
2 parents 94102ef + 7385b16 commit 18972bd

File tree

3 files changed

+56
-39
lines changed

3 files changed

+56
-39
lines changed

src/ServiceStack.Text/Common/DeserializeTypeRefJson.cs

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -91,37 +91,36 @@ internal static object StringToType(
9191
var explicitTypeName = Serializer.ParseString(propertyValueStr);
9292
var explicitType = AssemblyUtils.FindType(explicitTypeName);
9393

94-
if (explicitType != null && !explicitType.IsInterface() && !explicitType.IsAbstract())
94+
// let's do the type safety checks first before we even attempt to create
95+
// a type instance
96+
if (explicitType == null || explicitType.IsInterface() || explicitType.IsAbstract())
9597
{
96-
instance = explicitType.CreateInstance();
98+
Tracer.Instance.WriteWarning("Could not find type: " + propertyValueStr);
9799
}
98-
99-
if (instance == null)
100+
else if (!type.IsAssignableFrom(explicitType))
100101
{
101-
Tracer.Instance.WriteWarning("Could not find type: " + propertyValueStr);
102+
Tracer.Instance.WriteWarning("Could not assign type: " + propertyValueStr);
102103
}
103104
else
104105
{
105-
//If __type info doesn't match, ignore it.
106-
if (!type.InstanceOfType(instance))
107-
{
108-
instance = null;
109-
}
110-
else
106+
instance = explicitType.CreateInstance();
107+
}
108+
109+
if (instance != null)
110+
{
111+
var derivedType = instance.GetType();
112+
if (derivedType != type)
111113
{
112-
var derivedType = instance.GetType();
113-
if (derivedType != type)
114+
var derivedTypeConfig = new TypeConfig(derivedType);
115+
var map = DeserializeTypeRef.GetTypeAccessorMap(derivedTypeConfig, Serializer);
116+
if (map != null)
114117
{
115-
var derivedTypeConfig = new TypeConfig(derivedType);
116-
var map = DeserializeTypeRef.GetTypeAccessorMap(derivedTypeConfig, Serializer);
117-
if (map != null)
118-
{
119-
typeAccessorMap = map;
120-
}
118+
typeAccessorMap = map;
121119
}
122120
}
123121
}
124122

123+
125124
Serializer.EatItemSeperatorOrMapEndChar(strType, ref index);
126125
continue;
127126
}

src/ServiceStack.Text/Common/DeserializeTypeRefJsv.cs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,37 +45,33 @@ internal static object StringToType(
4545
var explicitTypeName = Serializer.ParseString(propertyValueStr);
4646
var explicitType = AssemblyUtils.FindType(explicitTypeName);
4747

48-
if (explicitType != null && !explicitType.IsInterface() && !explicitType.IsAbstract())
48+
if (explicitType == null || explicitType.IsInterface() || explicitType.IsAbstract())
4949
{
50-
instance = explicitType.CreateInstance();
50+
Tracer.Instance.WriteWarning("Could not find type: " + propertyValueStr);
5151
}
52-
53-
if (instance == null)
52+
else if (!type.IsAssignableFrom(explicitType))
5453
{
55-
Tracer.Instance.WriteWarning("Could not find type: " + propertyValueStr);
54+
Tracer.Instance.WriteWarning("Could not assign type: " + propertyValueStr);
5655
}
5756
else
5857
{
59-
//If __type info doesn't match, ignore it.
60-
if (!type.InstanceOfType(instance))
61-
{
62-
instance = null;
63-
}
64-
else
58+
instance = explicitType.CreateInstance();
59+
}
60+
61+
if (instance != null)
62+
{
63+
var derivedType = instance.GetType();
64+
if (derivedType != type)
6565
{
66-
var derivedType = instance.GetType();
67-
if (derivedType != type)
66+
var derivedTypeConfig = new TypeConfig(derivedType);
67+
var map = DeserializeTypeRef.GetTypeAccessorMap(derivedTypeConfig, Serializer);
68+
if (map != null)
6869
{
69-
var derivedTypeConfig = new TypeConfig(derivedType);
70-
var map = DeserializeTypeRef.GetTypeAccessorMap(derivedTypeConfig, Serializer);
71-
if (map != null)
72-
{
73-
typeAccessorMap = map;
74-
}
70+
typeAccessorMap = map;
7571
}
7672
}
7773
}
78-
74+
7975
//Serializer.EatItemSeperatorOrMapEndChar(strType, ref index);
8076
if (index != strType.Length) index++;
8177

tests/ServiceStack.Text.Tests/JsonTests/PolymorphicInstanceTest.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,27 @@ public void Can_deserialise_polymorphic_list_exact_with_no_side_effect_for_bad_t
4444

4545
}
4646

47+
[Test]
48+
public void Should_not_even_instantiate_incorrect_type()
49+
{
50+
var json = @"{""__type"":"""
51+
+ typeof(TestClass).ToTypeString() + @""", ""Name"":""Fido""}";
52+
var dog = JsonSerializer.DeserializeFromString<Dog>(
53+
54+
json);
55+
56+
Assert.IsFalse(TestClass.Called);
57+
}
58+
59+
public class TestClass
60+
{
61+
public static bool Called { get; set; }
62+
63+
public TestClass()
64+
{
65+
Called = true;
66+
}
67+
}
68+
4769
}
4870
}

0 commit comments

Comments
 (0)