Tag Archives: String

Exploit using System.String? Not Really

I’ve been playing around in the CLR for some time just playing with quirks and oddities.  I  noted some time ago that non-printable characters were easily stored in strings.  This really wasn’t a suprise except that a null character (“”) could be stored and appropriately retrieved from a string.  If I embedded a null character in a string, it didn’t cause the string to truncate when I read it back.  This made me wonder just how the string class knew how large its buffer was. How did it know which null character was it’s terminator?

Since my upcoming book deals, in part, with Reflection, I decided to try some playing around with the string object using MemberInfo. I found something rather interesting.  The string class keeps track of how large its buffer is in a member variable called m_stringLength.  So I started to wonder, what would happen if I created a string and then used reflection to change the length?

I decided to make this interesting.  I first created an example class that would represent a class handling sensitive data.  My code was simple and was as follows:

using System;

namespace CodeWithSecrets {

  // Lets assume this is a class that handles connection strings
  // or other sensative data.
  class ConnectionStringGuardian {
     public ConnectionStringGuardian() {
        connect = "uid=sa;pwd=LoveSexSecretGod";
     }
  }
}

I put this class in its own class library assembly named “CodeWithSecrets”. Then came the code that I would use to exploit the “ConnectionStringGuardian” class. 

using System;
using System.Reflection; 
using CodeWithSecrets;

namespace MalCode{ 
  class Malware {
    [STAThread]
    static void Main(string[] args) {
      ReadPastBuffer();
    }
    private static void ReadPastBuffer() {
      // Storing some variable
        String stringObj = "12345"; 
      // Store an object with private data in it
        ConnectionStringGuardian obj = new ConnectionStringGuardian();
      // Getting the String Type
        Type stringType = Type.GetType("System.String");
      // Getting a reference to the private field in System.String 
        FieldInfo fi = stringType.GetField( "m_stringLength", 
          BindingFlags.Instance|BindingFlags.NonPublic);
      // Read the string object 
        Console.WriteLine( "Reflected String: '{0}'", stringObj );
      // Set the private variable that keeps track of string length;
        Object parameter = 255;
        fi.SetValue( stringObj, parameter );
      // Read the reflected string  
      Console.WriteLine( "Expanded Buffer: '{0}'", stringObj );
      Console.ReadLine();
    }
  }
}

To explain what I’ve done here, I created a typical string holding an arbitrary value.  I then create an instance of my class that holds secret data.  Using reflection, I then access the private m_stringLength member to increase the size of the string’s buffer to 255. Finally, I output my string to the console to see if I can read past my buffer in a managed string. As you’ll notice, I write the string’s value to the console before increasing the buffer size, and then I write the strings value to the console again after modifying the buffer size.  The following screen shot depicts the results:

Malicious Code

Notice that I was able to read past the buffer and into the memory where the sensitive data was stored.  (First person to name the movie the sample password comes from gets a free Apress t-shirt if you send me your address.)

Now this is not really an exploit other than the fact that I can read memory to possibly sensitive data.  I tried to do other things to the memory such as stomp on it by calling the private “NullTerminate()” method that I found using reflection as well.  NullTerminate writes a null terminator at the end of a buffer using the m_stringLength value to determine just where to put that value.  This, unfortunately, did not overwrite the data in memory as I was expecting.  Ultimately, I was thinking that I might be able to break the type safety of an assembly by stomping on memory belonging to an instance. 

The problem with this code (or perhaps the good thing to note if you are an MS security expert) is that I have to use reflection to pull this off. I wouldn’t be able to execute this in a partial trust environment. If I downloaded this code in the internet zone, the reflection permission is not permitted by default. This severely cripples my attempts to make this tidbit worthwhile.  As Michael Howard responded to me: “fully trusted code is fully trusted code.”  True enough.

In any case, I hope this serves as some sort of education in some more internals of the string class. Let me know what you think. 

(P.S. No need to make the obvious statement that sensitive data shouldn’t be stored in classes.)

More String / StringBuilder Quirks

Circular References Between Classes:
I find it odd just how many circular references there are between StringBuilder and String. String.Format uses StringBuilder.AppendFormat while the StringBuilder.Chars property uses String.SetChar() (an internal method).

