Not calling your parent constructor

Earlier today, JArnold wrote a blog entry that looked at an instance-based constructor hack that is similar (in an opposite kind of way) to my earlier post on class constructors.

Whilst JArnold's blog is 100% correct, there's an important distinction from a security perspective: what (s)he (sorry JArnold, I don't know who you are! :-) ) does is fail to initialise the parent class in a constructor. This is clearly against the rules of the CLR and will cause your code to be unverifiable. It will not run from a partially-trusted location such as an internet web site.

I'll omit the source and IL code for this post, but in the following example "noconstructor" is the base C# executable (100% "pure" code) and "noconstructorhack" is the hand-tweaked IL version that doesn't call the base class' constructor:

[C:scripts]
noconstructor.exe

Constructing...

Done!

 

[C:scripts]
peverify noconstructorHack.EXE

 

Microsoft (R) .NET Framework PE Verifier Version 1.1.4322.573

Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

 

[IL]: Error: [c:scriptsnoconstructorhack.exe : D::.ctor] [offset 0x00000000] [opcode ret] Return from ctor when this is uninitialized.

1 Errors Verifying noconstructorHack.EXE

 

[C:scripts]
noconstructorHack.EXE

Done!

 

[C:scripts]
caspol -u -ag 1.1 -url c:scriptsnoconstructorHack.EXE Internet -n "NoConstructorTest" -exclusive on

Microsoft (R) .NET Framework CasPol 1.1.4322.573

Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

 

Added union code group with "-url" membership condition to the User level.

Success

 

[C:scripts]
noconstructorHack.EXE

 

Unhandled Exception: System.Security.VerificationException: Operation could destabilize the runtime.

   at D..ctor()

   at D.Main()

Master of everything Raymond Chen has a comment that gives another example of how you can do it without tweaking IL, but again serialisation requires privileges that are not granted to code in the Internet zone:

[C:scripts]
serialise.exe

Creating

constructed

Serializing

Deserializing

False

 

[C:scripts]
caspol -u -ag 1.1 -url c:scriptsserialise.EXE Internet -n "Serialise" -exclusive on

Microsoft (R) .NET Framework CasPol 1.1.4322.573

Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

 

Added union code group with "-url" membership condition to the User level.

Success

 

[C:scripts]
serialise.exe

Creating

constructed

Serializing

 

Unhandled Exception: System.Security.SecurityException: Request for the permission of type System.Security.Permissions.SecurityPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 failed.

   at System.Security.CodeAccessSecurityEngine.CheckHelper(PermissionSet grantedSet, PermissionSet deniedSet, CodeAccess

Permission demand, PermissionToken permToken)

   at System.Security.CodeAccessSecurityEngine.Check(PermissionToken permToken, CodeAccessPermission demand, StackCrawlMark& stackMark, Int32 checkFrames, Int32 unrestrictedOverride)

   at System.Security.CodeAccessSecurityEngine.Check(CodeAccessPermission cap, StackCrawlMark& stackMark, PermissionType permType)

   at System.Security.CodeAccessPermission.DemandInternal(PermissionType permissionType)

   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)

   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)

   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)

 

   at Program.Main()

 

The state of the failed permission was:

<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

             version="1"

             Flags="SerializationFormatter"/>

The attack I posted yesterday would succeed even in the Internet zone, assuming that a highly-trusted assembly had been produced by a compiler that generated public static constructors.