Click to Rate and Give Feedback
Related Articles

This month we demonstrate how easy it is to use IronPython to test .NET-based libraries.

James McCaffrey

MSDN Magazine June 2009

...

Read more!

Here we examine data persistence patterns to help you determine which best suits your needs. We look at a number of patterns, including the Active Record, the Data Mapper, the Repository, the Identity Map, the Lazy Loading, and the Virtual Proxy.

Jeremy Miller

MSDN Magazine April 2009

...

Read more!

In this article, we show you how to integrate a Windows Services-based solution with SharePoint. The results enable you to provision, start, stop, and remove service instances through SharePoint 3.0 Central Administration.

Pav Cherny

MSDN Magazine April 2009

...

Read more!

Udi Dahan explains how his team identified and overcame unforeseen problems while developing a large-scale software + services trading application.

Udi Dahan

MSDN Magazine April 2009

...

Read more!

Microsoft Velocity exposes a unified, distributed memory cache for client application consumption. We show you how to add Velocity to your data-driven apps.

Aaron Dunnington

MSDN Magazine June 2009

...

Read more!

Also by this Author

Access control lists (ACLs) can be complex beasts, and user interfaces for editing them are incredibly tricky to implement properly. That's why I was really excited when Windows® 2000 shipped with a programmable ACL editor, shown in Figure 1.

Keith Brown

MSDN Magazine March 2005

...

Read more!

Now that Windows Server 2003 is widely deployed, Keith Brown addresses questions from readers who are trying to use protocol transition to build secure gateways into their intranets.

Keith Brown

MSDN Magazine January 2007

...

Read more!

GINA, the Graphical Identification and Authentication component, is a part of WinLogon that you can customize or replace. Last month I introduced GINA customization; this month, I'm going to drill down to implement each of the GINA entry points.

Keith Brown

MSDN Magazine June 2005

...

Read more!

This month Keith Brown fields some reader questions on InfoCard turned CardSpace and passwords for SqlMembershipProvider.

Keith Brown

MSDN Magazine October 2006

...

Read more!

Over the years I've had many people ask me to write about GINA, the Graphical Identification and Authentication component that serves as the gateway for interactive logons. This month I'll begin my coverage of this topic to help you get started if you're tasked to build such a beast.

Keith Brown

MSDN Magazine May 2005

...

Read more!

Popular Articles

One-time passwords offer solutions to dictionary attacks, phishing, interception, and lots of other security breaches. Here's how it all works.

Dan Griffin

MSDN Magazine May 2008

...

Read more!

C# allows developers to embed XML comments into their source files-a useful facility, especially when more than one programmer is working on the same code. The C# parser can expand these XML tags to provide additional information and export them to an external document for further processing. This article shows how to use XML comments and explains the relevant tags. The author demonstrates how to set up your project to export your XML comments into convenient documentation for the benefit of other developers. He also shows how to use comments ...

Read more!

Chris Tavares explains how the ASP.NET MVC Framework's Model View Controller pattern helps you build flexible, easily tested Web applications.

Chris Tavares

MSDN Magazine March 2008

...

Read more!

Here we present techniques for programmatic and declarative data binding and display with Windows Presentation Foundation.

Josh Smith

MSDN Magazine July 2008

...

Read more!

A Sidebar gadget is a powerful little too that's surprisingly easy to create. Get in on the fun with Donavon West.

Donavon West

MSDN Magazine August 2007

...

Read more!

Security Briefs
Hashing Passwords, The AllowPartiallyTrustedCallers Attribute
Keith Brown

Code download available at: SecurityBriefs0308.exe (110 KB)
Browse the Code Online

Q How can I store passwords in a custom user database?
Q How can I store passwords in a custom user database?

A There are several options. The simplest might leave you with cleartext passwords. The following example is XML, but you could easily use a database table:
<users>
  <user name='Alice' password='7&y2si(V1dX'/>
  <user name='Bob'   password='mary'/>
  <user name='Fred'  password='mary'/>
</users>
After implementing something like this, you'll likely feel rather uncomfortable that all those passwords are sitting there in one file, in the clear. If you don't feel uncomfortable, you should! This makes it way too easy for an attacker who compromises your system to walk away with user passwords without even breaking a sweat. And, if this happens, it's not just your site that could feel the repercussions—most people use the same password for multiple sites. A stolen password is a privacy violation for the user, and frankly, if you didn't do anything to protect those passwords, you're to blame.
A There are several options. The simplest might leave you with cleartext passwords. The following example is XML, but you could easily use a database table:
<users>
  <user name='Alice' password='7&y2si(V1dX'/>
  <user name='Bob'   password='mary'/>
  <user name='Fred'  password='mary'/>
