From 58b6571f37b62dab6f801d015f24e05d968ded5d Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Mon, 29 Nov 2021 22:10:57 +0100 Subject: [PATCH] added check for custom type deserialization --- AjaxPro/AssemblyInfo.cs | 6 +- AjaxPro/JSON/Converters/DataTableConverter.cs | 5 +- AjaxPro/JSON/Converters/HashtableConverter.cs | 13 +++- .../JSON/Converters/HtmlControlConverter.cs | 6 +- AjaxPro/JSON/JavaScriptDeserializer.cs | 70 +++++++++++++------ AjaxPro/Utilities/Utility.cs | 4 +- 6 files changed, 71 insertions(+), 33 deletions(-) diff --git a/AjaxPro/AssemblyInfo.cs b/AjaxPro/AssemblyInfo.cs index 924fb17..f6b332f 100644 --- a/AjaxPro/AssemblyInfo.cs +++ b/AjaxPro/AssemblyInfo.cs @@ -29,8 +29,6 @@ * MR Matthew Raymer * * - * - * * MS 06-04-03 fixed missing http error status code in core.js * MS 06-04-04 added AjaxPro.onError, onTimeout, onStateChanged, onLoading to core.js * MS 06-04-05 removed Object.prototype.extend from prototype.js and all othere files using this @@ -41,7 +39,7 @@ * MS 06-07-19 removed ReflectionPermission attribute (why did we add it?) * MS 21-10-30 added contentSecurityPolicy to specify a nonce for all scripts * MS 21-11-22 changed default behavior of passing types during deserialization to deny - * + * MS 21-11-29 added check for custom type deserialization * */ using System; @@ -93,7 +91,7 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("21.11.22.1")] // do not remove the blanks!!!! +[assembly: AssemblyVersion("21.11.29.1")] // do not remove the blanks!!!! // // In order to sign your assembly you must specify a key to use. Refer to the diff --git a/AjaxPro/JSON/Converters/DataTableConverter.cs b/AjaxPro/JSON/Converters/DataTableConverter.cs index eb2e8e9..301b00c 100644 --- a/AjaxPro/JSON/Converters/DataTableConverter.cs +++ b/AjaxPro/JSON/Converters/DataTableConverter.cs @@ -33,7 +33,7 @@ * MS 06-09-26 improved performance using StringBuilder * MS 07-04-24 added renderJsonCompliant serialization * MS 08-03-21 fixed DataTable client-side script - * + * MS 21-11-29 added check for custom type deserialization * * */ @@ -147,7 +147,10 @@ public override object Deserialize(IJavaScriptObject o, Type t) for (int i = 0; i < columns.Count; i++) { column = (JavaScriptArray)columns[i]; + colType = Type.GetType(column[1].ToString(), true); + JavaScriptDeserializer.ThrowExceptionIfNotCustomTypeDeserializationAllowed(colType); + dt.Columns.Add(column[0].ToString(), colType); } diff --git a/AjaxPro/JSON/Converters/HashtableConverter.cs b/AjaxPro/JSON/Converters/HashtableConverter.cs index 2dc731f..7cd5bc1 100644 --- a/AjaxPro/JSON/Converters/HashtableConverter.cs +++ b/AjaxPro/JSON/Converters/HashtableConverter.cs @@ -32,7 +32,7 @@ * MS 06-09-24 use QuoteString instead of Serialize * MS 06-09-26 improved performance using StringBuilder * MS 07-04-24 added renderJsonCompliant serialization - * + * MS 21-11-29 added check for custom type deserialization * */ using System; @@ -86,8 +86,15 @@ public override object Deserialize(IJavaScriptObject o, Type t) for (int i = 0; i < a.Count; i++) { aa = (JavaScriptArray)a[i]; - key = JavaScriptDeserializer.Deserialize((IJavaScriptObject)aa[0], Type.GetType(((JavaScriptString)aa[2]).ToString())); - value = JavaScriptDeserializer.Deserialize((IJavaScriptObject)aa[1], Type.GetType(((JavaScriptString)aa[3]).ToString())); + + Type keyType = Type.GetType(((JavaScriptString)aa[2]).ToString()); + Type valueType = Type.GetType(((JavaScriptString)aa[3]).ToString()); + + JavaScriptDeserializer.ThrowExceptionIfNotCustomTypeDeserializationAllowed(keyType); + JavaScriptDeserializer.ThrowExceptionIfNotCustomTypeDeserializationAllowed(valueType); + + key = JavaScriptDeserializer.Deserialize((IJavaScriptObject)aa[0], keyType); + value = JavaScriptDeserializer.Deserialize((IJavaScriptObject)aa[1], valueType); d.Add(key, value); } diff --git a/AjaxPro/JSON/Converters/HtmlControlConverter.cs b/AjaxPro/JSON/Converters/HtmlControlConverter.cs index 1a7595e..780f25b 100644 --- a/AjaxPro/JSON/Converters/HtmlControlConverter.cs +++ b/AjaxPro/JSON/Converters/HtmlControlConverter.cs @@ -26,6 +26,8 @@ /* * MS 06-05-23 using local variables instead of "new Type()" for get De-/SerializableTypes * MS 06-09-26 improved performance using StringBuilder + * MS 21-11-29 added check for custom type deserialization + * * * */ @@ -171,12 +173,14 @@ internal static HtmlControl HtmlControlFromString(string html, Type type) if(!typeof(HtmlControl).IsAssignableFrom(type)) throw new InvalidCastException("The target type is not a HtmlControlType"); + JavaScriptDeserializer.ThrowExceptionIfNotCustomTypeDeserializationAllowed(type); + html = AddRunAtServer(html, (Activator.CreateInstance(type) as HtmlControl).TagName); if(type.IsAssignableFrom(typeof(HtmlSelect))) html = CorrectAttributes(html); - Control o = HtmlControlConverterHelper.Parse(html);; + Control o = HtmlControlConverterHelper.Parse(html); if(o.GetType() == type) return (o as HtmlControl); diff --git a/AjaxPro/JSON/JavaScriptDeserializer.cs b/AjaxPro/JSON/JavaScriptDeserializer.cs index 16f5fee..d4064a8 100644 --- a/AjaxPro/JSON/JavaScriptDeserializer.cs +++ b/AjaxPro/JSON/JavaScriptDeserializer.cs @@ -38,13 +38,14 @@ * MS 06-09-26 improved performance removing three-times cast * MS 21-10-27 added allowed customized types for JSON deserialization * MS 21-11-22 changed error message when type is not allowed - * + * MS 21-11-29 added check for custom type deserialization * */ using System; using System.Text; using System.Reflection; using System.Collections; +using System.Security; namespace AjaxPro { @@ -146,27 +147,7 @@ public static object Deserialize(IJavaScriptObject o, Type type) if (type == null || type.IsAssignableFrom(t)) { type = t; - - if (AjaxPro.Utility.Settings.IsCustomTypesDeserializationDisabled) - { - bool isCustomTypeAllowed = false; - - foreach (var s in AjaxPro.Utility.Settings.JsonDeserializationCustomTypesAllowed) - if ((s.EndsWith("*") && type.FullName.StartsWith(s.Substring(0, s.Length - 1), StringComparison.InvariantCultureIgnoreCase)) || s == type.FullName) - { - isCustomTypeAllowed = true; - break; - } - - if (!isCustomTypeAllowed) - throw new System.Security.SecurityException("This type is not allowed as argument for this method."); - } - else - { - foreach (var s in AjaxPro.Utility.Settings.JsonDeserializationCustomTypesDenied) - if ((s.EndsWith("*") && type.FullName.StartsWith(s.Substring(0, s.Length -1), StringComparison.InvariantCultureIgnoreCase)) || s == type.FullName) - throw new System.Security.SecurityException("This type is not allowed as argument for this method."); - } + ThrowExceptionIfNotCustomTypeDeserializationAllowed(type); } } @@ -228,6 +209,51 @@ public static object Deserialize(IJavaScriptObject o, Type type) #region Internal Methods + internal static void ThrowExceptionIfNotCustomTypeDeserializationAllowed(Type type) + { + SecurityException ex = null; + if (!IsCustomTypeDeserializationAllowed(type, out ex) && ex != null) + throw ex; + } + + internal static bool IsCustomTypeDeserializationAllowed(Type type, out SecurityException ex) + { + ex = null; + + // allow all primitive and basic types + if (type.IsPrimitive || type == typeof(string) || type == typeof(DateTime) || type == typeof(TimeSpan) || type == typeof(decimal)) + return true; + + if (AjaxPro.Utility.Settings.IsCustomTypesDeserializationDisabled) + { + bool isCustomTypeAllowed = false; + + foreach (var s in AjaxPro.Utility.Settings.JsonDeserializationCustomTypesAllowed) + if ((s.EndsWith("*") && type.FullName.StartsWith(s.Substring(0, s.Length - 1), StringComparison.InvariantCultureIgnoreCase)) || s == type.FullName) + { + isCustomTypeAllowed = true; + break; + } + + if (!isCustomTypeAllowed) + { + ex = new SecurityException("This type is not allowed as argument for this method."); + return false; + } + } + else + { + foreach (var s in AjaxPro.Utility.Settings.JsonDeserializationCustomTypesDenied) + if ((s.EndsWith("*") && type.FullName.StartsWith(s.Substring(0, s.Length - 1), StringComparison.InvariantCultureIgnoreCase)) || s == type.FullName) + { + ex = new SecurityException("This type is not allowed as argument for this method."); + return false; + } + } + + return true; + } + /// /// Deserializes the custom object. /// diff --git a/AjaxPro/Utilities/Utility.cs b/AjaxPro/Utilities/Utility.cs index 0ad4f9e..13be74b 100644 --- a/AjaxPro/Utilities/Utility.cs +++ b/AjaxPro/Utilities/Utility.cs @@ -48,7 +48,7 @@ * using new AjaxSecurityProvider * MS 09-02-17 fixed memory problem * MS 21-10-30 added contentSecurityPolicy to specify a nonce for all scripts - * + * MS 21-11-29 removed HtmlControlConverter from default converters * */ using System; @@ -254,7 +254,7 @@ internal static void AddDefaultConverter(AjaxSettings settings) AddConverter(settings, new IEnumerableConverter()); AddConverter(settings, new DataRowConverter()); - AddConverter(settings, new HtmlControlConverter()); + //AddConverter(settings, new HtmlControlConverter()); #endregion }