Not calling your parent constructor

Not calling your parent constructor

  • Comments 4

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:\scripts\noconstructorhack.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:\scripts\noconstructorHack.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:\scripts\serialise.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.

  • Yep, I wasn't trying to imply that it's a security hole, just a feature to be used and abused.

    And she's a he :-)


    Jim
  • Well, ya never know these days. Thanks for clearing that up :-)
  • Here is a way to not call your parent constructor (that works in partially trusted code):

    public class Base
    {
    public Base(int i)
    {
    System.Console.WriteLine("don't run me");
    }
    }

    public class Derived : Base
    {
    public Derived()
    : base(Throw())
    {
    }

    static int Throw()
    {
    throw new System.Exception();
    }

    ~Derived()
    {
    cheat = this;
    }

    static void Main()
    {
    try
    {
    new Derived();
    }
    catch {}
    System.GC.Collect();
    System.Console.WriteLine(cheat);
    }

    static Derived cheat;
    }

Page 1 of 1 (3 items)