</users>
After implementing something like this, you'll likely feel rather uncomfortable that all those passwords are sitting there in one file, in the clear. If you don't feel uncomfortable, you should! This makes it way too easy for an attacker who compromises your system to walk away with user passwords without even breaking a sweat. And, if this happens, it's not just your site that could feel the repercussions—most people use the same password for multiple sites. A stolen password is a privacy violation for the user, and frankly, if you didn't do anything to protect those passwords, you're to blame.
The first approach you might take to protect these passwords is to encrypt them. That's better than nothing, but it's not the best solution either. In order to validate a user's password, you need the encryption key, which means it needs to be available on the machine where the passwords are processed. While this does raise the bar a bit because the attacker must find the key, there's a better solution that doesn't require any key at all: a one-way function.
A cryptographic hash algorithm like SHA-1 or MD5 is a sophisticated one-way function that takes some input and produces a hash value as output, like a checksum, but more resistant to collisions. This means that it's incredibly unlikely that you'd find two messages that hash to the same value. In any case, because a hash is a one-way function, it can't be reversed. There is no key that you need to bury. So let's imagine you hash the password before storing it in the database:
<users>
  <user name='Alice' password='D16E9B18FA038...'/>
  <user name='Bob'   password='5665331B9B819...'/>
  <user name='Fred'  password='5665331B9B819...'/>
</users>
Now when you receive the cleartext password and need to verify it, you don't decrypt the stored password for comparison. Instead, you hash the password provided by the user and compare the result with your stored hash. If an attacker manages to steal your password database, he won't immediately be able to use the passwords, as they can't be reversed back into cleartext. But look closely at Bob and Fred's hashed passwords. If the attacker happened to be Fred, he now knows that Bob uses the same password he does. What luck! Even without this sort of luck, a bad guy can perform a dictionary attack against the hashed passwords to find matches.
The usual way a dictionary attack is performed is to get a list of commonly used passwords, like the lists you'll find at ftp://coast.cs.purdue.edu/pub/dict/wordlists, and calculate the hash for each. Now the attacker can compare the hash values of his dictionary with those in the password database. Once he finds a match, he looks up the corresponding password.
To slow down the attack, use salt. Salt is a way to season the passwords before hashing them, making the attacker's precomputed dictionary useless. Here's how it's done. Whenever you add an entry to the database, you calculate a random string of digits to be used as salt. When you want to calculate the hash of Alice's password, you look up the salt value for Alice's account, prepend it to the password, and hash them together. The resulting database looks like this:
<users>
  <user name='Alice' salt='Tu72*&' password='6DB80AE7...'/>
  <user name='Bob'   salt='N5sb#X' password='096B1085...'/>
  <user name='Fred'  salt='q-V3bi' password='9118812E...'/>
</users>
Note that now there is no way to tell that Bob and Fred are using the same password. Note that the salt itself isn't a secret. The important thing is that it's different for each user account, so generating a random string of digits based on output from RNGCryptoServiceProvider would work fine.
Figure 1 summarizes the levels of security. Once you decide to store hashed passwords, you'll realize there's no way to e-mail the user their password if they forget what it is. This is a good thing! It's pretty silly to e-mail passwords. Take a lesson from paypal.com. They store a set of questions and answers, like "What is your pet's name?" and "What city were you born in?" To change your password, you must provide answers to these types of questions.
Figure 1 Levels of Security 
With a salted password database, the attacker can't use a prehashed dictionary. But he can still perform a dictionary attack using the salt for each account to rehash his dictionary. He can also try to find short passwords with brute-force by calculating the hash of, say, every possible four-character password. You can slow this attack by requiring a certain level of complexity for passwords, including a minimum length. You can also require that users use a combination of uppercase and lowercase letters, digits, and punctuation. Of course, if passwords are too hard to remember, users may write them down. It's a difficult balancing act.
Salt isn't a silver bullet. You should react immediately if your password database has been compromised, even if it uses salted hashes. But salt buys you a wee bit of extra time. It just might give you enough time to discover the attack and disable the affected accounts until the users can change their passwords.
To make it easy for you to get started with this technique, Figure 2 provides a class in C# that will verify passwords using salted hashes. It will also create the salt and calculate the hash for new passwords as new accounts are added to your database. You just need to provide storage for the salt and the password hash, which are both strings. Here's an example of usage:
string password = Console.ReadLine();
SaltedHash sh = SaltedHash.Create(password);

// imagine storing the salt and hash in a database
string salt = sh.Salt;
string hash = sh.Hash;

Console.WriteLine("Salt: {0}", salt);
Console.WriteLine("Hash: {0}", hash);

// after looking up salt and hash, verify a password
SaltedHash ver = SaltedHash.Create(salt, hash);
bool isValid = ver.Verify(password);
namespace DevelopMentor.SecUtils {

using System;
using System.Security.Cryptography;

public sealed class SaltedHash {
    public string Salt { get { return _salt; } }
    public string Hash { get { return _hash; } }

    public static SaltedHash Create(string password) {
        string salt = _createSalt();
        string hash = _calculateHash(salt, password);
        return new SaltedHash(salt, hash);
    }

    public static SaltedHash Create(string salt, string hash) {
        return new SaltedHash(salt, hash);
    }

    public bool Verify(string password) {
        string h = _calculateHash(_salt, password);
        return _hash.Equals(h);
    }

