More on privates...

Wes asked exactly how private is private this past week, showing how reflection can be used to modify private fields and invoke private methods.

After giving it some thought, and discussing it with a few colleagues, I guess we can consider access modifiers not a security feature so much as a way to encapsulate internal implementation details. And sure, the general assumption is that anything in memory is never really "private", because someone somewhere can always touch it. But I still have a tough time getting my head around this, because it kind of violates a lot of what you're taught from day one when it comes to OOP.

Then again, I should be used to this, after all the crazy Javascript I've done over the past two years. Javascript is really powerful in this regard - if powerful is the right word. Not only does Javascript have no means to enforce access modifiers, it allows you to change an instance's composition at runtime. Hell, you can even mess with an object's prototype, effectively modifying any new instances of that object.

This should also teach us, I guess, that we can't take the validity of private fields for granted. For example, if the only place we're doing validation is in a property modifier, it leaves the door open to potential, unexpected behavior.

I expanded on Wes' original example a little, and using a built-in .NET type instead of using a custom class.

string s = "test"; t = s.GetType();
FieldInfo[] fields = t.GetFields( BindingFlags.Instance | BindingFlags.NonPublic );
foreach (FieldInfo field in fields)
{
   if (field.IsPrivate && field.FieldType == typeof(int))
   {
      field.SetValue(s,3000);
   }
}
Console.WriteLine(s);

Now, bear in mind I don't know much (read: anything) about buffer overflows or how the CLR handles memory and so on (maybe it's time to get that book sooner than I thought), but it seems like this could be bad. Would it be possible, for example, to touch other AppDomains (on shared ASP.NET hosting) with this, or even worse, to break out of the .NET sandbox?

Published Thursday, March 06, 2003 11:01 PM by Tim Marman

Comments

# More on privates... : ShowUsYour-Blog!

Thursday, March 06, 2003 11:01 PM by TrackBack
More on privates... : ShowUsYour-Blog!

# Loosely Coupled

Thursday, March 06, 2003 11:01 PM by TrackBack
Loosely Coupled

# re: More on privates...

Friday, March 07, 2003 3:59 AM by Jamie Cansdale
> Would it be possible, for example, to touch other
> AppDomains (on shared ASP.NET hosting) with this,
> or even worse, to break out of the .NET sandbox?
>
I know you can't touch fields accross app domain/remoting boundries. It seems you can call private methods (see test code below).

There is no managed way of enumerating app domains. Security is out of the window if you pass a remote handle to an app domain out. If you're running with full trust you can use COM Interop to enumerate app domains like this...
http://dotnetweblogs.com/NUnitAddin/archive/02072003.aspx

On a related note, it's also possible to create an object without calling its constructor! For example...

using System.Runtime.Serialization;
MyClass c = (MyClass)FormatterServices.GetUninitializedObject(typeof(MyClass));

Here are some unit tests showing what is and isn't possible with private fields, methods...


using System;
using System.Runtime.Remoting;
using System.Reflection;
using System.Diagnostics;
using System.Runtime.Serialization;
using NUnit.Framework;

namespace Tests
{
[TestFixture]
public class TestPrivateStuff
{
[SetUp]
public void SetUp()
{
_domain = AppDomain.CreateDomain("TestDomain");
_local = new TestClass();
_remote = (TestClass)_domain.CreateInstanceFromAndUnwrap(typeof(TestClass).Assembly.CodeBase, typeof(TestClass).FullName);
}
private AppDomain _domain;
private TestClass _local;
private TestClass _remote;

[TearDown]
public void TearDown()
{
AppDomain.Unload(_domain);
}

[Test]
public void TestUninitializedObject()
{
TestClass tc = (TestClass)FormatterServices.GetUninitializedObject(typeof(TestClass));
As

# re: More on privates...

Friday, March 07, 2003 4:03 AM by Jamie Cansdale
Sorry about that. The tests are here...

http://www.mutantdesign.co.uk/nunit-addin/blog/PrivateTests.txt

# re: More on privates...

Friday, March 07, 2003 5:42 AM by Tim Marman
Jamie -

Thanks! I'm going to take a look at the code and start playing with it. The whole thing just seemed really odd to me!

# re: More on privates...

Friday, May 02, 2003 2:38 PM by Craig
Here's a question:

Can you invoke methods on objects that are instantiated within the class you are reflecting? Good example is a Windows Form, can you change the text in one of the TextBoxes?

Leave a Comment

(required) 
(required) 
(optional)
(required)