Added ImageEffectsSerializationBinder to improve security of JSON deserialization

This commit is contained in:
Jaex 2021-05-31 09:32:50 +03:00
parent caba14a36e
commit f32da61fab
7 changed files with 19 additions and 28 deletions

View file

@ -157,11 +157,7 @@ private object Deserialize(string json)
JsonSerializer serializer = new JsonSerializer(); JsonSerializer serializer = new JsonSerializer();
serializer.Converters.Add(new StringEnumConverter()); serializer.Converters.Add(new StringEnumConverter());
serializer.ObjectCreationHandling = ObjectCreationHandling.Replace; serializer.ObjectCreationHandling = ObjectCreationHandling.Replace;
serializer.TypeNameHandling = TypeNameHandling.Auto; if (SerializationBinder != null) serializer.SerializationBinder = SerializationBinder;
if (SerializationBinder != null)
{
serializer.SerializationBinder = SerializationBinder;
}
serializer.Error += (sender, e) => e.ErrorContext.Handled = true; serializer.Error += (sender, e) => e.ErrorContext.Handled = true;
return serializer.Deserialize(textReader, ObjectType); return serializer.Deserialize(textReader, ObjectType);
} }

View file

@ -1360,6 +1360,13 @@ public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
return instances.ToArray(); return instances.ToArray();
} }
public static IEnumerable<Type> FindSubclassesOf<TBaseType>()
{
Type baseType = typeof(TBaseType);
Assembly assembly = baseType.Assembly;
return assembly.GetTypes().Where(t => t.IsSubclassOf(baseType));
}
public static string GetOperatingSystemProductName(bool includeBit = false) public static string GetOperatingSystemProductName(bool includeBit = false)
{ {
string productName = null; string productName = null;

View file

@ -47,7 +47,6 @@ public static class JsonHelpers
serializer.Converters.Add(new StringEnumConverter()); serializer.Converters.Add(new StringEnumConverter());
serializer.DefaultValueHandling = defaultValueHandling; serializer.DefaultValueHandling = defaultValueHandling;
serializer.NullValueHandling = nullValueHandling; serializer.NullValueHandling = nullValueHandling;
serializer.TypeNameHandling = TypeNameHandling.Auto;
if (serializationBinder != null) serializer.SerializationBinder = serializationBinder; if (serializationBinder != null) serializer.SerializationBinder = serializationBinder;
serializer.Serialize(jsonTextWriter, obj); serializer.Serialize(jsonTextWriter, obj);
} }
@ -110,7 +109,6 @@ public static T Deserialize<T>(TextReader textReader, ISerializationBinder seria
JsonSerializer serializer = new JsonSerializer(); JsonSerializer serializer = new JsonSerializer();
serializer.Converters.Add(new StringEnumConverter()); serializer.Converters.Add(new StringEnumConverter());
serializer.ObjectCreationHandling = ObjectCreationHandling.Replace; serializer.ObjectCreationHandling = ObjectCreationHandling.Replace;
serializer.TypeNameHandling = TypeNameHandling.Auto;
if (serializationBinder != null) serializer.SerializationBinder = serializationBinder; if (serializationBinder != null) serializer.SerializationBinder = serializationBinder;
serializer.Error += (sender, e) => e.ErrorContext.Handled = true; serializer.Error += (sender, e) => e.ErrorContext.Handled = true;
return serializer.Deserialize<T>(jsonTextReader); return serializer.Deserialize<T>(jsonTextReader);

View file

@ -297,7 +297,6 @@
<Compile Include="ShareXTheme.cs" /> <Compile Include="ShareXTheme.cs" />
<Compile Include="TextBoxTraceListener.cs" /> <Compile Include="TextBoxTraceListener.cs" />
<Compile Include="Settings\SafeStringEnumConverter.cs" /> <Compile Include="Settings\SafeStringEnumConverter.cs" />
<Compile Include="Settings\TypeNameSerializationBinder.cs" />
<Compile Include="UITypeEditors\EnumDescriptionConverter.cs" /> <Compile Include="UITypeEditors\EnumDescriptionConverter.cs" />
<Compile Include="UITypeEditors\DirectoryNameEditor.cs" /> <Compile Include="UITypeEditors\DirectoryNameEditor.cs" />
<Compile Include="UITypeEditors\EnumProperNameKeepCaseConverter.cs" /> <Compile Include="UITypeEditors\EnumProperNameKeepCaseConverter.cs" />

View file

@ -50,7 +50,7 @@ public partial class ImageEffectsForm : Form
public string FilePath { get; private set; } public string FilePath { get; private set; }
private bool pauseUpdate; private bool pauseUpdate;
private ISerializationBinder serializationBinder = new TypeNameSerializationBinder("ShareX.ImageEffectsLib", "ShareX.ImageEffectsLib"); private ISerializationBinder serializationBinder = new ImageEffectsSerializationBinder();
public ImageEffectsForm(Bitmap bmp, List<ImageEffectPreset> presets, int selectedPresetIndex) public ImageEffectsForm(Bitmap bmp, List<ImageEffectPreset> presets, int selectedPresetIndex)
{ {

View file

@ -24,19 +24,20 @@
#endregion License Information (GPL v3) #endregion License Information (GPL v3)
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
using ShareX.HelpersLib;
using System; using System;
using System.Collections.Generic;
using System.Linq;
namespace ShareX.HelpersLib namespace ShareX.ImageEffectsLib
{ {
public class TypeNameSerializationBinder : ISerializationBinder public class ImageEffectsSerializationBinder : ISerializationBinder
{ {
public string AppNamespace { get; private set; } public IEnumerable<Type> KnownTypes { get; set; }
public string AppAssembly { get; private set; }
public TypeNameSerializationBinder(string appNamespace, string appAssembly) public ImageEffectsSerializationBinder()
{ {
AppNamespace = appNamespace; KnownTypes = Helpers.FindSubclassesOf<ImageEffect>();
AppAssembly = appAssembly;
} }
public void BindToName(Type serializedType, out string assemblyName, out string typeName) public void BindToName(Type serializedType, out string assemblyName, out string typeName)
@ -47,18 +48,7 @@ public void BindToName(Type serializedType, out string assemblyName, out string
public Type BindToType(string assemblyName, string typeName) public Type BindToType(string assemblyName, string typeName)
{ {
string resolvedTypeName; return KnownTypes.SingleOrDefault(t => t.Name == typeName);
if (!string.IsNullOrEmpty(assemblyName))
{
resolvedTypeName = $"{typeName}, {assemblyName}";
}
else
{
resolvedTypeName = $"{AppNamespace}.{typeName}, {AppAssembly}";
}
return Type.GetType(resolvedTypeName, true);
} }
} }
} }

View file

@ -171,6 +171,7 @@
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
</Compile> </Compile>
<Compile Include="ImageEffectsSerializationBinder.cs" />
<Compile Include="WatermarkConfig.cs" /> <Compile Include="WatermarkConfig.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>