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.
Comments
- Anonymous
January 27, 2004
The comment has been removed - Anonymous
January 28, 2004
Well, ya never know these days. Thanks for clearing that up :-) - Anonymous
January 30, 2004
The comment has been removed