-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add deserialization type denylist #242
Changes from 26 commits
d6f8418
ff0a22c
cf20153
84eb198
72d6188
b0075b4
d9a9319
326f89f
2cf4598
457a5e7
b6a4f25
0f2044d
204e3c6
255948e
7b6f992
615d9d1
1c7a6d2
071c880
cbe964e
1f40195
781eaee
2fb434e
09185c7
3d5c626
984f6ac
f491d48
c57c37d
089f6ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using System.IO; | ||
using Hyperion.Extensions; | ||
using Hyperion.Internal; | ||
using Xunit; | ||
|
||
namespace Hyperion.Tests | ||
{ | ||
public class UnsafeDeserializationExclusionTests | ||
{ | ||
[Fact] | ||
public void CantDeserializeANaughtyType() | ||
{ | ||
//System.Diagnostics.Process p = new Process(); | ||
var serializer = new Hyperion.Serializer(); | ||
var di =new System.IO.DirectoryInfo(@"c:\"); | ||
|
||
using (var stream = new MemoryStream()) | ||
{ | ||
serializer.Serialize(di, stream); | ||
stream.Position = 0; | ||
Assert.Throws<EvilDeserializationException>(() => | ||
serializer.Deserialize<DirectoryInfo>(stream)); | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,10 +10,12 @@ | |
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Collections.ObjectModel; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Text.RegularExpressions; | ||
using Hyperion.Internal; | ||
|
||
namespace Hyperion.Extensions | ||
{ | ||
|
@@ -132,19 +134,82 @@ private static Type GetTypeFromManifestName(Stream stream, DeserializerSession s | |
}); | ||
} | ||
|
||
public static bool disallowUnsafeTypes = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, you can't -really- get to this since TypeEx is internal. This should probably be either moved or left out (because really, -why- would you want to do any of these? it's just a bad idea.) |
||
|
||
private static ReadOnlyCollection<string> unsafeTypesDenySet = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This list was amalgamated from:
|
||
new ReadOnlyCollection<string>(new[] | ||
{ | ||
"System.Security.Claims.ClaimsIdentity", | ||
"System.Windows.Forms.AxHost.State", | ||
"System.Windows.Data.ObjectDataProvider", | ||
"System.Management.Automation.PSObject", | ||
"System.Web.Security.RolePrincipal", | ||
"System.IdentityModel.Tokens.SessionSecurityToken", | ||
"SessionViewStateHistoryItem", | ||
"TextFormattingRunProperties", | ||
"ToolboxItemContainer", | ||
"System.Security.Principal.WindowsClaimsIdentity", | ||
"System.Security.Principal.WindowsIdentity", | ||
"System.Security.Principal.WindowsPrincipal", | ||
"System.CodeDom.Compiler.TempFileCollection", | ||
"System.IO.FileSystemInfo", | ||
"System.Activities.Presentation.WorkflowDesigner", | ||
"System.Windows.ResourceDictionary", | ||
"System.Windows.Forms.BindingSource", | ||
"Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvider", | ||
"System.Diagnostics.Process", | ||
"System.Management.IWbemClassObjectFreeThreaded" | ||
}); | ||
|
||
#if NETSTANDARD1_6 | ||
#else | ||
public static bool UnsafeInheritanceCheck(Type type) | ||
{ | ||
if (type.IsValueType) | ||
return false; | ||
var currentBase = type.BaseType; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we actually start this off with type, just to be safe? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In terms of security scanning? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If that's your question, then yes I would - want to work our way from bottom to top There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, its fine, its the while...loop check that needs to be changed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah ok, I misunderstood what was being asked here |
||
while (currentBase != typeof(object)) | ||
{ | ||
if (unsafeTypesDenySet.Any(r => currentBase.FullName.Contains(r))) | ||
return true; | ||
currentBase = currentBase.BaseType; | ||
} | ||
|
||
return false; | ||
} | ||
#endif | ||
public static Type LoadTypeByName(string name) | ||
{ | ||
if (disallowUnsafeTypes && unsafeTypesDenySet.Any(r => name.Contains(r))) | ||
{ | ||
throw new EvilDeserializationException( | ||
"Unsafe Type Deserialization Detected!", name); | ||
} | ||
try | ||
{ | ||
// Try to load type name using strict version to avoid possible conflicts | ||
// i.e. if there are different version available in GAC and locally | ||
var typename = ToQualifiedAssemblyName(name, ignoreAssemblyVersion: false); | ||
return Type.GetType(typename, true); | ||
var type = Type.GetType(typename, true); | ||
#if NETSTANDARD1_6 | ||
#else | ||
if (UnsafeInheritanceCheck(type)) | ||
throw new EvilDeserializationException( | ||
"Unsafe Type Deserialization Detected!", name); | ||
#endif | ||
return type; | ||
} | ||
catch (FileLoadException) | ||
{ | ||
var typename = ToQualifiedAssemblyName(name, ignoreAssemblyVersion: true); | ||
return Type.GetType(typename, true); | ||
var type = Type.GetType(typename, true); | ||
#if NETSTANDARD1_6 | ||
#else | ||
if (UnsafeInheritanceCheck(type)) | ||
throw new EvilDeserializationException( | ||
"Unsafe Type Deserialization Detected!", name); | ||
#endif | ||
return type; | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this unit test will play well in other OS runs... May need to make this something more platform friendly.