Printer Friendly Version      Send     
Click to Rate and Give Feedback
Related Articles
Here we explain how the new hierarchyID data type in SQL Server 2008 helps solve some of the problems in modeling and querying hierarchical information.

By Kent Tegels (September 2008)
We introduce you to the benefits of building composite applications with the Composite Application Guidance for WPF from Microsoft patterns & practices.

By Glenn Block (September 2008)
ADO.NET Data Services provide Web-accessible endpoints that allow you to filter, sort, shape, and page data without having to build that functionality yourself.

By Shawn Wildermuth (September 2008)
See how routed events and routed commands in Windows Presentation Foundation form the basis for communication between the parts of your UI.

By Brian Noyes (September 2008)
More ...
Articles by this Author
Keith Brown introduces you to the new identity model in the Microsoft .NET Framework 3.0.

By Keith Brown (September 2007)
If you're not taking advantage of Active Directory, you should be. Learn the benefits from Keith Brown.

By Keith Brown (July 2007)


By Keith Brown (May 2007)
When something goes wrong, a manageable application will tell the administrator how to fix the problem. The Windows Event Log can provide the necessary information.

By Keith Brown (April 2007)
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.

By Keith Brown (January 2007)
Use Active Directory Federation Services to allow other organizations to use your Web applications without the need for you to grant access explicitly.

By Keith Brown (November 2006)


By Keith Brown (November 2006)
Windows Communication Foundation provides three major protections— confidentiality, integrity, and authentication. This month Keith Brown explains what they can do for you.

By Keith Brown (August 2006)
More ...
Popular Articles
Here the author introduces SQL Server Data Services, which exposes its functionality over standard Web service interfaces.

By David Robinson (July 2008)
Here the author uses Document Information Panels in the Microsoft 2007 Office system to manipulate metadata from Office docs for better discovery and management.

By Ashish Ghoda (April 2008)
We build a Silverlight 2.0 application using the InkPresenter to let users annotate a pre-defined collection of images, perform handwriting recognition, and save the annotations and recognized text into a server-side database.

By Julia Lerman (August 2008)
See how to build a document-level Visual Studio Tools for Office customization and integrate it with a content type in SharePoint.

By Steve Fox (May 2008)
More ...
Read the Blog
SQL Server 2008 supports a new data type, HierarchyID, that helps solve some of the problems in modeling and querying hier­archical information. In the September 2008 issue of MSDN Magazine, Kent Tegels introduces you to the ...
Read more!
Many people using SharePoint technologies don't realize that there is auditing support built directly into the Windows SharePoint Services (WSS) 3.0 platform. In the September 2008 issue of MSDN Magazine, Ted Pattison walks you through a ...
Read more!
The September 2008 issue of MSDN Magazine is now available online. Here's what's in the issue: Hierarchy ID: Model ...
Read more!
Silverlight 2 features a rich and robust control model that is the basis for the controls included in the platform and for third-party control packages. You can also use this control model to build controls of your own. In the August 2008 issue of MSDN Magazine, Jeff Prosise describes how to ...
Read more!
In the August 2008 issue of MSDN Magazine, Matt Milner covers several topics regarding development with Windows Workflow Foundation, some that are intended to address specific reader questions, such as how to safely share a persistence database ...
Read more!
LINQ is a powerful tool enabling quick filtering data based on a standard query language. It can tear through a structured set of data using a simple and straightforward syntax. In the August 2008 issue of MSDN Magazine, Jared Parsons demonstrates a ...
Read more!
More ...
Security Briefs
CardSpace, SqlMembershipProvider, and More
Keith Brown

Code download available at: SecurityBriefs2006_10.exe (151 KB)
Browse the Code Online

In this month's column, I'd like to take time to answer a few questions that I frequently get from readers. I'll cover information cards, the SqlMembershipProvider in ASP.NET 2.0, and access control GUIs.

Q How can I discover the long-term key for a security token from a self-issued information card?
Q How can I discover the long-term key for a security token from a self-issued information card?