Unsafe Code and Unmanaged Code, No Assert?
While it is true that String, StringBuilder, and most other .NET assemblies use unmanaged and unsafe code. So why don’t you need to need to assert these permissions when using these common classes? The answer is not anything magical. Microsoft has to follow the same rules for Code Access Security and permissions that everyone else does. It just so happens that Microsoft has added their rules by default. Consider the following statement: Evidence + Policy = Permissions. OK so it’s not exact and you math majors out there might be wrything in your seats. But the basics are that an assemblies evidence is combined with code access security policy to yield all the permissions an assembly has. Do Microsoft-compiled assemblies have some special piece of evidence? Not special evidence, just your standard, every day Microsoft Strong Name evidence. Microsoft has added, during its installation, a rule that gives their strong name “full trust” permissions. You can view this in your .NET framework configuration 1.1 control panel applet. Navigate to the Security policy | Machine | My_Computer group. Under this group is the Microsoft and ECMA rules which provide the access your applications need to call the unsafe and unmanaged code in Microsoft assemblies.

Char Pointers? Why through StringBuilder but not through String?
I’m wondering why in the world StringBuilder.Chars would give access to the individual characters of a string (appropriately referenced through unsafe code pointers), but String.Chars hides this functionality, sticking to read-only access to the character indexer. I can understand, to some degree, that this might have been for thread-safety reasons. But, really, why do I have to create a StringBuilder if I want to use the faster user of pointers to modify individual characters in my string? Again, I can also understand that Microsoft might have wanted to limit the footprint of the string class since it is one of the native data types of .NET and is used so often. However, since the actual method (SetChar) that modifies the data is found in the string class anyway (back to that circular reference thing again) why wouldn’t you just make this available from the instance?

I have more problems with the behavior of these two classes, but really, who wants to write all those problems down?

String.Format vs StringBuilder.AppendFormat

So here’s a question, what’s the difference between String.Format( string, object[]) and StringBuilder.AppendFormat( string, object[] ) ?

For those of you thate don’t know, String.Format allows you to parameterize your strings, by placing replacement tokens througout a string template.  You can later fill in those tokens with parameterized data by passing it in as an array. Here is an example:

string.Format("I own a {0} and {1} name is '{2}'", 
        "cat", "her", "Ellie" );

Of course this would output the sentence: “I own a cat and her name is ‘Ellie'”.  You can also achieve the same thing by calling StringBuilder.AppendFormat much like the following example:

StringBuilder sb = new StringBuilder();
sb.AppendFormat( "I own a {0} and {1} name is {2}", 
        "cat", "her", "Ellie" );

At first glance, you may be thinking that these are somewhat interchangable with the exception of performance. By now, we all know StringBuilder is usually faster for excessive string manipulation. What you may not know is that string.format calls the StringBuilder.AppendFormat method under the hood.  Additionally, StringBuilder will throw an exception if the number of parameters does not match the number of tokens found in the template string.  Try compiling and running a program that executes the following statement:

[STAThread]
static void Main(string[] args) {
  string x = string.Format(
    "{4} owns a {0} and {1} name is {2}.", "cat", "her", "Ellie" ); 
  Console.WriteLine( x );
  // For those of you that know WriteLine takes format strings... shhhhh
  // I'm trying to make a point here!
}

You will receive the following exception.

An unhandled exception of type 'System.FormatException' 
occurred in mscorlib.dll

Additional information: Index (zero based) must be greater 
than or equal to zero and less than the size of the argument 
list.

This exception is actually thrown by StringBuilder.AppendFormat and the String.Format method bubbles the exception up without providing the consumer with any recourse if the parameters dont’ match up.  However, if you call StringBuilder.AppendFormat yourself, you can place the code in a try catch block, and reap the benefits of a string that has been formatted as best as it can be with the parameters provided. Take the following code, for instance:

[STAThread]
static void Main(string[] args) { 
  StringBuilder sb = new StringBuilder();
  try {
    sb.AppendFormat( "{0} owns a {1} and {2} name is {3}.",
        new object[] {"Tobin", "cat", "her"} );
  }
  catch(FormatException ex) {
    Console.WriteLine("An exception occurred: {0}", ex.Message ); 
  }
  finally { 
    Console.WriteLine( sb.ToString() ); 
  } 
  Console.ReadLine();
}

Notice here that we have caught the exception, reported on it, but can still write the string builder’s text to the screen — or at least the part that was parsed.

Now here’s the questions I pose for all of you:

  1. Since you now know that you can bypass the token-count to parameter-count validation check by using StringBuilder, should you incorporate this into your applications in instances where you don’t know how many parameters you are going to have?
  2. Would you consider this to be a bug, or a reasonable feature and why?