March 2006 - Posts

More information on http://www.microsoft.com/presspass/press/2006/mar06/03-27BizTalk2006RTMPR.mspx. With BizTalk 2006, the release wave around .NET 2.0, SQL Server 2005 and Visual Studio 2005 comes to its end. Time to play with the golden trio of RTM'ed techologies and on to Orcas and Vista now :-).

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Introduction

Within a couple of weeks, our series of MSDN Security Evenings will go on air at various locations (see http://community.bartdesmet.net/blogs/bart/archive/2006/03/25/3841.aspx for more information). It's pretty clear developers care about security (maybe just not enough yet) and so I received a couple of mails last week with questions about security in the world of .NET. Keep those mails coming guys! One of the questions was about the new System.Security.SecureString class. The MSDN Documentation is rather limited:

Represents text that should be kept confidential. The text is encrypted for privacy when being used, and deleted from computer memory when no longer needed. This class cannot be inherited.

And so, I decided to write a bit more about this new feature. Actually, the most common problem with the .NET Framework documentation is the lack of "forward references" which indicate where a certain class is being used elsewhere in the framework. Of course, this wouldn't make sense for things such as System.Int32 or System.String but for something like System.Security.SecureString it would be a handy piece of documentation indeed. Samples on how to use this class in a real scenario are just missing, so read on to learn more.

 

What's in a name?

So, what's the goal of the System.Security.SecureString class, or even more, why is the System.String class not secure that we need a new class? The answer is not so straightforward and you need a bit of insight on how strings work in the .NET Framework and what the troubles are because of the "string approach". Assume you have a string which contains a credit card number, or a social security ID, or a password, or a pin-code, or whatever that has to remain confidential. In order for your application to work with it, you'll need to keep that secret somewhere in memory. But where's "somewhere"? And how is the thing stored? Both questions deserve a proper answer. The latter one is the most straightforward to answer and its answer is just "in plain text". So, when somebody can read your memory (which is - as the matter in fact - not so difficult to do if security on the machine is compromised; notice a buffer overrun attack isn't a possibility in safe verifiable managed code), the data can be stolen pretty easy. The other question about where the data lives is a bit more difficult to understand. First of all, strings in .NET are immutable. This means that string concatenation creates a new string (if you aren't using the System.Text.StringBuilder utility class, see http://community.bartdesmet.net/blogs/bart/archive/2005/10/04/3583.aspx). Assume the following:

string password = "";
while (condition)
{
   char someChar = ...; //get from Console.ReadKey() for example
   password += someChar;
}

Over here, you're just creating a bunch of additional intermediary string instances which contain fragments of the password the user is typing: "H", "He", "Hel", "Hell", "Hello", ... This wouldn't be much of a problem if you could remove the string from memory in a deterministic way when it's not used anymore. However, memory reclaim of strings is totally undeterministic due to the use of the garbage collector. As the matter in fact, the garbage collector also introduces an additional problem. As you know, the managed memory space is divided in generations. When an object survives generation 0, it will be propagated to generation 1 (the same applies for generation 1 to generation 2). Basically, this means that a copy of the original string is created and stored elsewhere in memory. The phantoms will eventually be overwritten but you don't know when. So, you know when the confidential information enters the memory of your computer, but you don't know when it leaves again. You're out of control now :S.

This is where the SecureString comes into play. Basically, it solves the two problems listed above as follows:

  • the string content is stored in memory in an encrypted fashion, using DPAPI (because of this, it will only work on NT-based platforms and not on Windows 98 or Millennium (in contrast to what the "Platforms" section in the MSDN documentation tells you);
  • to allow more deterministic clean-up, SecureString follows the IDisposable pattern;
  • you can't retrieve the stored string in clean text easily from a SecureString instance, to reduce the risk of fatal accidents (once a SecureString becomes a normal String, all problems are reintroduced again).

 

The internals

So, how does this thing work? Let's start with the signature of SecureString:

public sealed class SecureString : CriticalFinalizerObject, IDisposable

The key takeaway from this signature is that the SecureString class implements IDisposable and so you will do something like:

using (SecureString str = new SecureString())
{
   //perform work
}

to ensure proper cleanup by calling the Dispose method implicitly (and automatically). Secondly, the SecureString class inherits from the System.Runtime.ConstrainedExecution.CriticalFinalizerObject abstract class. The CriticalFinalizerObject ensures that finalization code is marked as critical and is allowed to run always. In order to do make this possible, the finalization code must follow the rules of a Constrained Execution Region. Integration of the CLR in SQL Servr 2005 was one of the reasons why CER's where born in .NET v2.0 in order to allow the CLR to be hosted in a reliable environment where proper clean-up is a must-have (think of a transactional context). Due to this implementation, the finalizer is allowed to run always, even when the runtime performs a rude thread abort or unloads an application domain, cases where finalization of normal objects is not always guaranteed.

Inside the SecureString class, data is just kept in a piece of unmanaged memory space, outside the control of the garbage collector. By doing so, the user/application is in control of the time when the memory space is cleaned up, rather than having to rely on the garbage collector to come around. On to the relevant public members of the class:

  • void AppendChar(char) - appends one character to the end of the string
  • void InsertAt(int, char) - inserts a character in the string on the given position
  • void RemoveAt(int) - removes a character from the string on the given position
  • void SetAt(int, char) - sets a character in the string on the given position
  • void Clear() - deletes the string's value
  • SecureString Copy() - creates a copy of the string
  • void IDisposable:Dispose() - releases all resources used by the SecureString instance behind the scenes
  • void MakeReadOnly() - makes the string read-only (irreversible)
  • bool IsReadOny() - checks whether the string is read-only

As you can see, it's impossible to get the contents of a SecureString instance directly. The ToString() method derived from System.Object isn't overridden either, to prevent you from getting the secure data accidentally in managed memory space, with all the associated problems mentioned above.

 

Getting the data

Putting data in there is one thing, but ghetting it out of it is another crucial thing. If you can't (and shouldn't even try) to convert a SecureString to a normal String instance, how to use the data inside? The answer is using the Marshal class to convert the SecureString to ANSI or Unicode or a BSTR. Those methods (of System.Runtime.InteropServices.Marshal) include:

  • Marshal.SecureStringToCoTaskMemAnsi
  • Marshal.SecureStringToGlobalAllocAnsi
  • Marshal.SecureStringToCoTaskMemUnicode
  • Marshal.SecureStringToGlobalAllocUnicode
  • Marshal.SecureStringToBSTR

Once you've used the data, you need to free (and zero out) the unmanaged memory space you've been using to put the (decrypted) string in. The code pattern looks like this:

IntPtr bstr = Marshal.SecureStringToBSTR(ss);

try {
   // use the bstr
}
finally {
   if (IntPtr.Zero != bstr)

      Marshal.ZeroFreeBSTR(bstr);
}

An alternative is to use unsafe code with a pointer in C#:

unsafe
{
   Char* pDecryptedString;
   try {
      // use the string
   }
   finally {
      if (null != pDecryptedString)
         Marshal.ZeroFreeCoTaskMemUnicode(pc as IntPtr);
   }
}

The code listed above is only applicable to developers who need to get a password (or another secret) in a secure fashion and forward it to an (unmanaged) piece of code. However, as a "normal" developer you're likely more interested in BCL classes which use SecureString out of the box.

 

Using it

Let's take a look at the BCL classes that use SecureString first of all. When investigating the .NET Framework API you'll come to the conclusion SecureString isn't used that much yet. One place where you'll find SecureString is in the System.Diagnostics.ProcessStartInfo's Password property. Other places I'm aware of are the System.Security.Cryptography classes (more specifically when working with Crypto Service Providers and X.509 Certificates). Useful 3rd party projects include the following:

The most common SecureString example however is to use the Console to read a password and store it in a SecureString instance. A sample can be found on the .NET Security Blog but notice keys such as F1, Home, End, media buttons, etc are intercepted by Console.ReadKey(true) too, so you might want to add additional logic to filter those out (see ConsoleKey class). Also don't forget to apply a MakeReadOnly() at the end.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Last weekend I installed the latest CTP build of Windows Vista (build 5342) on my new laptop. However, one of the problems I ran into was the lack of the new Aero Glass experience right after the installation. As you might know, Vista is self-tuning in order to enable only the functionality that will work for sure on your machine based on a "hardware performance measurement". It happened to be the case that my machine was rated with a poor 1 which causes the system to disable Aero Glass. In order to fix it, I went to the Control Panel, System and Maintenance, Performance Rating and Tools and re-ran the performance rating process which takes a couple of minutes. Now I have a rating of 3 and Aero Glass :-). And of course the killer demo for Vista's graphics richness, Windows-TAB, works fine (except for the bug which takes the Start Menu's Windows logo in the programs list).Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

For everyone out there caring about security (this filter clause should be a tautology) this blog post should be the trigger to a "start downloading immediately" action. So here's the link: http://www.microsoft.com/downloads/details.aspx?familyid=aa5589bd-fb2c-40cf-aec5-dc4319b491dd&displaylang=en. Formerly codenamed ACE Torpedo, the Microsoft Threat Analysis & Modeling tool allows non-security subject matter experts to enter already known information including business requirements and application architecture which is then used to produce a feature-rich threat model. Along with automatically identifying threats, the tool can produce valuable security artifacts such as:

- Data access control matrix
- Component access control matrix
- Subject-object matrix
- Data Flow
- Call Flow
- Trust Flow
- Attack Surface
- Focused reports

(Summary grabbed from download site)

Other links to bookmark in your favorites folder about security:

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

To continue my evangelism of .NET Framework 2.0 features, I'm going to focus on friend assemblies in today's post.

The old story

Go back to the .NET Framework 1.x era and think of the various visibility modifiers you can apply on types and members. One of those visibility modifiers is internal which basically states that the type (let's stick with types) is only visible inside the assembly to which it belongs. This is very useful in quite some scenarios where you need some helper types to aid in the internal workings of an assembly containing some functionality. However, the scalabilty of internal in .NET Framework 1.x is rather limited because you can't span "internal types" across multiple assemblies which are created by various teams. As the matter in fact, you'd like to group a series of assemblies an make them all "friends" living together in peace, relying on each other's internal types. That's exactly what you need if you start writing software in group and you decide that various teams will be responsible to create some helper (and other have-to-be-internal) types but it's infeasible to make them work on the same assembly (or if you just want to divide the internal types across mutliple assemblies for any reason whatsoever).

Now, how does this look like? The only way I'm aware of to get around this problem using .NET FX 1.x is by using Code Access Security (CAS), more specifically the StrongNameIdentityPermission class which can be used to demand that the caller's identitty matches a given identity (based on a strong name which you should be familiar with). In code you'll get the following:

[StrongNameIdentityPermission(SecurityAction.LinkDemand,
PublicKey=
"
0024000004800000940000000602000000240000525341310
00400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9
e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9
ad236132102900b723cf980957fc4e177108fc607774f29e8
320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d6
22caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a
12436518206dc093344d5ad293"
)]
public class
ProtectedUtility //only callable by my "friends"
{

   ...
}

<Game>Find the public key owner.</Game>

This means that only assemblies with the given public key will be able to use the functionality defined in ProtectedUtility. Notice additional properties can be set on the StrongNameIdentityPermission attribute, such as Name and Version.

 

The new "friendly" story

.NET Framework 2.0 frees you from this burden of having to declare a bunch of StrongNameIdentityPermissions to accomplish the aforementioned goal. Now, the concept of "friend assemblies" is known by the runtime and you as a developer can take advantage of this. All you have to do now is to change the AssemblyInfo.cs file (well, as the matter in fact, you can put the attribute I'm going to show you everywhere but in VS2005 solutions the AssemblyInfo.cs file is the most convenient place to put it in) and add the following attribute:

[assembly: InternalsVisibleTo("SomeBodySpecial,
0024000004800000940000000602000000240000525341310
00400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9
e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9
ad236132102900b723cf980957fc4e177108fc607774f29e8
320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d6
22caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a
12436518206dc093344d5ad293
"
)]

The difference with the oldfashioned way to do this is of course the fact that this attribute applies to the whole assembly and every internal type in it, rather than the explicitly marked types. Also notice you don't have to declare the members you want to make visible outside the assembly as public (which was a need to work with StrongNameIdentittyPermission). One little caveat is that you need to specify the /out: compiler parameter when compiling the friend assembly (that's the one which is referring to the assembly that "exports" internal types in the way outlined above) so the system knows the identity upfront in order to determine whether it's a friend or not. Luckily, VS2005 takes care of this (by design).

There is however one situation in which the old way of working still is the better way to do this kind of stuff and that's when the assemblies don't ship together and you want to avoid compatibility problems. In such a case a publicly visible type is the better choice, restricted in its usage by means of a StrongNameIdentityPermission link demand.

A few remarks to conclude:

  • The syntax of the InternalsVisibleTo parameter has to be name, public key. A public key token is not allowed and both elements have to be present in the declaration (name and public key). Note: you can retrieve the public key of a strong-named assembly using sn -Tp <assembly>.
  • Friends of a strongly-named assemblies have to be strongly-named too.
  • Of course, InternalsVisibleTo means exactly what it tells: it only exposes types and members declared as internal to the friends.
  • You can declare more than one InternalsVisibleTo per assembly, whileas it's not possible to have more than one StrongNameIdentityPermission on a type.
  • Friend declarations are explicit-only and are not inferred. Therefore, the is no transitive property ("the friends of my friends are my friends" doesn't hold in this context, luckily!).
  • Friendship is a non-commutative relationship. If A is a friend of B, then B is not automatically a friend of A. Whether this matches the real world is a filosophical question which falls outside my domain of expertise :-).
Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Still working with Visual Studio .NET 2003? (I am for my .NET FX 1.1 development projects that can't be upgraded to 2.0 yet!) Then you'll be interested in Visual Studio.NET 2003 Service Pack 1 Beta which is available on http://connect.microsoft.com now (under Available Programs). RTM of this SP is pinned on June 1st 2006. The first Service Pack for Visual Studio 2005 is due Q3 this year.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

For those of you interested in compiler technologies and enhancements, the Microsoft Research Phoenix project will be worth to take a look at. A short introduction:

Phoenix is the code name for a software optimization and analysis framework that is the basis for all future Microsoft compiler technologies. The Phoenix framework is an extensible system that can be adapted to read and write binaries and MSIL assemblies and represent the input files in an IR, which can be analyzed and manipulated by applications by using the Phoenix API. The code can then be written in binary or JITable form for execution.

More information on http://research.microsoft.com/phoenix/.Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

MSBee is the codename for MSBuild support for .NET Framework 1.1 (Everett) projects. It's being developed by the Developer Aftermarket Solutions and Powertoys team. The beta 2 release of MSBee can be found on http://www.gotdotnet.com/codegallery/codegallery.aspx?id=22a73581-57c1-4874-a7d5-c9138c8c1f4b.Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

I'm very happy to announce the MSDN Security Evenings in Belgium where I'll deliver an (approx) 2h30 Dutch-speaking talk about the art of secure programming in various high schools/universities throughout the country. For the French-speaking part of Belgium, Grégory Renard will deliver a talk. More information can be found on http://www.microsoft.com/belux/nl/msdn/events/2006/securityevenings.mspx.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

BIGBOY, that's the name of my new laptop. I was a very surprised to come home and find a new machine on my desk. The machine was ordered on Sunday, payment was done on Monday, and now, Friday, the machine has already been assembled and delivered at home. Congratulations to Dell! What about the specifications? Here we go:

  • Dell Inspiron 9400
  • Intel ® Core™ Duo Processor T2600 (2.16 GHz, 2 MB L2 cache, 667 MHz FSB)
  • Windows® XP Media Center Edition 2005
  • 2048MB 667MHz DDR2 SDRAM (2x1024)
  • 100GB (7,200 rpm) SATA Hard Drive
  • 17" UltraSharp™ Wide Screen WUXGA (1920 x 1200) Display with TrueLife™
  • 256MB DDR ATI® MOBILITY™ RADEON® X1400 graphics card, PCI-Express x16
  • 8X DVD+/-ReWriter Drive
  • 9 Cell 80 WHr battery
  • Intel® Pro WLAN 3945 Internal Wireless (802.11a/b/g 54 Mbps) for Duo Processors
  • Dell Wireless 350 Bluetooth 2.0 Module

A killer machine (I hope)! The most annoying thing of having a new laptop from some vendor is all of the software that comes with it and the default settings. As the matter in fact, I'm used to a 1920 x 1200 resolution but the configuration "downgrades" this because of larger font sizes etc (even making images look blurry on the screen). Further on, the machine contains stuff such as McAfee free trial, Corel Photo Center, a Modem Helper and even Microsoft Works (have never used this product in my life). So the very next thing that will happen is a repartitioning of the harddisk and a reinstall of the machine using the software I want and with the configuration I want. Installation time (which will be difficult because I forgot to bring home my MSDN DVD's)!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

More Posts Next page »