A In a recent column that covered InfoCard (which has since been renamed Windows® CardSpace), I talked about using a self-issued information card in place of a user name and password. At about the same time I wrapped that column, the February community technology preview (CTP) shipped. Unfortunately, that was not a good release for CardSpace and most CardSpace samples stopped working under that release. However, in late May, Microsoft released a new version that brought CardSpace back to life.
A In a recent column that covered InfoCard (which has since been renamed Windows® CardSpace), I talked about using a self-issued information card in place of a user name and password. At about the same time I wrapped that column, the February community technology preview (CTP) shipped. Unfortunately, that was not a good release for CardSpace and most CardSpace samples stopped working under that release. However, in late May, Microsoft released a new version that brought CardSpace back to life.
I've got a new and improved Notepad Web service example that demonstrates how to discover the user's long-term key. Before I show you how to do this, let me explain why this is important. Say you write a service that accepts self-issued security tokens. When Alice contacts your service, the client-side CardSpace plumbing creates a security token with the claims you've requested. These claims can be an e-mail address, a phone number, or any other personal information that can be stored in a self-issued card. Of course, this could also be an identifier that allows the user to remain anonymous. This is the personal private identifier (PPID) I've talked about in earlier columns. E-mail addresses are common, but PPIDs are handy when user anonymity is important.
Imagine that you use an e-mail address to identify the user. When Alice first visits your site and sends you a self-issued security token, you record her e-mail address as a new account. When she visits a second time, you can look up her user account data using the e-mail address you receive in the security token. But how do you know the person on the other end is really Alice and not a different user trying to impersonate her? There's no longer a password, so what secret information is being used to authenticate the user?
Remember, the security token that is being sent by the user will be signed with a private key that only the user's self-issued security token service knows. The corresponding public key will be included in the signature so that Windows Communication Foundation (or whatever type of plumbing your relying party uses) can verify the signature. This is your cryptographic assurance that the client does, in fact, know her private key. However, Windows Communication Foundation doesn't know what the correct public key is for any given user. If an attacker wants to impersonate alice@fabrikam.com, all he needs to do is generate a new public/private key pair, sign his token with the private key, and send the corresponding public key in the signature. It's easy to forget this little detail, but while Windows Communication Foundation is happy to do the heavy lifting by verifying the signature against the submitted public key, it's still your job to make sure that the submitted public key is the same public key the user initially used.
So how do you discover this public key? It's easy using AuthorizationContext in Windows Communication Foundation. Enumerating the claims sent by your user gives you the e-mail address you requested as well as the sender's RSA public key.
Before any privacy advocates get upset with me, let me clarify what this all really means. If there were only one public key used for all interactions, it would be impossible to maintain anonymity across relying parties. If those parties had no scruples, they could use your public key as an identifier and easily correlate all the claims you gave each of them to create a shared dossier of information about you. This is clearly a scenario that should be avoided!
To understand what's really going on, recall how the PPID is constructed. It's essentially a hash of various bits of information that comes from the relationship between a particular information card and a particular relying party. You can use the same information card with 10 different relying parties and each relying party will see a different PPID since the information they provide (such as their public key) will differ. Well, the self-issuing security token service generates RSA key pairs in a similar way. Each of those 10 relying parties will see a different public key, even if you use the same information card. This helps keep the user in control of her identity.
Figure 1 shows the code you can use to retrieve this public key. Note that the URIs for self-issued information card claims have changed slightly since my last column.
An RSA public key isn't just a string of bytes. It actually comes in two parts: a modulus and an exponent. When you read the public key claim from AuthorizationContext, you actually get an object that extends the RSA abstract class, which itself extends AsymmetricAlgorithm in the System.Security.Cryptography namespace. To extract the public key parameters, you need to downcast and call RSA.ExportParameters to get access to the modulus and exponent. You hash them together to produce a unique identifier for the key that you can store in your database. The method shown in Figure 2 does just that. If you don't mind storing binary data, you can skip the Base64 encoding step; this will produce a 32-byte identifier for the key.
The Notepad sample I discussed in my earlier column used a PPID to identify users while allowing them to remain anonymous. And it kept a little piece of state for each user—a note—which he could access by calling GetNote or SetNote and presenting a self-issued security token to identify himself. My updated sample differs in that it doesn't index the notes based only on PPID. Instead, it combines the PPID and the hash of the public key to form a user identifier. This way if an attacker submits Alice's PPID along with his own public key, he won't be able to see Alice's note. Figure 3 shows the new code for GetNote and SetNote, showing how to pair up the PPID with the public key hash to index into the dictionary where I keep state for each user.
In general, you should consider storing the user's public key as part of any user tracking mechanism you rely upon. A column in a Users database table, for instance, would serve this purpose well. When you enumerate the claims in the self-issued token, grab the RSA claim as well and verify that it's the same key the user presented in the past. Be sure to download my latest sample code from the MSDN®Magazine Web site, which works with Beta 2 of Windows CardSpace.