    private SaltedHash(string s, string h) {
        _salt = s;
        _hash = h;
    }

    private static string _createSalt() {
        byte[] r = _createRandomBytes(saltLength);
        return Convert.ToBase64String(r);
    }

    private static byte[] _createRandomBytes(int len) {
        byte[] r = new byte[len];
        new RNGCryptoServiceProvider().GetBytes(r);
        return r;
    }

    private static string _calculateHash(string salt, string password) {
        byte[] data = _toByteArray(salt + password);
        byte[] hash = _calculateHash(data);
        return Convert.ToBase64String(hash);
    }

    private static byte[] _calculateHash(byte[] data) {
        return new SHA1CryptoServiceProvider().ComputeHash(data);
    }

    private static byte[] _toByteArray(string s) {
        return System.Text.Encoding.UTF8.GetBytes(s);
    }

    private readonly string _salt;
    private readonly string _hash;
    private const int saltLength = 6;
}

}

Q When should I use the AllowPartiallyTrustedCallers attribute in my assembly?
Q When should I use the AllowPartiallyTrustedCallers attribute in my assembly?

A Only after careful review of your code. This attribute was added very late in the development of version 1.0 of the Microsoft® .NET Framework. It wasn't in the beta. In fact, it was so close to the 1.0 release that it didn't make it into the mainstream documentation, but you could read a bit about it in the release notes for the product. Let me first explain the motivation behind its existence.
A Only after careful review of your code. This attribute was added very late in the development of version 1.0 of the Microsoft® .NET Framework. It wasn't in the beta. In fact, it was so close to the 1.0 release that it didn't make it into the mainstream documentation, but you could read a bit about it in the release notes for the product. Let me first explain the motivation behind its existence.
When you build strongly named assemblies, those assemblies may be placed in the Global Assembly Cache (GAC), which means they can be seen not only by your code, but by any other code on the machine, including mobile code that may have originated from an untrusted source. If you assume your code might have bugs in it, and if you also assume that those bugs could lead to security problems if exploited by malicious code, then you'll be happy to know that your assembly can only be called by fully trusted assemblies by default. This means that random code downloaded from the Internet won't be able to call your code by default because the downloaded code is only partially trusted.
Figure 3 shows an example of a very buggy piece of code that can be exploited by an attacker. Every line of this code has a bug. The Assert statement prevents a stack walk that would keep partially trusted code from accessing the database. The database connection string uses the sa account, which if misused could severely damage or destroy the database. The SQL statement is concatenated so that it incorporates unfiltered external input in the form of a name and a password. This constitutes a SQL injection vulnerability, as an attacker could use the name and password to inject malicious SQL statements! There are so many things wrong with this code, and yet sadly it's typical code that you'd see in a database programming example. If an unsuspecting programmer cuts and pastes code like this into his source file, he's opening security holes. A code audit would catch these bugs, but code is frequently shipped without proper security testing.
public class HopeThisIsntUsedByEvilCodeBecauseItsNotRobust {
  public string Name;
  public string Password;

  // this entire function consists of horribly bad code 
  // you should NEVER EVER use
  public bool IsValidUser() {
    new DbDataPermission(PermissionState.Unrestricted).Assert();
    SqlConnection conn = new SqlConnection(
      "initial catalog=accounts;user id=sa;password=;")
    conn.Open();
    cmd.CommandText = string.Format(
      "select count(*) from users where name='{0}'" +
      "and password='{1}'", Name, Password);
    return ((int)cmd.ExecuteScalar()) > 0;
  }
}
This is where AllowPartiallyTrustedCallers comes in. Microsoft decided at the last minute to add a final knob that had to be turned before partially trusted code would be allowed to call your locally installed, fully trusted code. Here's the deal: without this attribute on your strongly named assembly, there is effectively a link-time demand in your assembly that prevents partially trusted code from linking to it.
Now, hopefully the answer is clearer. The only time you should ever add the AllowPartiallyTrustedCallers attribute to your assembly is after a careful security audit. Be doubly wary if your assembly calls unmanaged code. As soon as you apply this attribute to a GAC-deployed assembly, you're opening that assembly up to attack from external untrusted code. Even the core .NET assemblies don't all have this attribute. For example, partially trusted code isn't allowed to use System.Runtime.Remoting.dll or System.Management.dll. The reason is that Microsoft apparently hasn't convinced itself that partially trusted code can't use these libraries to obtain elevated privileges. Only recently did ASP.NET pass examination and receive this attribute: System.Web.dll was awarded the AllowPartiallyTrustedCallers attribute in version 1.1 of the Microsoft .NET Framework.

Send your questions or comments for Keith to  briefs@microsoft.com.


Keith Brown is a member of the technical staff at DevelopMentor, where he spends his time researching, writing, teaching, and generally spreading the word about security to the developer community. He is the author of Programming Windows Security (Addison Wesley, 2000) and is working on a new book on .NET Security. Read chapters of the new book online and reach Keith at http://www.develop.com/kbrown.

Page view tracker