A The SqlMembershipProvider ships with three password formats: Clear, Encrypted, and Hashed. These values are found in the MembershipPasswordFormat enumeration, and you can select which one to use via configuration. If you already require your users to supply a password in order to log in, your system probably has assets that require protection—otherwise you wouldn't inconvenience your users with a logon prompt.
A The SqlMembershipProvider ships with three password formats: Clear, Encrypted, and Hashed. These values are found in the MembershipPasswordFormat enumeration, and you can select which one to use via configuration. If you already require your users to supply a password in order to log in, your system probably has assets that require protection—otherwise you wouldn't inconvenience your users with a logon prompt.
When you require users to submit passwords, you owe them a certain amount of due diligence. Exposing passwords in cleartext so that anyone with SQL SELECT privileges to the membership table can casually browse them is simply negligent. So that rules out Clear in production scenarios.
What about Encrypted? Well, one consideration is that if you encrypt a user's password, you can always decrypt it and communicate it to her if she forgets it. While it might be tempting to simply e-mail the password to the user, e-mail messages are normally sent in the clear and are not at all a secure way to transmit secret information like passwords. Unless the password is basically a nuisance fee for using your Web site, you should probably use an SSL protected Web page. But as you'll see soon enough, the main problem with encrypted passwords is that you need a secret to use them.
The secret key that SqlMembershipProvider uses to encrypt passwords is the one specified in the <machineKey> element in the configuration file. If you don't specify this configuration element, it is set to the equivalent of AutoGenerate, IsolateApps. With the AutoGenerate option, ASP.NET uses a randomly generated master key that is stored on the machine. Meanwhile, the IsolateApps option tells ASP.NET to derive individual keys for each application by modifying the master key based on the hash of the application's virtual directory. This doesn't work very well for encrypting passwords because there's no easy way to back up this data. If you are developing on one machine and testing on another, you need to create new test user accounts for each system. And if you lose the encryption key in a production system, you lose the ability to encrypt or decrypt passwords and thus you can no longer authenticate your existing users. So the first problem you'll likely encounter is the exception that the ASP.NET team put in to warn you not to use auto-generated keys if you're going to encrypt passwords.
To solve this problem, you need to generate a strong, random key and add the <machineKey> element to your configuration file. (Don't let the name of this element fool you—you can put this in your web.config file if you want your application to have its own individual key). If you need a tool to help you generate the key, surf to www.pluralsight.com/tools.aspx and download the ASP.NET Administration Console. This tool will help you generate the strongest possible <machineKey> that ASP.NET 2.0 supports, and since the tool comes with source code, you can verify that it doesn't e-mail a copy of the key to me. All jokes aside, this is a serious consideration when using tools of this nature. In addition, you should avoid the IsolateApps feature so that your key doesn't depend on the name of your virtual directory, since the name could very well change over time.
You don't want that key sitting around visible for any sysadmin to see through casual browsing. You can use aspnet_regiis to encrypt the <machineKey> section once you've made a backup copy of the key. To learn how this is done, see the patterns & practices article "How To: Encrypt Configuration Sections in ASP.NET 2.0 using DPAPI" available at msdn.microsoft.com/library/en-us/dnpag2/html/PAGHT000005.asp. It's really quite easy.
Now here's the really bad news. Because all user accounts are encrypted using <machineKey>, if you change that key, you'll need to rekey your user database, and there's no easy way to do that with the providers as they stand today. So once you do this, your <machineKey> becomes very difficult to change. And a key that is hard to change is a liability. What happens when your system administrator quits and joins the competition? Things could get uncomfortable. And many other security features, such as login cookie protection and view state protection, all depend on that same key that you can no longer easily change. In order to change the <machineKey> you'll need to write code to rekey your membership user database and there's no built-in mechanism to make this an easy thing to do.
So my recommendation is to use the Hashed password format. When you add a new user account with SqlMembershipProvider, it generates a salted hash based on the password and stores the salt and the hash in the user's record as a password verifier. (I described this technique in detail in the August 2003 Security Briefs column at msdn.microsoft.com/msdnmag/issues/03/08/SecurityBriefs.) When a user tries to log in, the provider looks up the user's account based on the name she has provided, reads the salt from the record, and uses that to compute a hash of the password supplied by the user. If the hash matches the stored verifier, the user is authenticated and allowed to move on.
Some functionality of SqlMembershipProvider isn't available if you choose Hashed passwords. For example, if you try to retrieve the user's password, you'll be treated with an exception since there's no direct way to reverse the hash. If a user forgets her password, you can use the ResetPassword method to have the membership system generate a new random password, which you must communicate to the user. She can then change her password using the ChangePassword control. Of course, now you need to worry about having a secondary means of authenticating the user. Otherwise, you'll have bad guys resetting passwords for legitimate users in order to take over their accounts. The question and answer system built into the Membership feature can help with this.
By the way, just because you can't directly reverse the hash doesn't mean the passwords cannot be retrieved. If an attacker gets his hands on your user records in the membership table, he can mount an offline dictionary or brute force attack, guessing passwords and computing their hashes until he finds one that matches. This attack will quickly break weak passwords. A strong password policy is the best way to slow down this sort of attack. If this is a concern, use the attributes on the membership provider in your config file to require strong passwords. By default, the SqlMembershipProvider requires a minimum of 7 characters for a password, and one of those characters must be a non-alphanumeric symbol. You can go further if you like, specifying a regular expression that must be satisfied when a new user registers. You can even write code to validate new passwords by hooking up to the provider's ValidatingPassword event. If you end up writing your own password validation code, you can do things like checking for dictionary words in the password and so on. Figure 4 provides an example configuration that uses the Hashed password format, requiring an 8-character password with at least two non-alphanumeric characters.

Q Should I use the AclUIAdapter to edit the access control list on a file?
Q Should I use the AclUIAdapter to edit the access control list on a file?

A A reader recently asked how he should go about building a dialog box in managed code that is similar to the one in Windows Explorer that allows a user to edit the access control list (ACL) for a file. My first inclination was to suggest using the AclUIAdapter, which I presented in my March 2005 column.
A A reader recently asked how he should go about building a dialog box in managed code that is similar to the one in Windows Explorer that allows a user to edit the access control list (ACL) for a file. My first inclination was to suggest using the AclUIAdapter, which I presented in my March 2005 column.
But there’s a much easier solution. Let Windows Explorer handle the heavy lifting! There’s a function in Win32 called SHObjectProperties, which will display the Windows Explorer property sheet for files and printers. Here’s the Win32® definition:
BOOL SHObjectProperties(
    HWND hwndOwner, DWORD dwType,
    LPCWSTR szObject, LPCWSTR szPage
);

The first argument is the owner window handle for the property sheet, which can be NULL if you don’t have a window handy. The second indicates the type of object for which Windows Explorer should display a property sheet. These types are defined in shlobj.h:
#define SHOP_PRINTERNAME 0x00000001
#define SHOP_FILEPATH    0x00000002
#define SHOP_VOLUMEGUID  0x00000004
Given this, it’s quite easy to whip up some P/Invoke stubs and call this function to display a property sheet. Figure 5 shows the code for FSP.EXE, short for File System Properties. Figure 6 shows the property sheet that pops up when it is run from the command line:
fsp security c:\autoexec.bat
This program could easily be modified to show a printer or volume property page as well.
Figure 6 Properties Displayed 

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


Keith Brown is a cofounder of Pluralsight, a premier Microsoft .NET training provider. Keith is the author of Pluralsight's Applied .NET Security course, as well as several books, including The .NET Developer's Guide to Windows Security, which is available both in print and on the Web. Learn more at www.pluralsight.com/keith.

© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.
Page view tracker