Saturday, July 21, 2007

Excellent ASP.NET Information

Daniel currently publishes an internal Microsoft feed on his blog. Excellent information about ASP.NET internals like process models, dynamic compilation and the pipeline (more to come).

Recommended!

 


For Your Favourites
Saturday, July 21, 2007 4:42:48 AM UTC  #   
 Thursday, July 12, 2007

Windows Integrity Mechanism

Another very interesting security feature (even revolutionary for Windows) in Vista/2008 is mandatory access control (as opposed to discretionary access control).

Michael just posted the link to the new technical reference. Enjoy.


For Your Favourites
Thursday, July 12, 2007 7:49:50 AM UTC  #   

Windows Service Hardening

I am pretty impressed with the changes and new features for good old NT Services in Vista/Server 2008.

My favourite feature is, that every service can now have a distinct SID that can be used to ACL kernel objects. Imagine you have to deploy a bunch of services that have to be isolated from each other. Pre-Vista you would have to create an account for each service. Now you can simply use the new NT Service\ServiceName SID to control authorization. Very neat.

Even better the SIDs for services are deterministic across machines (S-1-5-80-SHA1(Servicename) to be exact), and you can also pre-calculate the SID even when the service doesn't exist yet:

sc showsid FooService

This makes it very easy in server farms to copy data *and* ACLs (e.g. using robocopy) between nodes...

Additionally you can write-restrict the service tokens - that means that the service won't have write access to any kernel object unless the service SID is explicitly part of the ACL.

Other nice features are that services no longer share the same desktop with interactive users and that you can bundle network access rules with services. These rules are independent from the Windows firewall and would even work if the firewall is disabled.

Nice least privilege work, guys!

Voy has written a series of blog posts about the new features (recommended reading):


Work in Progress
Thursday, July 12, 2007 7:00:12 AM UTC  #   
 Wednesday, July 11, 2007

New WCF Security Samples

Justin wrote me an email this morning:

"Dominick,

I hope you are well.

There are several new WCF-security samples posted at http://wcf.netfx3.com/files/53/default.aspx (today)

I thought you might be interested, especially if you are planning on writing that WCF security book…"

That's great news! They all look very interesting!

Thanks for getting me into trouble, Justin ;)

 


For Your Favourites
Wednesday, July 11, 2007 6:38:04 AM UTC  #   
 Friday, July 06, 2007

WCF Security Webcast

Im Rahmen der WCF/WF Webcast Serie auf MSDN Deutschland haben Christian Weyer und ich einen Webcast über WCF Security gemacht.

Der ist jetzt downloadbar. Viel Spass!

 


Microsoft Deutschland Security Portal
Friday, July 06, 2007 7:52:03 AM UTC  #   
 Thursday, July 05, 2007

Hit by Identity 1.0

I am moving soon to another city - that means I will have a new address, new telephone number etc. I realized at how many sites I have to change my details (e.g. for delivery).

Wouldn't life be much better if all these sites would just update their details from my updated Information Card?

Identity 2.0, where art thou?


Misc
Thursday, July 05, 2007 9:28:54 AM UTC  #   
 Monday, July 02, 2007

Re:MVP

Just got mail from Microsoft - my MVP status in the small but fine Developer Security category has been renewed.

Thanks Microsoft!

 


Misc
Monday, July 02, 2007 8:30:53 AM UTC  #   
 Thursday, June 28, 2007

Information Card Kits for ASP.NET and HTML

Microsoft just released two kits to make it easier to integrate information cards into HTML and ASP.NET based applications. woohoo.

A quick look reveals a new class for decrypting tokens and a helper to bridge the gap to membership. Looks like a perfect companion for my ASP.NET control ;) Stay tuned...

 


For Your Favourites
Thursday, June 28, 2007 3:55:55 AM UTC  #   
 Monday, June 25, 2007

Feature Complete Version of the ASP.NET CardSpace Control

UPDATE: new version available here.

After I made some incremental changes and releases of my CardSpace control (found some bugs, got some feedback), I wanted to consolidate all the information along with a new version and some new features here. It now contains all the features I need and will be the last release for some time i guess.

If you have any feedback or suggestions feel free to write me or leave me a comment. If you want to add support for XHTML, contact me too ;)

Download here. Have fun!

PS. This was only possible with a little help of my friends...thanks Brock and JasonD!

Features

Easy to use syntax
One of my main goals was to have an easy to use markup syntax and intellisense support. I don't want to type in all those namespace URIs...

<lp:CardSpaceSelector runat="server" ID="_selector_sic" AutoPostback="true"
    IssuerType="SelfIssued">

    <lp:ClaimType Name="givenname" />
    <lp:ClaimType Name="surname" />
    <lp:ClaimType Name="email" />

</lp:CardSpaceSelector>

Clean markup and independence of the server form
The emitted markup works with Firefox and IE. I also made sure that the <object> tag is placed outside of the postback form. This allows you to have multiple postback controls on the form without triggering the identity selector.

Support for standard InfoCard image
You can choose between all standard sizes of the official InfoCard image. You can also supply your own image and dimensions

Designer integration
I never use the designer - but I acknowledge the fact that some people do ;) The control renders correctly in the designer and has an editor to setup the required/optional claims (including intellisense support).

Event driven
The control fires an event when a token is submitted.

protected void _selector_sic_TokenSubmitted(object sender, TokenSubmittedEventArgs e)
{
    string xmlToken = e.Token;
}

Conditional rendering
You can choose to render the control only if the client browser supports InfoCards. You can specify an alternative <div /> that would render in that case (e.g. to tell the user how to get CardSpace).

Decoupling
I intentionally didn't couple the control with any user management semantics (like membership) or decryption clases (like the TokenProcessor). It is totally up to you how to proceed after you received the encrypted token. This is considered a feature ;)

 

Properties

InfoCard setup

IssuerType
This enum has two values ‘SelfIssued’ and ‘Managed’. If you select ‘SelfIssued’ then the issuer URI for self-issued cards will be emitted. If you select ‘Managed’ you have to set the issuer URI yourself. Defaults to 'SelfIssued'

Issuer and IssuerPolicy
Specifies the URIs for the issuer and the issuer policy.

TokenType
Specifies the token type. Defaults to SAML 1.0.

PrivacyUrl and PrivacyVersion
Specifies to the URL and version of the associated privacy policy (if any).

Image

ImageUrl
Specifies a custom image to display. Defaults to the official InfoCard logo. 

StandardImageSize
Selects one of the standard images sizes for the official InfoCard logo. Defaults to 114x80.

Width & Height
Specifies the size of the image in pixels. Only relevant when a custom image is used.

Rendering

RenderOnlyIfSupported
When set to true, the control will only render if the client browser supports CardSpace. You have to embed the control into a <div /> and specify the name in the DivToRender attribute. Defaults to false.

DivToRender
Specifies which <div /> to render/make invisible based on client support.

UnsupportedDiv
Optionally specifies a <div /> to render when CardSpace is not supported on the client.

RenderMode
Choose between static and dynamic rendering. Static preserves the space for the control on the client. Defaults to Static.

Misc

HiddenFieldName
Name of the hidden field used to transmit the token back to the page. Defaults to __XMLTOKEN.

AutoPostBack
Specifies if the control posts back after a card has been selected. Defaults to false.

TriggerOnLoad
Specifies if the identity selector should be invoked directly after the page has finished loading. Defaults to false.

XmlToken
Holds the encrypted token after the user has selected a card.

 

CardSpaceSelectorV2.5.zip (393.33 KB)
Work in Progress
Monday, June 25, 2007 6:40:10 PM UTC  #   
 Saturday, June 23, 2007

Recorded Sessions from IMTC

The Irish folks are great - not only they organized a fantastic community conference - they also recorded all the sessions...

http://www.askasqlguru.com/category/imtc/

Have fun!

 


Conferences
Saturday, June 23, 2007 3:43:00 PM UTC  #   

MSDN Security Code Clips

In Zusammarbeit mit MSDN Deutschland habe ich einen ganzen Schwung Screencasts rund um sichere Softwareentwicklung erstellt (unterteilt in die Bereiche Allgemein, Client Entwicklung, ASP.NET, WCF und CardSpace).

Die Startseite findet Ihr hier:
http://www.microsoft.com/germany/msdn/solve/knowhow/sicherheit/default.mspx

 


Microsoft Deutschland Security Portal
Saturday, June 23, 2007 2:49:02 AM UTC  #   

MSDN UK CardSpace Nuggets

I recently did four short screencasts for MSDN UK on various aspects of CardSpace. The focus more on self issued cards and are divided into the following topics:

Also find the sample code I used here.

 


CardSpace | Work in Progress
Saturday, June 23, 2007 2:40:34 AM UTC  #   
 Thursday, June 21, 2007

Another update to the CardSpace Control for ASP.NET (2)

Sorry about the confusion - but I felt like adding some more "nice to have" features to the control.

In this new version you can tell the control to render only if CardSpace is supported in the client browser. For this I added three new properties:

  • RenderOnlyIfSupported (self explanatory)
  • DivToRender (specifies the <div /> to render if CardSpace is supported
  • RenderMode (either Static or Dynamic - render either a hidden or a none div. Like the display mode in validation controls)

The tag could look like this:

<div id="selectorDiv">
    <h2>CardSpace Login</h2>
    <lp:CardSpaceSelector runat="server" ID="_selector" 
AutoPostback="true" IssuerType="SelfIssued" OnTokenSubmitted="_selector_TokenSubmitted" RenderOnlyIfSupported="true" DivToRender="selectorDiv" RenderMode="Dynamic"> <lp:ClaimType Name="Email" /> <lp:ClaimType Name="Surname" /> <lp:ClaimType Name="PPID" /> <lp:ClaimType Type="Custom" CustomName="http://foo" IsOptional="true" /> </lp:CardSpaceSelector> </div> 

CardSpaceSelectorV2.2.zip (51.76 KB)

 


Work in Progress
Thursday, June 21, 2007 6:16:00 AM UTC  #   
 Tuesday, June 19, 2007

Another Update to the CardSpace Control for ASP.NET

Update: updated version here.

I did another slight modification to my CardSpace control (see here and here) - it now fires a TokenSubmitted event where it passes the encrypted token back to the page. This makes for a nicer programming model.

The tag could look like this:

<lp:CardSpaceSelector runat="server" ID="_selector" AutoPostback="true" 
IssuerType="SelfIssued" OnTokenSubmitted="_selector_TokenSubmitted"> <lp:ClaimType Name="Email" /> <lp:ClaimType Name="Surname" /> <lp:ClaimType Name="PPID" /> <lp:ClaimType Type="Custom" CustomName="http://foo" IsOptional="true" /> </lp:CardSpaceSelector>

And the corresponding code:

protected void _selector_TokenSubmitted(object sender, TokenSubmittedEventArgs e)
{
    try
    {
        // parse and decrypt the token
        Token token = new Token(e.Token);
        ...
    }
    catch (Exception ex)
    {
        ...
    }
}

Have fun!

CardSpaceSelectorV2.1.zip (48.28 KB)

 


Work in Progress
Tuesday, June 19, 2007 3:47:08 AM UTC  #   
 Monday, June 18, 2007

Getting CardSpace Tokens Programmatically

Last week I did a talk at Software Architect about Federation and CardSpace. I got almost the same question three times: "Can I use CardSpace in my own applications - without having to use WCF or a browser?"

The scenarios where interesting - Andy had a CardSpace enabled VPN/Radius access in mind and Tim was wondering how to CardSpace enable an http/xml based system.

So I decided to have another look at the APIs in the System.IdentityModel.Selectors assembly (specifically the CardSpaceSelector.GetToken() method).

Well - this API is quite unpleasant to use as it requires a lot of handcrafted XML to generate the policy that gets passed to the CardSpace selector service. So I wrote a little wrapper to simplify things. You basically pass in the required details (issuer and target URI, the target identity as well as required/optional claims) and get back the encrypted XML token. From this point on it is up to you to use this token in whatever way you want -  it is as easy a shipping a string to your relying party. handy.

This code snippet shows how to use the wrapper to get a token for a self issued card:

IdentitySelector selector = new IdentitySelector();

selector.IssuerUri = 
new Uri("http://schemas.xmlsoap.org/ws/2005/05/identity/issuer/self"); selector.TargetUri = new Uri("http://relyingParty"); selector.SetTargetCertificate("RelyingParty", X509FindType.FindBySubjectName, StoreLocation.CurrentUser, StoreName.AddressBook); selector.RequiredClaims.Add(ClaimTypes.GivenName); selector.RequiredClaims.Add(ClaimTypes.Surname); selector.RequiredClaims.Add(ClaimTypes.Email); string tokenString = selector.GetTokenString();
 

IdentitySelectorWrapper.zip (13.29 KB)

 

 


Work in Progress
Monday, June 18, 2007 6:34:44 AM UTC  #   
 Saturday, June 09, 2007

Updated CardSpace Control for ASP.NET

Update: updated version here.

I did some updates to the CardSpace control I posted last year. It now produces cleaner HTML which plays nicer with the Firefox plugin and has improved server side markup.

A typical tag could look like this:

<lp:CardSpaceSelector runat="server" ID="_selector" AutoPostback="true"
    IssuerType="SelfIssued">

  <lp:ClaimType name="Email" />
  <lp:ClaimType name="Surname" />
  <lp:ClaimType name="PPID" />
  <lp:ClaimType type="Custom" CustomName="http://foo" isOptional="true" />
    
</lp:CardSpaceSelector>

The name attribute now supports intellisense so you don't have to remember all those claim type namespace URIs.

I intentionally did not couple the control with any token decryption logic or user management. There are simply too many options how to handle claims in your application and I didn't want to dictate any style or pattern.

After the postback you can retrieve the encrypted token from the XmlToken property and use the token decryption logic of your choice to get to the claims (a tweaked version of the TokenProcessor SDK sample is included - but you may wanna consider using the TokenDecryptionService).

protected void Page_Load(object sender, EventArgs e)
{
  if (IsPostBack)
  {
    // retrieve encrypted XML
    string xmlToken = _selector.XmlToken;
    if (!string.IsNullOrEmpty(xmlToken))
    {
      // parse and decrypt the token
      Token token = new Token(xmlToken);
      string email = token.Claims[ClaimTypes.Email];
  }
}

CardSpaceSelectorV2.zip (51.13 KB)

 


Work in Progress
Saturday, June 09, 2007 7:12:11 PM UTC  #   
 Friday, May 25, 2007

Online Vorlesungen zu Betriebssystem Architektur

Wow - 60h online Material zu OS Internals. hier und hier.

Mehr Infos bei Sebastian.

 


Microsoft Deutschland Security Portal
Friday, May 25, 2007 6:59:08 AM UTC  #   
 Wednesday, May 23, 2007

"Hello {0}: {1}", "Dublin", "Irish Microsoft Technology Conference"

Clare, Microsoft and the Irish community gang have set up a fantastic conference in june! Lots of interesting talks! Looking forward to it!

If you are around say Hi!

 


Conferences
Wednesday, May 23, 2007 9:43:50 AM UTC  #   
 Thursday, May 17, 2007

Identity Providers, Authentication, Self Issued Cards and (again) Keys

I just assume (= hope) that it will be a common scenario in the future that identity providers set up a web page where you somehow register and in turn get a managed card to import into CardSpace.

After you imported the card you can use it to login to applications and services that accept cards from that particular identity provider. Under the covers, CardSpace will then contact the STS to obtain a token for the relying party. To get this token you have to somehow authenticate with the STS.

A CardSpace STS currently supports four credential types

  • Username/password
  • Certificates
  • Kerberos
  • Self issued cards

Each authentication type has its use.

  • Username/password supports any key/value pair type of authentication, e.g. also CC# and security code.
  • Kerberos enables single-sign on in Kerberos realms
  • Self issued cards enable single sign on with self asserted information (but probably verified by the identity provider)
  • Certificates (my favourite) enable very strong authentication and especially when combined with smart cards multiple factors

You can also strengthen the protection of the cards with an additional pin that you have to enter, every time you use them.

When you want to build your own STS for CardSpace you have to make a choice which authentication type(s) you want to support. While reading the The Identity Selector Interop Profile about using self issued cards, I came across this:

<quote>

5.4. Self-issued Token Credential

When the identity provider requires a self-issued token as the credential type, the following credential descriptor format MUST be used in the information card to specify the required credential.

Syntax:

<ic:UserCredential>
  <ic:SelfIssuedCredential>
    <ic:PrivatePersonalIdentifier> xs:base64Binary </ic:PrivatePersonalIdentifier>
  </ic:SelfIssuedCredential>
</ic:UserCredential>

The following describes the attributes and elements listed in the schema outlined above:

.../ic:SelfIssuedCredential

This element indicates that a self-issued token credential is needed.

.../ic:SelfIssuedCredential/ic:PrivatePersonalIdentifier

This required element provides the value of the PPID claim asserted in the self-issued token used previously to register with the IP/STS (see Section 8.5.14). Furthermore, the actual security policy of the IP/STS (expressed in its WSDL) MUST include the sp:IssuedToken assertion requiring a self-issued token with exactly one claim, namely, the PPID.

</quote>

This means that you have to embed the PPID of the self issued card inside a managed card to make the connection between these two cards. In a recent post I told you that PPIDs are generated dynamically based on the application identity.

Now this implies that from a CardSpace point of view the web site issuing the managed card and the STS (usually a separate web service) need to have the same identity. Otherwise the PPIDs would get calculated differently and CardSpace could not associate the SIC with the managed card.

This means that essentially the web site and the STS have to use the same server certificate. And both of them need read access to the private key.

Now to me it sounds a little bit dangerous when a flaw in one application can compromise the identity of another. And especially an identity provider should have rock solid security.

Just another reason to factor out at least the token decryption code in the web interface. I wrote about that here and provided a service that allows doing that here.

Another approach could be to use EV certificates. That would allow having separate certs for the web app and the STS and still the PPID would get calculated correctly (given the O, L, S, C fields in the certificate match). I have not tried that but will once I can afford them ;)

Sometimes it is really funny how such a small detail can completely change your overall architecture…and sometime you find out the hard way…


Work in Progress
Thursday, May 17, 2007 10:11:40 PM UTC  #   
 Wednesday, May 16, 2007

Live Alerts

Trying to be as "2.0" as Clemens - I added Live Alerts support to this blog.

Click here to subscribe:

Windows Live Alerts

Spass beiseite: I think the Alerts service is interesting (for more than just pinging you when I wrote a new post) - so I thought I give it a try...more to come...

 


Work in Progress
Wednesday, May 16, 2007 7:00:15 AM UTC  #   
 Saturday, May 12, 2007

Primary Keys in Identity

Keith followed up on my recent post about unique values and IDs in InfoCards. He proposes a model of simply using the hash of the public key as an identifier. This is totally fine and, frankly, I simply forgot to talk about that option in my post.

Basing the ID only on the public key gives you the most flexibility, but you also need a strategy for dealing with the case when certain "key" values in the card change. Combining the public key with certain claims will automatically invalidate the card when these values change. Both behaviors are totally valid, and it depends on your application scenario which way you wanna go. Just be sure to know what you get.

In this post Keith talks about another piece of the puzzle – the ClaimType.Right. Recommended.


Work in Progress
Saturday, May 12, 2007 7:37:43 AM UTC  #   
 Thursday, May 03, 2007

Orcas, WF, WCF and CardSpace

Vittorio posted a nice walkthrough on how to combine the above mentioned technologies. Sweet.


For Your Favourites
Thursday, May 03, 2007 9:47:50 AM UTC  #   
 Saturday, April 21, 2007

UAC Manifest Support in "Orcas"

Adding UAC manifests to apps built with VS2005 is kind of a hassle (and does not really work in all situations).

I was pleased to spot this new properties dialog in VS "Orcas":

 

 


Work in Progress
Saturday, April 21, 2007 11:29:02 AM UTC  #   
 Wednesday, April 18, 2007

Token Decryption Service for CardSpace

Web Applications that want to decrypt CardSpace tokens need read access to the SSL private key. But you would increase your attack surface tremendously if you directly grant this access to the worker process account of your application. I wrote about this in more detail here and Richard Turner followed up here.

Together with my colleagues at Thinktecture (thanks Christian and Buddhike for code reviewing and QA) I wrote an out-of-proc token decryption service that allows decrypting tokens without having to have direct access to the private key in the application, the idea is as follows:

Your web application runs under its normal least privilege account with no read access to the private key. The token decryption service runs as an NT service on the same machine under an account that has read access. Whenever the application has to decrypt a token, it hands the encrypted token to the token decryption service which (in this version) simply uses the TokenProcessor to return a list of claims, a unique ID and the issuer key.

The token decryption service is implemented as a WCF service that uses named pipes to communicate with the applications. To make sure that only authorized applications can call into the service, the application(s) have to be member of a special Windows group called "TokenDecryptionUsers" (can be changed in configuration to support multiple decryption services on the same machine). I also wrote a shim for the WCF client proxy that allows using this service from partially trusted web applications.

The download contains binaries, installation instructions and the full source code. I hope this helps CardSpace adopters to improve the security of their applications and servers. If you have any comments or questions – feel free to contact me.

TDSv1.zip (167.91 KB)

 


Tools | Tools for Thinktecture | Work in Progress
Wednesday, April 18, 2007 5:22:26 AM UTC  #   
 Tuesday, April 17, 2007

UAC Demo and Helpers

As a follow up to the UAC article I wrote some weeks ago, I compiled some demos and a helper library.

The demos show how applications behave given different manifest settings and the helper includes some useful methods like:

  • Find out if the application is currently running elevated
  • Start a process elevated
  • Restart the current process elevated
  • Start a COM DLL elevated
  • Add the shield icon to a button

Btw - excellent information about UAC internals can be found in Mark Russinovich's talk from TechEd '06

UAC_Demo.zip (151.69 KB)

 


Tools | Tools for Thinktecture | Work in Progress
Tuesday, April 17, 2007 8:36:29 AM UTC  #   
 Monday, April 16, 2007

TechDays IIS7 Talk

Danke an alle Teilnehmer der TechDays. Es war ein schöne Konferenz und traumhaftes Wetter.

Ein paar der Demos aus meinem IIS7 Talk findet Ihr hier.

 


Conferences
Monday, April 16, 2007 6:17:56 PM UTC  #   
 Friday, April 13, 2007

CardSpace, PPIDs and UniqueIDs – my Conclusion

In the last post I described the unique values you can find in a card, how they are (roughly) generated and how the certificate of the application (relying party) influences this generation.

Now which value do you use to uniquely identify your users?

In a lot of samples the PPID is used. The PPID is unique for each card/relying party pair - but it is not really a good secret. If you would solely base user identification on the PPID, anybody who knows a valid PPID could craft up a card with that claim and use it to log in to your application.

The CardSpace UI does a good job of not disclosing the complete PPID to the user which helps against phishing. But you still enter the realm of shared secrets – and that's exactly what we try to get away from (think passwords). The secrecy of the PPID would depend on how secure applications store them in their databases. The same techniques as with passwords could be applied here (e.g. iterated salted hashing), but there are much better approaches.

What's really secret in a card is the private key –this key is never transmitted to the relying party. Instead the card is signed with the private key, and the public key is sent alongside to verify this signature. The WCF plumbing and the TokenProcessor sample for ASP.NET do all the heavy lifting to verify the incoming cards using the public key.

That means that you could store the public key at registration time with your user record – and when the user logs in, you would compare the public key with the one you stored before. Keith was the first who wrote about this technique, Garret and Vittorio followed up here and here.

Now the key size can be quite big and could also change with new versions of CardSpace over time. This could become a problem with your database design. For storage it would be better to have a fixed key length – enter hashing.

Hashing produces fixed length outputs of variable length inputs, and in addition, you can combine multiple values of a card in the hash. This is often referred to as the "unique id" of a card. The TokenProcessor uses the PPID as a second value for the hash by default (but this can be changed using the IdentityClaimType appSetting in web.config).

Now which value(s) should you use for the unique id? Well it depends... (I know this is lame ;). But it really depends on your application. In classic applications you stored all the user details in your database (first name, last name, email etc..) and provided a UI for the user to change some of these values. In CardSpace these values come from the claims inside the card and in theory there is no reason to store them again – also the UI to change the values is provided by CardSpace itself. Some applications need the user details for offline processing, some don't. Some applications don't need private user details at all and just need some way to distinguish between users. And some applications don't allow the user to change certain values after registration.

So the rule of thumb is, if changing certain values in a card would invalidate the account, combine these values together with the public key to the unique id. So e.g. if you absolutely wanna make sure that changing the email address in the card would render the card useless – and the user has to re-register, do a hash over the email claim and the public key. The next time the user would try to login with that card – he would not get recognized as a registered user in your system.

If you want to allow users to change all values in the card (or you don't care about other values) do the hash over the PPID and the public key. In this case you either don't store any user data and just re-read it from the card every time. Another approach would be to "cache" the data and update your cache on every login based on the incoming claims.

The attached sample is a bare-bones implementation of a register/login system using unique IDs. With that code you can play around with different ways to generate the unique ID. The code is also compatible with the TokenProcessor for ASP.NET which allows sharing users between ASP.NET and WCF.

CardSpaceUniqueIdDemo.zip (25.08 KB)

 


Samples | Work in Progress
Friday, April 13, 2007 5:57:44 PM UTC  #   

InfoCards and Identity Stability

InfoCards don't have the notion of a username in the classic sense. That means you need to find some other unique value to "recognize" your users.

Two unique values are created whenever you send a card to an application for the first time. These values are a public/private key pair and the PPID. The private key is used to sign the card, and the public key is sent along the card so that the relying party is able to verify the signature (and thus authenticate the card – but not the user). The PPID is a claim which is a long number that should make it easy to distinguish between cards. When you send the same card to five different applications, each application will see a different PPID and key pair. This prevents phishing and that one application can try to use your data to log into a different application.

CardSpace generates these values based on the identity of the relying party and a locally stored salt. The exact algorithm that is used to create these values is not public, but the general approach depends on the type of certificate that the relying party uses (e.g. a SSL certificate for a web application).

Since you have to base your user management on one of these values (or even both in combination), you should be aware of the implications when you select or change the certificate of your application.

For EV (extended validation) certificates the generation is based on the Organisation, State, Country and Location fields in the certificate. This means that you can change you certificate over the times as long as it is still an EV cert and these values don't change. You can even have multiple applications/servers with different certificates and share the users between them as long as the above mentioned fields match.
The term EV is kind of a joke IMO. It is the job of a Certification Authority to validate the identity of the person/company that requests the certificate. Obviously most CAs do a questionable job here. So EV really means that they now try to do it properly – and this of course is also more expensive…

For "normal" certificates the approach is totally different. Here the subject fields from all the certificates in the chain, all the way to the root certificate are used. This means that you have to be very careful when you change a certificate. If one of the subjects change, the unique values will be calculated differently. This in turn means that your stored user records are now out of sync with the incoming cards, and you basically lost your users.

You can read more details about that here.

I came across a lot of companies which see certificates just as a necessary evil to get SSL up and running and they choose whatever CA is the cheapest on a yearly basis (basically after a customer reports that their browser gives them a security warning when trying to access the web application).

Be aware that you have to be more careful with your certificates when you plan to use CardSpace as an authentication system.


Work in Progress
Friday, April 13, 2007 10:05:51 AM UTC  #   
 Wednesday, April 11, 2007

Wrap-up of HTTP.SYS Discussion

After my post about punching holes in HTTP.SYS – there was some discussion going on (on this blog, on Keith's blog and in a number of private email conversations). Let me wrap this up.

Kenny commented on my post:

"I think that the main confusion here is around the purpose of http.sys reservations. Reservations are used to prevent squatting. For example, SQL doesn't want other apps, admin or otherwise, to listen on http://+:80/sql/, so they make a reservation with their creds. Reservations are not for preventing malware from listening on your machine. If you have malware on your machine it can just open a socket if it wants to receive data."

Keith then posted this:

"If Kenny is correct, then it would seem to me that things would work the other way around: that is, by default you'd be allowed to register with HTTP.SYS unless some other application set up a reservation on that port/prefix. But by default, HTTP.SYS is locked down (except for the holes that Dominick is discussing)."

and:

"Squatting on a port is one attack. But it's only one of a myriad of attacks that this reservation system prevents. I cannot imagine that squatting was the only consideration. The port sharing ability of HTTP.SYS makes it even more vulnerable to malware than simply opening a socket. If my exploit can port share with an existing, legitimate service, you might not notice it there if you're using a traditional tool such as netstat. Plus, firewalls are configured to control access to ports - sharing a legitimate port might allow my malware to communicate with the cloud."

I'm sure malware authors worldwide rejoiced when HTTP.SYS port sharing was introduced. I'd say that concerns like Dominick's are well founded."

In the meantime Kenny posted this (shocking IMO) comment:

"To followup, there is a confluence of unfortunate events that actually turn this into a larger concern:
Because of the absence of proper Http.sys – Firewall interaction (you cannot do per-app or per-service firewall exceptions with Http.sys), you have to use reservations to prevent firewall bypass.

It also turns out that WS-Man conveniently installs a firewall exception on port 80 (scoped to system). So with the WCF reservation for world, on every Vista client machine the port 80 is opened for anybody at the WCF temporary addresses prefix."

It turns out that this is not as catastrophic as it first looked because the WS-Man firewall exception is not enabled by default (which is good news). So be aware that when you should ever open port 80 on a machine you might be sharing ports…

Kenny also asked:

"I understand the concerns here. I do have to wonder though, if you have malware running on your machine, can't it just open a client socket to the cloud (which actually is worse since it will traverse your client-side NAT)? Is the difference Reputability since you can check what the client is connecting to?"

and Keith replied:

    "Yep. It could. But it'd be noisy.

Windows Firewall, for example, would prompt the user whether she wanted to "unblock" the application. Any other sort of monitoring tool worth its salt would notice this as well.

Compare this to simply registering as a listener on an existing port via HTTP.SYS. The port is already open as far as the TCP/IP network stack is concerned, so would monitoring software notice this? I don't know.

You have to ask yourself, why go to the bother of locking something down with an ACL if you're then going to configure it loosely so that the ACL doesn't have any effect. I believe that's what Dominick may have been feeling when he wrote his post."

In some private conversation I heard the comparison of the temporary listen URIs to a temp directory on the hard disk: "It is just as opening up a small part of the hard disk as opposed to the whole system." I personally think this analogy is OK for squatting, but does not work very well for the malware opening a listener case.

A listener is a listener, regardless of where he is listening. If some widespread malware establishes a listener on some open URI, this becomes a well known URI.

Remember Back Orifice? This back door was distributed via various means. But BO was not necessarily also exploited by the same people that distributed it. Instead there was also scanning software available that could scan complete address ranges for BO. So a lot of people just used an already installed BO to exploit a machine…

So to sum up:

  • The HTTP ACL system seems to target squatting only – in that case I wonder why it is not implemented as described by Keith above
  • There are several mitigating factors like the Windows firewall and potential NATs
  • You may not be always behind a NAT
  • With the reservation open for world, some malware could potentially open a listener on a system without a single prompt – no UAC, no firewall.
  • Malware establishing outgoing connections (as opposed to listeners) is also a big concern

Make up your mind yourself.


Work in Progress
Wednesday, April 11, 2007 6:56:19 AM UTC  #   
 Wednesday, April 04, 2007

UAC is for Developers

I recently wrote this short article for the latest DevelopMentor newsletter. It is not as detailed as it could be – but I only had 1000 words. Maybe it is still interesting for you.

 

Windows Vista finally starts to address one of the biggest security problems we have in software development today – the administrator problem. Most applications don't need administrative rights, most services don't need them either – but strangely a lot of applications simply don't work when run as a normal user thus forcing your clients (e.g. in corporate environments) to run as administrators. Why is that?

This is kind of a chicken and egg problem. The developers writing these applications also mostly run as administrators and often just don't properly debug and test their code under non-administrative conditions. The changes in Vista security try to break this vicious circle.

The UAC (User Account Control) feature in Vista makes administrators have kind of a split personality. Even if a user is in the administrators group, all administrative privileges are stripped out of their default security token. So whenever an application requests these powerful privileges, Vista puts up a consent dialog to inform the user about this fact. After the user confirms, Vista will put the full token containing all groups and privileges on the newly created process and thus giving it all rights a "normal" administrator would have. This only applies to administrators – not standard users.

This serves two purposes. First of all, people that insist on being administrators on their machines run with reduced privileges by default which makes it much harder for malware to cause harm to your system (but not your user data of course). For developers this makes it much easier to find out if their applications work with a normal privileged user account. If your apps work elevated but not with the default security context – you most probably do something that requires elevated privileges and you should think about if this is really needed.

The most common problems why applications break when run as normal users are very easy to fix. Check e.g. if you are trying to write to a location where you don't have write access to. Popular locations are e.g. "Program Files", the Windows directory or HKLM in the registry – which is just forbidden. You should always put user data into the profile – and it is incredibly easy to do that. The following line of code returns the per-application directory in the profile – similar enum values exist for "My Documents", the desktop and so on:

string path = Environment.GetFolderPath(
  Environment.SpecialFolder.ApplicationData);

Now – another new feature of Vista makes this a little bit harder to test – it is called Virtualization. By default Vista redirects write attempts to some forbidden locations to a per user store. This includes parts of "Program Files" and parts of the registry. This feature is enabled by default to not break legacy applications running in this new and tighter security context on Vista. But what makes an application "legacy"?

Applications express their "Vista readiness" by embedding a so called manifest into the binary. The existence of this manifest makes Vista turn off the compatibility features like Virtualization and an attempt to write to the above mentioned locations will result in an access denied error. Manifests further express the security needs of an application, e.g. if they are designed to work with normal privileges as opposed to administrative applications. Embedding a manifest into applications is by the way a Vista logo requirement.

A manifest is a resource file that looks like this:

#include <winuser.h>
#define IDR_MANIFEST 1 // 2 for a DLL

IDR_MANIFEST RT_MANIFEST MOVEABLE PURE
{
  "<assembly xmlns=""urn:schemas-microsoft-com:asm.v1"" manifestVersion=""1.0"">
    <asmv3:trustInfo xmlns:asmv3=""urn:schemas-microsoft-com:asm.v3"">
      <asmv3:security>
        <asmv3:requestedPrivileges>
          <asmv3:requestedExecutionLevel
            level=""asInvoker""
            uiAccess=""false"" />
        </asmv3:requestedPrivileges>
      </asmv3:security>
    </asmv3:trustInfo>
  </assembly>"
}

The level attribute tells Vista about the security needs of the application. "asInvoker" starts the application with the current security token of the user – which is by default non-administrative. There is another value called "requireAdministrator" which tells Vista that this application is designed to be used by administrators only and the user will see the elevation prompt at application startup.

Before Visual Studio "Orcas" there is no automated way of embedding this resource files into your assemblies – you have to do the following steps:

Compile this file (which should have an extension of ".rc") to a binary resource file using the resource compiler:

rc.exe manifest.rc

This will result in a ".res" file that you can embed using the project properties dialog in Visual Studio. Use the "Resource File" option in the "Application" tab for that. That's it – you are done.

Now the application will behave "Vista compatible" – which is exactly the same behavior as running it on pre-Vista operating systems under a non-administrative account. You are now at a point where you can easily test the application under normal user conditions. And when you start Visual Studio non-elevated (which you should do contrary to what most blog entries tell you), you can also debug it using the standard-user security context.

In the case you plan to write applications that expose both user and administrator functionality you can also programmatically find out in which security context the application was started and modify the application based on that. The following line of code tells you about your state:

bool isElevated = newWindowsPrincipal(
  WindowsIdentity.GetCurrent()).IsInRole(
    WindowsBuiltInRole.Administrator);

By talking to the shell (and thus the consent dialog) you can also programmatically elevate your application programmatically. You can use the standard .NET process API for that:

public static void StartElevated(
  string filename, string workingDirectory, string arguments)
{
  ProcessStartInfo startInfo = newProcessStartInfo();
  startInfo.UseShellExecute = true;
  startInfo.Verb = "runas";
  startInfo.WorkingDirectory = workingDirectory;
  startInfo.FileName = filename;
  startInfo.Arguments = arguments;

  Process.Start(startInfo);
}

You should always make a conscious decision about who the target audience of your application is. If it is meant to be used by administrators then you need administrative privileges. If it is meant for normal users, you should be very careful to not introduce unneeded dependencies on administrative privileges. This is nothing new in Vista – UAC just makes it easier now for developers to switch between contexts and to find out if your apps work in both "worlds". Happy testing!

 


Work in Progress
Wednesday, April 04, 2007 5:41:48 AM UTC  #   
 Tuesday, April 03, 2007

Making my Visual Studio better

James, a student on this week's WCF course has found solutions to two things that bugged me in Visual Studio:

  • Removing the #region tags around interface implementations when using the smart tag "Implement Interface"
  • Setting the default startup mode to "Current Selection"

James has the details for the #region tags here – for the startup mode, change the "DefaultBehaviorForStartupProject" from 0 to 2.

Thanks James! And indeed a good reason to start a blog ;)


For Your Favourites
Tuesday, April 03, 2007 9:40:50 PM UTC  #   
 Sunday, April 01, 2007

WCF Performance Comparison

Microsoft has published a paper that compares WCF to other communication stacks (WSE, ASMX, ES…). Of course WCF is the fastest of them all (in most situations). It would have been nice to give us the test code to verify this against our own networks…

The following section made me wonder (quoting):

"3.3.2 Self-Hosted Secure Request/Reply TCP Application

In this section, the performance of WCF and ES are compared for the same message loads as the previous section (Section 3.3.1) with security enabled. Specifically, transport-level SSL security is employed and ASP.NET Role principle is used for the authorization. Figure 9 shows that the performance of ES on a uni processor is faster than WCF by 24% for the primitive message type while for the order message type, WCF is faster than ES by 69%."

Anyone ever seen Enterprise Services running over SSL (and what does ASP.NET has to do with this)?

Check it out yourself:
http://msdn2.microsoft.com/en-us/library/bb310550.aspx

 


Work in Progress
Sunday, April 01, 2007 1:12:29 PM UTC  #   

WCF Faults and Information Disclosure

I am sure you all have seen these kind of exceptions when working with WCF:

System.ServiceModel.FaultException: The server was unable to process the request
due to an internal error. For more information about the error, either turn on
IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.

Server stack trace:

at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, proxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Why do the default exceptions have to be so verbose, telling everyone the exact toolkit running on the server – and even a stack trace…??

This is (unnecessary) information disclosure.


Work in Progress
Sunday, April 01, 2007 12:49:14 PM UTC  #   
 Tuesday, March 27, 2007

Decrypting CardSpace Tokens in Partial Trust

One way to overcome the problem I described in this post would be to run in partial trust. This way you could factor out the code that does the encryption while the rest of your application doesn't even have file IO access to the private key file.

The problem is that the TokenProcessor code from the SDK has a lot of dependencies on System.ServiceModel/IdentityModel – and they require full trust (no APTCA). After massaging the decryption code a little bit, I was able call it from a partially trusted web app. The necessary steps were:

  • Put the code into a separate assembly
  • Assert full trust
  • Add APTCA
  • Re-implement the ClaimTypes class (so that the web app doesn't need to use the full-trust only WCF class)
  • Put it in the GAC / write a custom policy

Works fine. (download)

 


Work in Progress
Tuesday, March 27, 2007 7:02:56 PM UTC  #   
 Friday, March 23, 2007

Punching Holes into HTTP.SYS

If you want to open a listen URI with HTTP.SYS you either need administrative privileges or an administrator that reserves the URI for normal users. I wrote about this here and here – and even wrote a tool to make that step easier (and given the download numbers, this seems to be helpful for a lot of people).

The whole reason for ACLs on listen URIs is that malware can't easily open a new listening port – or even trickier – hide behind an already opened port (at least that was my understanding).

You can view all existing reservations on your machine using either the httpcfg.exe tool:

httpcfg.exe query urlacl

or netsh on Vista/LHS:

netsh http show urlacl

Now on a typical machine you will find quite a lot of reservations – and even worse some of them are not ACLed for specific accounts (like service or machine accounts), but generally for 'users' or even 'everyone'.

One of those "wildcard" reservations is this one:

URL: http://+:80/Temporary_Listen_Addresses/
ACL: D:(A;;GX;;;WD)

This reservation comes with .NET 3.0/WCF to make duplex communication over HTTP easily possible (and the WD stands for 'everyone').

So if some malware wants to open a highly sophisticated listening port on your machine (e.g. using HttpListener, WCF or the C++ HTTP API) – they can just use one that Microsoft already opened for them….

Doesn't this totally defeat the purpose???


Work in Progress
Friday, March 23, 2007 5:46:01 PM UTC  #   

SQL Server 2005 Security

One of my favorite database guys wrote a whitepaper about my favorite topic: security.

Check out "SQL Server 2005 Security Best Practices" – interesting read!


For Your Favourites
Friday, March 23, 2007 5:42:29 PM UTC  #   
 Saturday, March 17, 2007

CardSpace and decrypting Tokens

While it is (technically) easy to CardSpace enable a web application or service, there are some implications regarding certificates and keys you should be aware of. Let's focus here on the web application scenario as I think this is what most people will try mostly these days. But first some background…

CardSpace only works over SSL – that means the page that triggers the identity selector UI must use HTTPS (which is a good thing). This has two reasons – first the identity selector wants to give the user information about the relying party (information from the SSL certificate as well as the issuer). But in addition to simply sending the token in clear text over SSL transport protection, CardSpace also encrypts the token using the SSL public key found in the certificate.

Now when you want to decrypt the token in the web application, you need access to the SSL private key. This causes some problems and when you search the usual forums you will find a lot of questions around that. Mostly centered around an error message saying "Keyset not found" you will most likely get when using the TokenProcessor that comes with the SDK. This error message means that the application account doesn't have read access to the private key. Now to get this working I wrote a tool some time ago that allows you to easily change ACLs on key containers (Vista has this functionality built in) – but back up for a second – and think about what you are doing here…

Web applications are the primary targets of attacks and since these key requirements for CardSpace are well known there will be a new class of attacks against such applications directly aimed at stealing your SSL private key. So whenever you application (or IIS itself) has a code defect that allows to disclose files on the file system (e.g. directory traversal) your private key lives in a very risky environment. This would allow an attacker to spoof your web site identity using the correct certificate/key combination – and this, of course, is something very dangerous.

So what's the recommended way of dealing with such a situation? I think you should never grant your application account direct access to the SSL private key – a better approach would be to factor out the decryption code into a separate secured process that runs under a different account (and only this account should be able to read the private key). Your web app and this process would talk to each other using a locked down communication channel (e.g. using WCF or Enterprise Services).

This is not hard to do – but is of course more work than simply setting an ACL. Now one of the goals of CardSpace is to get rid of the myriad of passwords we have to deal with, also for non high-security applications like forums. I have my doubts that these types of applications will a) enable SSL and b) take the burden of getting such a server side infrastructure in place. And if you are running on a shared host with no access besides to your web directory this is impossible.

Now while at shared hosting – most standard hosting offers don't give you a separate application pool which means you have to share the process with other customers. In this case there is no way of granting you access to your SSL key in a secure fashion. This of course is also closely related to the fact that the token decryption code has some dependencies on WCF which forces you to run in full trust – and this does not only mean that you are fully trusted – but that you fully trust everyone you are sharing the server with.

I think it would be useful to have an option in CardSpace (for self issued cards) to send the token in clear text over SSL – this would remove the risk of needing access to the private key. This should be of course not the default and opt-in. But I think this would solve some security problems in the end (even if it looks more insecure at first – but making these trade offs is one of the most fascinating aspects of security IMHO).


Work in Progress | CardSpace
Saturday, March 17, 2007 9:43:13 AM UTC  #   
 Tuesday, March 13, 2007

I can read your Googlemail

Enno asked me yesterday why Googlemail is using clear text HTTP by default – WTF?!

I didn't want to believe him and tried it out myself – and yes – if you go to http://www.googlemail.com they use SSL only for the initial login and redirect back to clear text directly after that (and I am pretty sure this has changed since I used the web front end the last time…). That means all the XmlHttpRequest calls and everything goes in clear text over the wire. Why are you doing that Google?? I heard you have so many machines – don't you have some spare CPU cycles to protect your innocent users??

Clear text HTTP connections are easy to eavesdrop (especially over wireless network like in hotels, airports or conferences) and given the way how googlemail works, someone could send "delete" or "send" requests and misuse your mailbox to send away offers for pharmacy, software and the like ;)

Interestingly if you open the login page using SSL – they don't redirect you back – so as an immediate solution, change your bookmarks to https…Besides that you are getting this annoying "do you want to display secure and non secure items" dialog (which also says a lot about the design) – this seems to work…tsts…Hall of shame!


Misc
Tuesday, March 13, 2007 9:13:02 PM UTC  #   

Hotels and Emails

It is not often that I rant on this blog. But this really pisses me off.

At least in Europe, hotels think they have to "proxy" my SMTP connections – well a better word than "proxying" would be "man in the middle attack" I guess. So all outgoing mail goes via their SMTP servers and they forward them to the real server. I am using SMTP over SSL for all my mail accounts – and of course this cannot work with a man in the middle. So this means I have to lower my security just to be able to send emails – and to add insult to injury – some of them force you to do this over unsecured wireless networks. WTF!?

After spending some time talking to support staff I finally got an answer why they are doing that: "It is because of SPAM – we don't want that anybody can send SPAM emails without notice over the hotel network…" Wow – how lame!

So what I normally end up doing is to use my Googlemail account – they also do SSL over SMTP but don't use the normal TCP/25 for that - and this just works (but of course causes other problems like ending up in junk mail folders because people don't have this account in their address book and messing up replies etc).

What an effective countermeasure against SPAM…


Misc
Tuesday, March 13, 2007 10:55:29 AM UTC  #   
 Thursday, March 08, 2007

Windows Process Activation and Faulted Application Pools

This week I ran into a nasty bug in the Windows Process Activation Service (WAS or WPAS?) on Vista. Here is what happened…

I fired up my little WAS application to verify some behavior with non-HTTP WCF endpoints hosted in WAS. But suddenly I got an EndpointNotFoundException in the client. This used to work before and only affected the non-HTTP endpoints. I had no clue what was going on.

After a little more looking around I noticed that the WAS listener adapter NT services are not started (net.tcp, net.msmq and net.namedpipes as well as the tcp port sharing service). And when I tried to start them I got the following scary error in the event log (in SMSvcHost):

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

at System.Runtime.InteropServices.Marshal.ReadByte(IntPtr ptr, Int32 ofs)
at System.Security.Principal.Win32.ConvertIntPtrSidToByteArraySid(IntPtr binaryForm)
at System.Security.Principal.SecurityIdentifier..ctor(IntPtr binaryForm, Boolean noDemand)
at System.Security.Principal.SecurityIdentifier..ctor(IntPtr binaryForm)
at System.ServiceModel.Activation.ListenerAdapterBase.onApplicationPoolCreated(IntPtr context, String appPoolId, IntPtr sid)

With some help from the IIS/WAS team (thanks to Mike for routing me to the right people) we could narrow down the problem – it turned out that this is related to another event log entry I found (from WAS):

Application pool LabPool has been disabled. Windows Process Activation Service (WAS) did not create a worker process to serve the application pool because the application pool identity is invalid.

Now this rang a bell. Some time ago I created an additional application pool that used a custom worker account. After I was finished with my work (and as a good security guy ;) I disabled the worker process account. But I did not delete or disable the application pool.

This was some weeks ago and since I rarely reboot my machine and mostly just put it into sleep mode at night (seems logical ;) everything was fine. Now I did a reboot beginning this week and suddenly all this WAS/SMSvcHost error messages popped up because the application pool could not be started.

Now it turns out that there is a bug in WAS. When a single application pool on the system fails to start, the whole WAS infrastructure dies. Regardless if the application pool is used or not…

Hopefully this post can save you some hours of pulling hair and reading log files…Thanks to all the guys at MS that helped me troubleshoot this!


Work in Progress
Thursday, March 08, 2007 5:59:56 PM UTC  #   
 Wednesday, March 07, 2007

Debugging Services on Vista

With the new session isolation features in Vista you cannot easily debug services like you used to do. Here is a good writeup.

 


For Your Favourites
Wednesday, March 07, 2007 12:49:38 PM UTC  #   

Worker Accounts and Resetting Passwords

This week I spent some hours troubleshooting a problem with IIS7 (more on that in another post) and came across a gotcha you can run into when using user profiles. This is something I knew and I just forgot about it – so I thought I share with you – just in case…

In this post I said that IIS7 now loads user profiles for worker accounts. This is a nice feature since it allows using per account data that can be easily isolated from other accounts on the same machine. One example I gave was using the per-user certificate/key store. So far so good.

But you should be extremely careful whenever you want to change the password of a worker account. There are two ways of "changing" a password. The first is, when logged in as that user, to press Ctrl-Alt-Delete and select "Change password". The other way is to go to "Computer Management" and reset the password of the account. These two methods are fundamentally different and the latter is not recommended at all.

Some background: Windows uses per-used DPAPI to encrypt some data in the profile (e.g. key stores). When you manually use DPAPI with the user scope, the same key is used. This key is partially derived from the user's password. That means whenever the user changes his password, the DPAPI key gets renewed and rotated. When the user changes his own password (method 1) Windows can rotate the DPAPI key (because it knows the old and new password). Everything is fine.

But when you reset the password, Windows cannot rotate the key and all encrypted data that used the "old" key will get lost.

So when setting up worker/service accounts you have two options:

  • Choose a really strong (and random) password upfront, e.g. using Keith's excellent Password Minder tool.
  • Login as the account and use the change password option

Don't reset the password – or at least be aware of the implications.

You can easily test this yourself: Use the protected configuration sample described in my post here and encrypt the connection string. After that reset the worker account password and reconfigure the app pool in IIS7 with the new password. After that do a reboot and call the protected configuration page again. You will see a runtime exception and the connection string cannot be decrypted again.

Just keep that in mind.

 


Work in Progress
Wednesday, March 07, 2007 12:16:44 PM UTC  #   

MSDN US Webcast: ASP.NET Security - Partial Trust

So this was the last of my 5 part mini series on ASP.NET Security. Find the samples for partial trust ASP.NET here.

Thanks to all attendees!

 


Work in Progress
Wednesday, March 07, 2007 11:55:09 AM UTC  #   
 Monday, March 05, 2007

MSDN US Webcast: ASP.NET Security - Logging and Instrumentation

Thanks to all that attended todays webcast. Find the demos here. Enjoy!

 


Work in Progress
Monday, March 05, 2007 9:20:20 PM UTC  #   
 Thursday, March 01, 2007

DevWeek 2007

Thanks to everyone who attended my talks!

Find the samples for my Windows security talk here - and for IIS7 here.

For IIS7 you maybe also wanna have a look at the end to end extensibility walkthrough I posted some weeks ago.



Thursday, March 01, 2007 12:29:24 PM UTC  #   
 Sunday, February 25, 2007

IE7 and local Proxies (e.g. Fiddler)

This is just a repeat of a german blog post by Marc Höppner - but I never read this elsewhere and it is so incredibly useful....

IE7 always bypasses proxies for "localhost" addresses. Regardless of configuration. Now when you want to use e.g. Fiddler with a local web app, this can become an issue.

If you are using IIS it's easy, just use the local machine name instead of "localhost" (something I usually do anyways because of SSL). But Cassini doesn't accept machine names - the (quite funny) workaround for that is to use "localhost." (note the dot) instead. Works fine....

 


Work in Progress
Sunday, February 25, 2007 11:05:27 AM UTC  #   
 Friday, February 23, 2007

MSDN US WebCast: ASP.NET Security - Storing Secrets

As always, the slides and demos I showed can be downloaded here.

See you next time!

 


Work in Progress
Friday, February 23, 2007 7:43:44 PM UTC  #   
 Thursday, February 22, 2007

MSDN US WebCast: ASP.NET Security - Input Validation

Thanks to all attendees - find the slides and source here.

See you next time!

 


Work in Progress
Thursday, February 22, 2007 8:34:00 PM UTC  #   

MSDN WebCast: ASP.NET Security 4 - Logging und Instrumentation

So es ist geschafft - vier WebCasts zu ASP.NET Security. Mir hat es Spass gemacht und ich hoffe für euch war etwas interessantes dabei!

Wie immer Slides und Code hier - und die ganze Serie im Überblick mit WMV download gibt es hier (ich hoffe der bleibt stabil...).

 


Microsoft Deutschland Security Portal
Thursday, February 22, 2007 4:34:19 PM UTC  #   

New (and finalized) CardSpace Resources

Recently Kim released the finalized versions of the CardSpace spec documents – get them here:

  • Information Card Profile V1.0 Technical Reference (here)
  • A Guide to Interoperating with the Infomation Card Profile V1.0 (here)
  • Guide to Supporting Information Cards within Web Applications and Browsers (here)

In addition there are now two sample Security Token Services you can play with:

Have fun…


For Your Favourites
Thursday, February 22, 2007 9:15:50 AM UTC  #   
 Wednesday, February 21, 2007

IIS7: Custom Worker Accounts and User Profiles

One of my favorite feature of IIS7 (well, there a lot) is that user profiles are now loaded for the worker process accounts. Why is this important?

A lot of the Windows functionality (and in my case – security features) depend on loaded profiles, e.g. DPAPI user keys and per user certificate/key stores. Prior to IIS7 you were always forced to use DPAPI machine keys (with application defined entropy) or to store application certificates in the machine store (and manually ACLing the private keys). This also affects the protected configuration feature which relies either on DPAPI keys or the key store. Per application pool profiles (and thus keys) makes isolating applications on a server now much easier.

Another interesting fact is that IIS7 injects the required group (called IIS_IUSRS) into the worker process account – in IIS6 you had to manually add the worker process account into IIS_WPG group.

To demonstrate all this I hacked a little proof of concept web site together that shows the worker process groups and uses the ProtectedData APIs, protected configuration and the X509Store class to query the user certificate store. Nice!

IIS7UserProfilesTest.zip (3.17 KB)

 


Work in Progress
Wednesday, February 21, 2007 12:12:03 PM UTC  #   
 Tuesday, February 20, 2007

MSDN US WebCast: Authentication and Authorization with ASP.NET 2.0

Thanks for attending the first webcast in my mini series!

Find the slides and code here.

 


Work in Progress
Tuesday, February 20, 2007 8:55:19 PM UTC  #   
 Wednesday, February 14, 2007

My 1st MSDN Magazine Article

The march issue of MSDN Magazine has just been released - it includes an article about certificates support in the .NET Framework I wrote a while ago.

I think MSDN Magazine is great and I am really happy this worked out...

http://msdn.microsoft.com/msdnmag/issues/07/03/NETSecurity/default.aspx

 


For Your Favourites | Work in Progress
Wednesday, February 14, 2007 11:07:19 PM UTC  #   
 Monday, February 12, 2007

DevelopMentor and Me

After my last post I received some emails asking me if I have left DevelopMentor …

No – that’s not the case! I am still taking care of their security curriculum and I am still teaching/authoring WCF, .NET Security and ASP.NET. Great people work at DM that I would really miss – besides the fact that I really enjoy teaching and helping people understand technologies that I find interesting.

Since I am doing consulting only for Thinktecture and training only for DevelopMentor there is no overlap at all.

 


Work in Progress
Monday, February 12, 2007 10:58:35 PM UTC  #   

Thinktecture and Me

I know Christian and Ingo for quite some time now. I respect their work and knowledge and (equally important) we always have a good time when we meet (late nights and high hotel/mini bar bills included).
Since security is part of every serious project today, I often helped the guys out when they had questions about Windows, ASP.NET or WCF security. So it seemed like a logical step to “officially” join them as a consultant. Since today the new website is online and you can have a look at which services we offer.

www.thinktecture.com


Work in Progress
Monday, February 12, 2007 1:36:00 PM UTC  #   
 Thursday, February 08, 2007

Admin Title Bar for PowerShell

I like this feature in Vista that elevated command prompts have the word "Administrator" in the title bar. This seems to be some special functionality baked into the command prompt - at least this does not work when starting PowerShell elevated.

This little script can do the trick - just call it from your profile.ps1:

$id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$p = New-Object System.Security.Principal.WindowsPrincipal($id)

if ($p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator))
{
 $Host.UI.RawUI.WindowTitle = "Administrator: " + $Host.UI.RawUI.WindowTitle
}

Thanks to Christian for the title bar code.

 


Work in Progress
Thursday, February 08, 2007 5:15:50 PM UTC  #   
 Tuesday, February 06, 2007

CardSpace and OpenID

A step in the right direction. Handing over to Kim.

 


For Your Favourites
Tuesday, February 06, 2007 7:52:26 PM UTC  #   

SPNs and IIS

Good KB article.

(via Doug Stewart)

 


For Your Favourites
Tuesday, February 06, 2007 11:08:11 AM UTC  #   
 Monday, February 05, 2007

ASP.NET Security Context Troubleshooting Tool

I slightly updated ShowContexts.aspx recently during some IIS7 research work. So I thought I post the new version here.

Features:

  • shows authentication and impersonation settings
  • shows configured role and membership providers
  • shows configured trust level (well - for completeness only - you need full trust for this page to work correctly)
  • shows the IPrincipal/IIdentity types on Context.User and Thread.CurrentPrincipal
  • shows the name and authentication type on Context.User and Thread.CurrentPrincipal
  • shows the thread identity (when impersonation is enabled)
  • shows the IIS LogonUser identity (used by FileAuthorizationModule)
  • shows the client cert (and some embedded information like the UPN if available)
  • shows roles (for Windows-, Roles and GenericPrincipal)
  • allows to save an aggregated config.web (with all settings from machine.config down to the vdir)
  • can set a FormsAuthentication ticket to simulate authentication

HTH

ShowContexts212.zip (2.67 KB)

 


Tools | Tools for Thinktecture
Monday, February 05, 2007 8:53:26 PM UTC  #   

Certificate Revocation and Status Checking

Thanks to Enno Rey for this excellent link. Haven't even fully read it yet, but seems to be THE document on the subject. For future reference.

 


For Your Favourites
Monday, February 05, 2007 8:35:40 PM UTC  #   
 Thursday, February 01, 2007

ASP.NET Security Webcast Teil 3 - Speichern von Daten

Wie immer - danke an alle Teilnehmer! Ich habe auch schon erste Rückmeldungen von Buchgewinnern erhalten...freut mich das das gut funktioniert!

Slides und Code: hier

Bis zum nächsten Mal...

 


Microsoft Deutschland Security Portal
Thursday, February 01, 2007 5:05:39 PM UTC  #   

MSDN US ASP.NET Security Webcasts

In february/march I am doing a 5-part Webcast series about ASP.NET Security for MSDN US. Maybe see you there...

The following topics are planned:

Authentication & Authorization
In this webcast, we explore how Microsoft ASP.NET 2.0 features a flexible authentication and authorization architecture that supports Windows, certificates, and custom credential types. Discover how, with the provided abstraction layers in ASP.NET, your application page code does not have to be aware of any authentication implementation details. Join this session to learn how you can take full advantage of these capabilities. We explain how the HTTP pipeline and its extensibility points work. We look at how the built-in authentication mechanisms function, and we examine how to extend them for enabling single sign-on (SSO) and Web farm scenarios. We also show you how to implement custom and mixed-mode authentication, role handling, and protection of other resources. (register)

Tuesday, February 20, 2007
11:00 AM Pacific Time (US & Canada)

Input Validation
Malicious or unexpected input is the reason for most of the stability and security problems in applications. How often do your applications crash because of logic problems compared to problems caused by malformed input? Many serious attacks rely on flawed or non-existent input validation in applications or how applications handle specially crafted input values. Join this webcast to learn about the most common input-validation attacks, like SQL injection, HTML injection, cross-site scripting, and directory traversal, in addition to the corresponding mitigation techniques. We examine the input validation mechanisms built into Microsoft ASP.NET, including request, ViewState, and event validation, and we look at the validation control infrastructure and its extensibility. (register)

Thursday, February 22, 2007
9:00 AM Pacific Time (US & Canada)

Storing Secrets
As an application developer you are responsible for many secrets, that is, sensitive information such as payroll, intellectual property, passwords, or configuration. Join this webcast to see how Microsoft ASP.NET can help you reduce the exposure of such data with hashing and encryption techniques. We explore the high-level data protection services in ASP.NET, including Data Protection API (DPAPI) and the protected configuration feature. Cryptography alone does not solve problems, but it can be effective in combination with the right architecture and management procedures. In this session, we examine approaches for different scenarios and explain how the APIs work to help you secure sensitive data. (register)

Friday, February 23, 2007
10:00 AM Pacific Time (US & Canada)

Error Handling, Logging & Instrumentation
In this webcast, we discuss best practices that can help you write more secure software. Building detection and reaction mechanisms that signal errors or attack conditions into your applications empowers you to diagnose and fix problems much more easily. We describe how these detection and reaction mechanisms are as important as prevention techniques, like authentication or input validation. Learn how Microsoft ASP.NET and the Windows platform offer many different error-handling and logging capabilities, like the event log, Windows Management Instrumentation (WMI), diagnostics tracing, or the performance monitor. Join this session to see which of these tools is most appropriate for certain situations. We also examine the Health Monitoring Framework, a new feature in ASP.NET that enables abstracting and extending your logging infrastructure through a unified API and a provider-based approach. (register)

 Monday, March 05, 2007
11:00 AM Pacific Time (US & Canada)

Partial Trust
Attend this webcast to discover one of the most overlooked security features of Microsoft ASP.NET, code access security (CAS). By default, your applications have access to powerful functionality, like calling out to arbitrary unmanaged code, accessing code in other application domains, and accessing every feature of the Microsoft .NET Framework. Join us to see how you can use CAS to disable dangerous APIs, or restrict them to only the features you need. We illustrate how this dramatically reduces the attack surface and enables you to use the principle of least privilege and defense-in-depth design. Also, learn about the dangers of running in full trust and get an introduction to partial trust, its configuration, and its extensibility. In this session, we explore common scenarios for using CAS to show you how it is possible to write feature-rich applications while running in a secure sandbox. (register)

 Tuesday, March 06, 2007
10:00 AM Pacific Time (US & Canada)

 


Work in Progress
Thursday, February 01, 2007 9:46:01 AM UTC  #   
 Tuesday, January 30, 2007

The universal Rules of Input Validation

...still apply ;)

(think XSS, SQL injection and friends...)

Everything that is not known at compile time is input...that of course includes InfoCards (and certificates btw too).

 


Misc
Tuesday, January 30, 2007 4:59:06 PM UTC  #   
 Monday, January 29, 2007

ASP.NET Security WebCast Teil 2 - Eingabe Validierung

Danke an alle Teilnehmer!

Slides und Code findet Ihr hier.

Bis zum nächsten mal...

 


Microsoft Deutschland Security Portal
Monday, January 29, 2007 4:41:11 PM UTC  #   
 Sunday, January 28, 2007

Adding Error Messages to a ValidationSummary

Validation summaries are nice when you are using the ASP.NET validation controls. It would be also quite handy to add your own validation/error messages (from internal validation or exception handling) to a summary. With a little background knowledge about the ASP.NET validation infrastructure, this is easily possible.

All validation controls implement the IValidator interface and add themselves to the Page.Validators collection at page creation time. IValidator has three members: IsValid, ErrorMessage and Validate(). When validation occurs, the Validate() method of each control is called which in turn sets the IsValid and ErrorMessage property. At render time the ValidationSummary cycles through the Validators collection and looks for controls where IsValid is set to false. If that's the case, the value of the ErrorMessage property is rendered to the summary.

To add a new error message, you simply have to add an IValidator derived class to the Validators collection (with IsValid = false) and let the summary pick it up. The following small helper class accomplishes that:

// adds an error message to a ValidationSummary control

public class ErrorSummary : IValidator

{

    string _message;

 

    public static void AddError(string message, Page page)

    {

        ErrorSummary error = new ErrorSummary(message);

        page.Validators.Add(error);

    }

 

    private ErrorSummary(string message)

    {

        _message = message;

    }

 

    public string ErrorMessage

    {

        get { return _message; }

        set { }

    }

 

    public bool IsValid

    {

        get { return false; }

        set { }

    }

 

    public void Validate()

    { }

}

You can use the class in your code like that:

catch (Exception ex)

{

    // logging

 

    ErrorSummary.AddError("error message", this);

    return;

}

 


Work in Progress
Sunday, January 28, 2007 8:37:26 AM UTC  #   
 Saturday, January 27, 2007

Source Code Navigation

OK – this is nothing new at all – more a note to self…

Source code navigation in VS is cumbersome…I want hyperlinks for methods, classes, properties etc. – and I want a browser like back/forward navigation. Is this available in VS and I am missing something?

I really like the way you can navigate code in Reflector and I use it often to look at my own source code. Reflector also supports .PDB files which means your variable names etc. are shown correctly in Reflector (unlike string1 to n).

You can easily invoke Reflector from VS for browsing – just add a custom tool entry for Reflector to the Tools menu – set the argument to TargetPath and the working directory to TargetDir – and enable .PDB support in Reflector…nice.

I really wish Lutz would work on Visual Studio to improve such basic things…


Misc
Saturday, January 27, 2007 7:47:35 AM UTC  #   
 Wednesday, January 24, 2007

WebCasts im Februar

Die ASP.NET Security Serie geht im Februar weiter. Auf dem Programm steht:

Security mit ASP.NET 2.0 (Teil 3-4) - Sicheres Speichern von Daten mit ASP.NET 2.0
(1.2.2007 / 16.00)
Als Entwickler ist man ein regelrechter Geheimniskrämer – man muss tagtäglich mit Daten wie Adressen, Kreditkarten und Passwörtern umgehen oder gar medizinische oder finanzielle Information verwalten und speichern. Das .NET Framework bietet einige Einrichtungen, um vertrauliche Daten besser zu schützen. Dies umfasst Hashing- und Verschlüsselungs-Algorithmen sowie einige Hilfs-APIs. Nun kann Kryptografie allein keine Probleme lösen, aber - kombiniert mit der richtigen Architektur - Ihren Daten Sicherheits-Mehrwert hinzufügen. Dieser Webcast gibt einen Überblick über die relevanten Techniken und sagt, wo, wann und wie diese am besten eingesetzt werden. (Anmelden)

Security mit ASP.NET 2.0 (Teil 4-4) - Fehlerbehandlung, Logging und Instrumentierung für ASP.NET 2.0 Anwendungen
(22.2.07 / 16.00)
Es ist unmöglich, hundertprozentig sichere Software zu schreiben. Wenn man allerdings Erkennungs- und Benachrichtigungs-Mechanismen in die Anwendung designed, wird es zumindest bedeutend einfacher, Probleme zu erkennen und zu beheben. ASP.NET und die Windows-Plattform bieten eine Vielzahl von Fehlerbehandlungs- und Logging-Mechanismen, z.B. das Event Log, WMI oder den Performance Monitor. Allerdings sind diese APIs fragmentiert und es ist nicht einfach, den ausgewählten Mechanismus zu ändern, um sich Kunden- oder Netzwerk-Anforderungen anzupassen. Dieser Webcast gibt einen Überblick über Fehlerbehandlung in ASP.NET sowie die verschiedenen Logging-Mechanismen. Weiterhin wird das ASP.NET Health Monitoring Framework vorgestellt, das einen einzigen API für viele Logging-Technologien ermöglicht und durch einen Provider-basierten Ansatz leicht erweiterbar ist. (Anmelden)

 


Microsoft Deutschland Security Portal
Wednesday, January 24, 2007 5:18:07 AM UTC  #   
 Tuesday, January 23, 2007

IIS7 Managed Extensibility: ServerHeader Feature

Below you can find the complete source code and an experimental installation project for the ServerHeader feature i described in the last posts.

Have fun.

ServerHeader.zip (73.26 KB)

 


Work in Progress
Tuesday, January 23, 2007 7:57:40 PM UTC  #   
 Monday, January 22, 2007

IIS7 Managed Extensibility: Deployment

OK – let’s face it – deployment is no fun. The fact that in addition APIs are fragmented, inconsistent or simply missing doesn’t make it more entertaining. But here are the general steps that are necessary to deploy an IIS7 feature.


Register all assemblies in the GAC
See my previous post for more details.

Register the configuration extension
This is a two step process – first you have to copy the schema file to the schema directory

%SystemDrive%\%windir%\system32\inetsrv\config\schema

The next step is to register the section in the <configSections> element in applicationHost.config. Unfortunately there is no API to do that currently (but will be available in “Longhorn Server” starting with Beta 3). So XmlDocument is your friend….

private void RegisterApplicationHost()

{

    XmlDocument doc = new XmlDocument();

    doc.Load(_applicationHost);

 

    XmlNode node = doc.SelectSingleNode(

      "configuration/configSections/sectionGroup[@name='system.webServer']");

 

    XmlElement configNode = doc.CreateElement("section");

    configNode.SetAttribute("name", _configSectionName);

    configNode.SetAttribute("overrideModeDefault", "Allow");

 

    node.AppendChild(configNode);

 

    doc.Save(_applicationHost);

}

The resulting section looks like this.

<sectionGroup name="system.webServer">

  <section name="serverHeader" overrideModeDefault="Allow" />

 

Register the HttpModule
The HttpModule can be registered in applicationHost.config if you want it to be available machine wide. Otherwise you would register it in a down-level web.config. The following code uses the ServerManager class in Microsoft.Web.Administration to access applicationHost.config and to add the module:

private void RegisterHttpModule()

{

    ServerManager manager = new ServerManager();

 

    // get access to applicationHost.config

    Configuration config = manager.GetApplicationHostConfiguration();

 

    // install the module

    ModulesSection sectionModules = (ModulesSection)

        config.GetSection(ModulesSection.SectionName, typeof(ModulesSection));

 

    sectionModules.Modules.Add(_httpModuleName,

        _httpModuleType,

        "");

 

    manager.CommitChanges();

}

The result should look like this:

<system.webServer>

  <modules>

    <add name="ServerHeaderModule"

         type="LeastPrivilege.ServerHeader.ServerHeaderModule, … " />

  </modules>

</system.webServer>

Register the Management Extension
The last step is to add a reference to the ServerHeader module provider to administration.config. Again ServerManager can be used to access this configuration file (this time using the GetManagementConfiguration() method). The code is very similar to the previous one so I will omit this here.

The result should look like this:

<moduleProviders>

  <add name="ServerHeader" type="… " />

 

 

<location path=".">

  <modules>

    <add name="ServerHeader" />

The above procedures can be e.g. used in a VS installer project (using custom actions).

Next Post: the complete solution (finally)...

 


Work in Progress
Monday, January 22, 2007 7:08:28 AM UTC  #   
 Friday, January 19, 2007

IIS7 Managed Extensibility: Solution Structure

OK – let's wrap up the last posts.

An IIS7 feature consists of three assemblies:

  • The HttpModule/Handler
  • Server Management
  • Client UI

All three assemblies should be in the GAC (you can avoid the GAC for the HttpModule/Handler) if you only want to use it locally in an application, but the other two must be in the GAC. So you need a strong name (all the usual security implications apply…).

I think the following assembly/namespace naming and separation of functionality makes sense (and also mostly resembles the layout of the built-in features):

  • HttpModule Assembly
    Name: LeastPrivilege.ServerHeader.dll
    Namespace: LeastPrivilege.ServerHeader
    Contents: HttpModule
  • Server Management Assembly
    Name: LeastPrivilege.ServerHeader.Management.dll
    Namespace: LeastPrivilege.ServerHeader.Management
    Content: ModuleService, ModuleProvider, ConfigurationSection*
  • Client UI
    Name: LeastPrivilege.ServerHeader.ManagementClient.dll
    Namespace: LeastPrivilege.ServerHeader.Management
    Content: Module, ModuleProxy, UI

* I chose to put the ConfigurationSection into the server management assembly. The HttpModule has a dependency on that class but this is OK since the HttpModule and the server management assembly will always be on the same machine.

Next post: Deployment (sigh).


Work in Progress
Friday, January 19, 2007 10:25:38 AM UTC  #   
 Thursday, January 18, 2007

IIS7 Managed Extensibility: Client UI Integration


In the preceding posts we implemented the HttpModule, the configuration section and the server module including the server service – the last part of the integration story is the UI.

UI integration consists of three parts:

  • UI elements
  • The service proxy that is used by the UI to talk to the server service
  • A module that registers the UI with the IIS GUI

Let’s start with the proxy. The proxy provides an interface for the UI to read and write configuration. The proxy then marshals the requests to the IIS management server who in turn does the real work. You call the server methods you implemented in the service via the ModuleServiceProxy base class. The proxy for our ServerHeader feature looks like this:

class ServerHeaderModuleProxy : ModuleServiceProxy

{

    public PropertyBag GetConfiguration()

    {

        return (PropertyBag)base.Invoke("GetConfiguration", new object[0]);

    }

 

    public void SetConfiguration(bool enabled, string headerValue)

    {

        base.Invoke("SetConfiguration", new object[] { enabled, headerValue });

    }

}

For the UI elements you have several choices of how to integrate with the GUI. If you inspect the several feature settings pages you can spot several general types of UIs – dialogs, lists, property grids and features with sub-features (e.g. authentication). Depending on which type of UI you want, you derive from one of these base classes:

-          ModulePage
offers only the most basic services, no standard UI support

-          ModuleDialogPage
similar to a dialog, provides apply, cancel and refresh functionality, e.g. Session State, Directory Browsing

-          ModulePropertiesPage
uses a property grid, e.g. Compilation, Pages & Controls

-          ModuleListPage
uses a list view, useful for collections, e.g. Connection Strings, Handlers

I chose to use a ModuleDialogPage. This gives you a dialog that you can populate with standard WinForms controls. By implementing some of the base class methods you get nice support for the standard Apply/Cancel/Refresh UI elements in the IIS GUI. The complete class is a lot of code (mostly related to standard UI stuff), so I will only show you the important parts of it (the complete solution can be downloaded when the series is complete).

The easiest way is to start with a WinForms Form so that you can use the designer to layout your dialog. Afterwards copy the control declarations and InitializeComponent() to your ModuleDialogPage derived class. Furthermore you need access to the service proxy to issue calls to the configuration service. So your class would look similar to this:

class ServerHeaderPage : ModuleDialogPage

{

    private ServerHeaderModuleProxy _serviceProxy;

 

    // UI

    private System.Windows.Forms.CheckBox _chkEnabled;

    private System.Windows.Forms.Label _lblHeaderValue;

    private System.Windows.Forms.ComboBox _cmbHeaderValue;

 

    // state

    bool _enabled;

    string _headerValue;

 

    public ServerHeaderPage()

    {

        InitializeComponent();

    }

 

    private ServerHeaderModuleProxy ServiceProxy

    {

        get

        {

            if (this._serviceProxy == null)

            {

                this._serviceProxy = (ServerHeaderModuleProxy)

                    base.CreateProxy(typeof(ServerHeaderModuleProxy));

            }

            return this._serviceProxy;

        }

    }
}

Next you need two methods to read and write configuration – this is as simple as calling the corresponding methods on your proxy class, e.g.

private void ReadConfig()

{

    PropertyBag bag = ServiceProxy.GetConfiguration();

 

    _enabled = _chkEnabled.Checked = (bool)bag[0];

    _headerValue = _cmbHeaderValue.Text = (string)bag[1];

}

 

private void WriteConfig()

{

    ServiceProxy.SetConfiguration(_chkEnabled.Checked, _cmbHeaderValue.Text);

}

The base class also offers support for asynchronous operations. This helps keeping the UI responsive when you exchange more complex data or have a slow connection. Remodeling the WriteConfig() method to async looks like this:

private void WriteConfig()

{

    base.StartAsyncTask("writing configuration...",

        OnWriteConfigDoWork,

        OnWriteConfigCompleted);

}

 

void OnWriteConfigDoWork(object sender, DoWorkEventArgs e)

{

    ServiceProxy.SetConfiguration(_chkEnabled.Checked, _cmbHeaderValue.Text);

}

 

void OnWriteConfigCompleted(object sender, RunWorkerCompletedEventArgs e)

{

    if (e.Error != null)

    {

        this.DisplayErrorMessage(e.Error, Resource.ResourceManager);

    }

}

To help the GUI to enable/disable the Apply/Reset/Cancel labels you also have to implement methods that signal the host that settings have changed. The methods are called OnActivated/HasChanges/CanApplyChanges and ApplyChanges/CancelChanges. This mainly boils down to keeping two versions of the configuration data – the original and the read one – and to signal the GUI if changes have been done. You should also hook up control change event handlers to the UI controls to update the status in realtime.

The last step is to register the UI with the IIS manager. This is done in a Module derived class, and this is btw the type you specified in ModuleProvider.GetModuleDefinition(). The main job of this class is to get a reference to the IIS manager control panel and to register the UI in one (or more) of the available categories.

class ServerHeaderModule : Module

{

    protected override void Initialize(

      IServiceProvider serviceProvider, ModuleInfo moduleInfo)

    {

        base.Initialize(serviceProvider, moduleInfo);

       

        // get access to the control panel

        IControlPanel panel = (IControlPanel)

            serviceProvider.GetService(typeof(IControlPanel));

 

        // create a module description (name, icon, description etc)

        ModulePageInfo info = new ModulePageInfo(

            this,

            typeof(ServerHeaderPage),

            "ServerHeader",

            "Allows to change the Server Response Header",

            Resource.ServerHeaderIcon,

            Resource.ServerHeaderIcon);

       

        // register in the security category

        panel.RegisterPage(ControlPanelCategoryInfo.Security, info);

       

        // register in the IIS category

        panel.RegisterPage(ControlPanelCategoryInfo.Iis, info);

    }

 

    public override Version MinimumFrameworkVersion

    {

        get

        {

            return Module.FxVersion20;

        }

    }

}

The assembly implementing these classes needs to be registered in the GAC.

So that’s it – we now have a full blown IIS7 feature. The code that is needed is mostly boilerplate and I hope this walkthrough is helpful when building your own IIS features. In the next post I will talk about the general solution infrastructure, how many assemblies you should use and which class goes where.

 


Work in Progress
Thursday, January 18, 2007 8:43:21 AM UTC  #   
 Wednesday, January 17, 2007

ASP.NET Webcasts Teil 1 - Authentifizierung und Autorisierung

Vielen Dank an alle Teilnehmer - vielleicht bis zur nächsten Episode!

Slides und Code finden Sie hier.

 


Microsoft Deutschland Security Portal
Wednesday, January 17, 2007 4:39:37 PM UTC  #   

IIS7 Managed Extensibility: Server Management Integration


The IIS management framework allows configuring the web server using the IIS7 GUI. To understand the code that needs to be written, you have to know more about the management architecture.

The IIS GUI allows configuring local and remote servers (the remote functionality is not included in Vista). The local case is easy and boils down to accessing the local configuration and state data. In the remote case, the IIS GUI opens a SSL connection to the remote server and uses a web service style protocol to talk to a service on the remote machine that does the configuration. The current plans are that the client can automatically download all the client parts from the server on the first connection. On subsequent connections the IIS GUI checks for updated and new features.

This is the reason why management modules will always have two logical parts. The server part implements some registration code and the configuration service. The client part consists of the UI that will be integrated into the IIS GUI and a service proxy to talk to the server configuration service. In the local case the proxy->service communication will be short-circuited to local calls.

BTW – in the remote scenario, the client will not directly talk to the “real” IIS but to a small, customized management server running on the same machine. This guarantees remote access even if the “real” IIS should be unresponsive.

OK – so first you should implement your module service. This is a simple class which reminds a little of .asmx web services. Every method that should be callable from the service proxy has to be decorated with a [ModuleServiceMethod] attribute. Inside the service methods you read or write the configuration. I have not extensively tested this, but it seems you can use any serializable type to transmit data between the service and the proxy. To minimize dependencies between the client and the server I would recommend using a data structure that comes with the BCL like a Dictionary<>. In this simple example I chose a PropertyBag. I omitted the configuration code since this works exactly as in the HttpModule, but this time you get the current configuration (in the context of the application you manage) from base.ManagementUnit.Configuration.

class ServerHeaderModuleService : ModuleService

{

    [ModuleServiceMethod(PassThrough = true)]

    public PropertyBag GetConfiguration()

    {

        PropertyBag bag = new PropertyBag();

 

        bag[0] = Configuration.Enabled;

        bag[1] = Configuration.Value;

 

        return bag;

    }

 

    [ModuleServiceMethod(PassThrough = true)]

    public void SetConfiguration(bool enabled, string headerValue)

    {

        Configuration.Enabled = enabled;

        Configuration.Value = headerValue;

 

        base.ManagementUnit.Update();

    }

}

Another class you have to implement is a module provider. This class does the registration of the service and the client UI module. Furthermore you can also specify at which configuration level (machine, site, application) the module should be available. There are several base classes to derive from – most commonly you will use ConfigurationModuleProvider – this is the base class of all built-in modules and gives you feature delegation support.

class ServerHeaderModuleProvider : ConfigurationModuleProvider

{

    // returns the name of the configuration section

    protected override string ConfigurationSectionName

    {

        get { return ServerHeaderConfigurationSection.SectionName; }

    }

 

    // returns the fqn of the corresponding client (UI) module type

    public override ModuleDefinition GetModuleDefinition(IManagementContext context)

    {

        string clientname = "…";

       

        return new ModuleDefinition(base.Name, clientname);

    }

 

    // hooks up the module service

    public override Type ServiceType

    {

        get { return typeof(ServerHeaderModuleService); }

    }

 

    // specifies at which level the module should be available

    public override bool SupportsScope(ManagementScope scope)

    {

        return true;

    }

 

    public override string FriendlyName

    {

        get { return "ServerHeader"; }

    }

}

Configuration modules need to be registered in the GAC.

The last step is to register the module in administration.config (\windows\system32\inetsrv\config). You have to modify two configuration sections named <moduleProviders> and <modules> like this:

<moduleProviders>

  <!-- Custom Modules -->

  <add name="ServerHeader" type="… " />

 

<location path=".">

  <modules>

  <!-- Custom Modules -->

  <add name="ServerHeader" />

 

 

OK – now we have finished the server side of the management integration. But on its own – the server module is not very useful. In the next post I will show you how to write the corresponding UI integration and proxy to talk to the configuration service.

 


Work in Progress
Wednesday, January 17, 2007 9:05:01 AM UTC  #   
 Tuesday, January 16, 2007

IIS7 Managed Extensibility: Extending Configuration


I showed you the HttpModule on which this walkthrough is based on in the last post. This module is always active once it is registered and changes the Server header to a hardcoded value. It would be nice if the value and the ‘enabled’ status could be read from a configuration file. In this post I will show you the bits and pieces you have to do to add a new configuration section and make this section available to the IIS7 command line configuration tool and the configuration API.

OK – so first of all you should have an idea how your configuration section looks like, I chose the following design (inside of system.webServer):

<serverHeader enabled="true" value="www.leastprivilege.com" />

To make the IIS configuration system “understand” this config section, you have to provide a schema file. This file describes the layout of the section and things like required values, default values, value boundaries and more. Unfortunately there is no documentation of the XML vocabulary used – but if you look at \windows\system32\inetsrv\config\schema – you can inspect the schema used for the built-in section and get an idea of the options you have. The XML schema file for our section looks like this:

<configSchema>

  <sectionSchema name="system.webServer/serverHeader">

    <attribute name="enabled" type="bool" defaultValue="false" />

    <attribute name="value" type="string" defaultValue="www.leastprivilege.com" />

  </sectionSchema>

</configSchema>

Copy this file to the above location. The next step is to register the configuration section in applicationHost.config (\windows\system32\inetsrv\config). Search for the system.webServer section group and add a new section underneath, like this:

<sectionGroup name="system.webServer">

  <section name="serverHeader" overrideModeDefault="Allow" />

 

 

From that point the native configuration system can handle your config section and tools like appcmd.exe know about it, e.g. you can show the standard settings of your section (according to the schema definition) with:

appcmd list config /section:serverHeader /config:*

To set configuration for an application use:

appcmd set config "Default Web Site/App" -section:serverHeader /enabled:true /value:SomeServer

You can now also use the APIs in Microsoft.Web.Administration to read/write the configuration section programmatically (I wrote more about the options here). To get a strongly typed wrapper for the configuration section you have to add a mapper class that derives from ConfigurationSection. The class is very simple and looks like this:

public class ServerHeaderConfigurationSection : ConfigurationSection

{

    public static readonly string SectionName = "system.webServer/serverHeader";

 

    public bool Enabled

    {

        get { return (bool)base["enabled"]; }

        set { base["enabled"] = value; }

    }

 

    public string Value

    {

        get { return (string)base["value"]; }

        set { base["value"] = value; }

    }

}

Now we can add configuration functionality to the HttpModule. First of all I added a property that retrieves the current configuration. I used the WebConfigurationManager class found in Microsoft.Web.Administration. This is the light-weight read-only API that always gives you an aggregated view of all configuration settings in effect (regardless of at which level they were configured). This API also works in partial trust scenarios.

private ServerHeaderConfigurationSection _configuration = null;

 

protected ServerHeaderConfigurationSection Configuration

{

    get

    {

        if (_configuration == null)

        {

            _configuration =

                (ServerHeaderConfigurationSection)WebConfigurationManager.GetSection(

                    HttpContext.Current,

                    ServerHeaderConfigurationSection.SectionName,

                    typeof(ServerHeaderConfigurationSection));

        }

 

        return _configuration;

    }

}

The OnLeave event handler can now read from config and act accordingly:

void OnLeave(object sender, EventArgs e)

{

    if (!Configuration.Enabled)

        return;

 

    // set header

    HttpContext.Current.Response.Headers.Set("Server", Configuration.Value);

}

OK – that’s it for now. We have completed two important steps – added a general request processing module to IIS and made this module available to the configuration system. In the next post I will show you how to integrate the module configuration into the IIS server side management system.

 


Work in Progress
Tuesday, January 16, 2007 9:01:21 AM UTC  #   
 Monday, January 15, 2007

IIS7 Managed Extensibility: The HttpModule

Writing a module that can intercept requests in IIS7 is very easy. In fact, for people that have written HttpModules in ASP.NET before – this is nothing new at all.

The general idea is that you write a class that implements the IHttpModule interface and register it in the <modules> section in configuration. This interface defines two methods, Init and Dispose. Init is called during application startup and is used to hook up an event handler to one of the various request processing events, e.g. BeginRequest, AuthenticateRequest etc. In Dispose you get the chance to do resource cleanup if needed.

namespace System.Web

{

    public interface IHttpModule

    {

        void Dispose();

        void Init(HttpApplication context);

    }
}

Since the ServerHeader module wants to change the HTTP response headers, it seems appropriate to inject our code into the PreSendRequestHeaders event which occurs directly before the headers are sent out to the client. The following code does the event handler registration:

public void Init(HttpApplication context)

{

    context.PreSendRequestHeaders += OnLeave;
}

To change a response header you use the HttpResponse.Headers collection. Changing response headers that don't originate from managed code (in this case from the web core) is a new feature in IIS7 and is enabled by the integrated pipeline. The following code would throw an exception on IIS6:

void OnLeave(object sender, EventArgs e)

{

    // set header

    HttpContext.Current.Response.Headers.Set("Server", "MyFavouriteServer");
}

The last step is to compile this class into a .dll and copy it either into the /bin folder of an application or into the GAC. After that you can register the module at the configuration level you want to use it (machine, site or application). Add the following section to the corresponding web.config:

<system.webServer>
 
<modules>
   
<add name="ServerHeaderModule"
        
type="LeastPrivilege.ServerHeader.ServerHeaderModule, … " />
 
</modules>
</system.webServer>

When you now make requests to IIS7 and inspect the response (e.g. with a tool like Fiddler), you can see that the value of the server header is to whatever you have set it in code. And btw – this is also the case if you request a static file like html or jpg. Managed modules get called for every single request now (at least by default).

OK – so that's the core of the new IIS7 feature I want to add. It may look simple but this is a huge improvement. For the first time we can plug directly into IIS request processing using managed code and you can imagine all kinds of interesting scenarios you can realize with this possibility.

Next time I will talk about how to add a custom configuration section to web.config and how the module can read its configuration settings.

 


Work in Progress
Monday, January 15, 2007 7:35:43 AM UTC  #   
 Saturday, January 13, 2007

IIS7 Managed Extensibility: An end-to-end Example

IIS7 (and the tooling around it) has wonderful new features. First of all managed code is now a first class citizen and can do (nearly) everything as the unmanaged API. Almost everything that could be accomplished by ISAPI filters and extensions is now possible with .NET HttpModules/HttpHandlers. Next IIS7 allows to seamlessly integrate your custom functionality with the configuration and management system. This includes the configuration file, the administration GUI and remote management features.

I wanted to test drive the new APIs so I decided to build a module that can change the value of the Server HTTP Header so that IIS can look to scanners like an Apache or whatever you want (I did this ages ago using an ISAPI filter). My module should feel like a built-in IIS feature with regards to configuration and management.

This scenario allows testing several new features of IIS7, e.g.

  • (ASP).NET code can change response headers even if they are not originating from the same "handler" (this also applies to request headers and server variables - btw)
  • Processing of all requests
  • Integration into the unified configuration system and feature delegation. The configuration section of the ServerHeader feature will live under <system.webServer>
  • Integration into the IIS7 GUI and the remote administration infrastructure

This was not hard to do, but it turns out that the whole solution is quite some code (mostly for the UI integration plumbing) – so I will split the walkthrough in several logical parts and explain the underlying concepts while we go. I plan to talk about the following topics:

  • The HttpModule
  • Configuration
  • Management Integration (on the server)
  • Management (aka UI) Integration (on the client)
  • Wrap up and Solution Structure
  • Deployment

Watch this space.


Work in Progress
Saturday, January 13, 2007 10:43:08 AM UTC  #   
 Tuesday, January 09, 2007

IIS7 Configuration API

IIS7 uses (nearly) standard .NET .config XML files for configuration. This is great and is one of the coolest features of IIS7 IMO. The metabase is gone (woohoo) and you can mix ASP.NET and IIS7 settings in a single web.config file. This means that you don't have to adjust settings in two places and that you can deploy your ASP.NET application together with IIS7 configuration. That's awesome.

How often have I wished in the past that I can configure Windows authentication in ASP.NET and IIS in a single step and without having to navigate GUIs. Like this:

<configuration>
 
<system.web>
   
<authentication mode="Windows" />
 
</system.web>

  <system.webServer>
   
<security>
     
<authentication>
       
<anonymousAuthentication enabled="false" />
       
<windowsAuthentication enabled="true" />
     
</authentication>
   
</security>
 
</system.webServer>
</configuration>

To read or modify configuration you have several choices, notepad, the IIS GUI, a command line tool (appcmd.exe) or the IIS configuration API.

You can find the API in the Microsoft.Web.Administration.dll assembly located in the GAC or \Windows\System32\Inetsrv. The most obvious class to start with is called ServerManager – this gives you full access to the IIS7 configuration and you can easily navigate through most settings using the Sites, Applications, ApplicationDomains and ApplicationPools collections. Another not so obvious class is called WebConfigurationManager which also gives you access to configuration. What's the difference and when to use which?

ServerManager is an administration (or design-time) API mostly useful for deployment and automated configuration. ServerManager is (currently) not designed for partial trust scenarios and some functionality requires elevated OS privileges.

WebConfigurationManager is a fast, light-weight runtime configuration API for applications, handlers and modules that need to read configuration settings. This is the one you want to use in your ASP.NET application code.

To get access to configuration you need a Configuration object. ServerManager features two methods called GetAdministrationConfiguration() and GetApplicationHostConfiguration() which return the Configuration object for the two machine wide config files (the Application class also has a method called GetWebConfiguration()). From there you usually call the GetSection() method and specify the configuration section you want to access using an XPath like expression, e.g. "system.webServer/directoryBrowse". WebConfiguration also has a GetSection() method – the configuration returned here is always the one for the current application.

GetSection() returns a ConfigurationSection (derived) class from which you can read and write configuration attributes and, when using ServerManager, write the changes back to the config file. The following code changes configuration to allow directory browsing for an application:

Configuration config = app.GetWebConfiguration();

// weak typed
ConfigurationSection sectionBrowse = config.GetSection
  (
"system.webServer/directoryBrowse");

sectionBrowse["enabled"] = true;

Those of you who have looked at ASP.NET custom configuration sections know that you can provide a class that does the mapping between the object and XML worlds. This allows using strongly typed properties instead of string values to change attributes. The IIS7 configuration API uses a similar approach (but not the same). You can provide a ConfigurationSection derived class that gives you properties – but the actual schema of the configuration section (enums, default and required values, min/max values etc.) is specified in an XML file. The reason for that is (I believe) that configuration has to be usable from managed and unmanaged code – and the custom attribute approach to define schema would tightly-couple the configuration section to the CLR.

The schema definition for the <directoryBrowse> section looks like this:

<sectionSchema name="system.webServer/directoryBrowse">
 
<attribute name="enabled" type="bool" defaultValue="false" />
 
<attribute name="showFlags" type="flags" defaultValue="Date, Time, Size, Extension">
   
<flag name="None" value="0" /> 
    
<flag name="Date" value="2" /> 
    
<flag name="Time" value="4" />
   
<flag name="Size" value="8" />
   
<flag name="Extension" value="16" />
   
<flag name="LongDate" value="32" /> 
  </attribute>
</sectionSchema>

You can find the complete schema file in \Windows\system32\inetsrv\config\schema.

The corresponding configuration section class would look like this:

public class DirectoryBrowseSection : ConfigurationSection
{
 
public static string SectionName = "system.webServer/directoryBrowse";

  public
bool Enabled
 
{
   
get { return (bool)base["enabled"]; }
   
set { base["enabled"] = (bool)value; }
 
}

  public EnumDirectoryBrowseShowFlags ShowFlags
 

   
get { return (EnumDirectoryBrowseShowFlags)base["showFlags"]; }
   
set { base["showFlags"] = (int)value;
  }
}

public enum EnumDirectoryBrowseShowFlags
{
 
None = 0,
 
Date = 2,
 
Time = 4,
 
Size = 8,
 
Extension = 16,
 
LongDate = 32
}

With such a strong typed wrapper, the configuration code looks more OO:

Configuration config = app.GetWebConfiguration();
DirectoryBrowseSection sectionBrowse = (DirectoryBrowseSection)
 
config.GetSection(
   
DirectoryBrowseSection.SectionName, 
    
typeof(DirectoryBrowseSection));

sectionBrowse.Enabled = true;

While technically there are already ConfigurationSection classes defined for all IIS7 and ASP.NET settings (in the Microsoft.Web.Management*.dll) – they are currently internal. Fortunately Kanwal from the IIS team posted a tool that generates configuration classes from the XML definition file. Simply point it at the IIS7 schema file and you will get an object model for all configuration groups and sections. Nice!

 



Tuesday, January 09, 2007 8:56:11 PM UTC  #   

ASP.NET Security WebCasts auf MSDN

Im Januar/Februar werde ich vier WebCasts zum Thema ASP.NET Security für MSDN Deutschland machen.

Genaue Informationen über den Februar reiche ich nach - aber im Januar haben wir folgendes auf dem Programm:

Security mit ASP.NET 2.0 (Teil 1-4) - Authentifizierung & Autorisierung mit ASP.NET 2.0
(Mitttwoch, 17.01.2007 16:00-17:00 Uhr)
ASP.NET verfügt über eine äußerst flexible Authentifizierungs- und Autorisierungs-Infrastruktur für Windows, Zertifikate und Custom Benutzer-Accounts. Dabei sind die Details für den Anwendungs-Code völlig irrelevant, und Seiten müssen nicht mit der eingesetzten Authentifizierungsmethode im Hinterkopf entwickelt werden. Um diese Infrastruktur effizient zu nutzen, muss man allerdings einen genaueren Blick auf die ASP.NET-Verarbeitungs-Pipeline und die vorhandenen Erweiterungs-Punkte werfen. Dieser Webcast beleuchtet die vorhandenen Authentifizierungs-Mechanismen und  untersucht, wie man durch Erweiterungen der Pipeline-Szenarien wie Single-Sign-On, Web Farms, Schutz von statischem Content sowei Mixed-Mode-Authentifierung implementieren kann. (Anmeldung)

Security mit ASP.NET 2.0 (Teil 2-4) - Eingabe-Validierung mit ASP.NET 2.0
(Montag, 29.01.2007 16:00-17:00 Uhr)
Böswillige oder einfach auch nur unerwartete Eingaben sind der Grund für die meisten Stabilitäts- und Sicherheits-Probleme in Anwendungen. Oder was ist der häufigste Grund für Programm-Abstürze bei Ihnen - Logikfehler oder unerwartete Eingabewerte? Zudem existieren eine Reihe von ernstzunehmenden Attacken, die sich fehlerhafte (bzw. nicht-existierende) Eingabe-Validierung zu Nutzen machen. Erfahren Sie mehr über typische Angriffe wie SQL, HTML und Script Injection, Cross Site Scripting oder Directory Traversal - und darüber, wie Sie sich dagegen wehren können. Beleuchtet werden weiterhin die eingebauten Eingabe-Validierungs-Dienste wie Request, ViewState und Event Validation sowie die Validation Controls und ihre Erweiterbarkeit. (Anmeldung)

 


Microsoft Deutschland Security Portal
Tuesday, January 09, 2007 7:46:21 AM UTC  #   
 Saturday, January 06, 2007

ASP.NET Control for CardSpace

CardSpace is a very promising new way of doing strong authentication across trust boundaries (it is much more than that, but there are already very good introductions and in-depth articles about it out there – see the links at the end of this post).

Adding CardSpace support to ASP.NET applications is very easy – you have to add a special <object> tag to a page and by submitting the containing form (or by doing a getElementById) you can trigger the client identity selector and transmit the encrypted XML token back to the web application. On the server side you can extract the token from the form, decrypt it using the private key of the server’s SSL certificate and process the contained claims. The <object> tag contains information about the card issuer, the token type and the required/optional claims, e.g.

<object type='application/x-informationcard' name='_selector'> 

  <param name='tokenType' value='urn:oasis:names:tc:SAML:1.0:assertion' />

  <param name='issuer' value='http://www.leastprivilege.com...' />

  <param name='requiredClaims' value='http://www.leastprivilege.com...' />

  <param name='optionalClaims' value='http://www.leastprivilege.com...' />

</object>

These are very low-entry technology requirements and can be done by any application that supports SSL, can emit HTML and decrypt standard W3C encrypted XML (e.g. sandbox.netfx3.com is implemented in ASP.NET whereas Kim Cameron’s blog uses PHP). Currently Microsoft only supports IE7, but there are plugins for Firefox and Safari available. For non-web applications, CardSpace support is integrated into WCF.

Due to the lack of broad support (OS, browsers and identity providers) and some other problems that need to get solved first (e.g. mobility of cards), most of you cannot just make an immediate switch to CardSpace – but it may be interesting for you to offer CardSpace authentication as an alternative to a password based logon. 

To find out how hard it really is to add CardSpace support to an existing username/password based application, I started with a pretty standard ASP.NET application that uses all the usual technologies that Microsoft wants us to use (master pages, themes, the security controls, forms authentication, profile, navigation etc.). I will write about my experiences in a different post (e.g. about possible migration scenarios, how to integrate token/claims based authentication / authorization into you back-end without impacting your existing application and some management issues and procedures that need to be thought about).

One thing I wrote during that experiment is an ASP.NET server control to emit the right CardSpace object tag and the necessary JavaScript to invoke the identity selector on the client. This gives you a server side object to program against, makes maintenance easier and solves some problems you might run into when using CardSpace with master pages.

The CardSpaceSelector markup is straightforward:

<lp:CardSpaceSelector runat="server" ID="_selector"

  IssuerType="Managed"

  Issuer="http://www.leastprivilege.com/sts"

  TokenType="urn:oasis:names:tc:SAML:1.0:assertion">

               

  <lp:ClaimType>http://www.leastprivilege.com/.../givenname</lp:ClaimType>

  <lp:ClaimType>http://www.leastprivilege.com/.../surname</lp:ClaimType>

 

  <lp:ClaimType IsOptional="true">

    http://www.leastprivilege.com/.../optionalclaim</lp:ClaimType>

</lp:CardSpaceSelector>

This renders an <object> tag, a clickable image and a JavaScript click handler that stores the encrypted XML in a hidden form field. On the server side you can retrieve the encrypted XML directly from the hidden field or from the XmlToken property of the control. Afterwards you can decrypt the token, e.g. using the TokenProcessor library from the SDK.

protected void Page_Load(object sender, EventArgs e)

{

  if (IsPostBack)

  {

    // retrieve encrypted XML

    string xmlToken = _selector.XmlToken;

    if (!string.IsNullOrEmpty(xmlToken))

    {

      try

      {

        // parse and decrypt the token

        Token token = new Token(xmlToken);

 

        // access claims

      }

      catch (Exception ex)

      { … }

    }

  }

}

CardSpaceSelector has a number of properties that can make your life easier, e.g.

IssuerType
This enum has two values ‘SelfIssued’ and ‘Managed’. If you select ‘SelfIssued’ then the issuer URI for self-issued cards will be emitted. If you select ‘Managed’ you have to set the issuer URI yourself.

Issuer and IssuerPolicy
Specifies the URIs for the issuer and the issuer policy.

TokenType
Specifies the token type. If not set, the URI for SAML 1.0 will be used.

HiddenFieldName
Specifies the name of the hidden field where the encrypted XML token gets stored on the client. The default is __XMLTOKEN.

XmlToken
Contains the encrypted XML token if an InfoCard was selected.

AutoPostBack
If set to true, the control will automatically do a postback after the user has selected an InfoCard.

ImageUrl
Let’s you change the default image.

In the attached zip you can find the source for the control alongside a little demo ASP.NET app that uses it. Be aware that the identity selector will only pop up if you are running over SSL – this is needed to encrypt the token and to create a unique PPID for your application.
Maybe this is useful for you. Write me if you have any comments, suggestions or found a bug…

Some additional reading

Thanks for your help: Brock Allen, Jason Diamond and Christian Wenz

CardSpaceSelector.zip (38.55 KB)

 


Tools | Tools for Thinktecture | Work in Progress
Saturday, January 06, 2007 7:54:17 AM UTC  #   
 Friday, January 05, 2007

Protocol Transition Revisited

Protocol Transition is a handy technology when you have to "convert" a non-Windows credentials to Kerberos.

Since PT does not require to know the password of an account to get a token, access to resources using this token is limited. You only have access to local resources if you have the TCB privilege and to remote resources via constrained delegation.

But sometimes you need access to local resources or, even worse, to access a remote resource you first have to read some local information (remote Performance Counters come to my mind here). And of course it is not recommended to elevate the privileges of your main application to SYSTEM or similar to make Protocol Transition work in these scenarios.

Keith describes an excellent solution how to factor out PT logic into a separate highly privileged process to create the tokens - and also adds some tricky ACL and token handle code - very interesting. Read it here.

 


For Your Favourites
Friday, January 05, 2007 4:34:09 PM UTC  #   
 Saturday, December 23, 2006

UAC DropPad

What bugs me from time to time with Vista and UAC is that I cannot directly start data files (like .sln files) elevated - I always have to start the application (like Visual Studio) elevated first and open the solution from there.

So I wrote a little WinForms app that allows to drag&drop arbitrary files on it and starts the associated application elevated.

The bare bones were easy to write, but my WinForms skills suck - so Jörg Neumann added some finishing touches and UI magic to it. So if this is useful for you, feel free to take it as our X-mas present.

Merry Christmas!

UacDropPad.zip (27.17 KB)

UPDATE1: I slightly modified the code - if you don't want to have an open window around - just keep a shortcut to UacDropPad.exe on your desktop and drag&drop the files you wannt to start elevated on the icon.

UPDATE2: Brock doesn't like to drag&drop. You can also add UacDropPad to the "Send to" menu - just copy a link to \Users\<user>\AppData\Roaming\Microsoft\Windows\SendTo.

 


Tools | Tools for Thinktecture
Saturday, December 23, 2006 9:02:32 PM UTC  #   
 Saturday, December 09, 2006

Known Differences Between IIS7 Integrated and Classic Mode

Read about it here.

 


For Your Favourites | Work in Progress
Saturday, December 09, 2006 8:19:32 AM UTC  #   
 Thursday, December 07, 2006

Bug in 2.0 Jitter?!

Just found this (scroll down to ".NET Framework 2.0 Security Hole") via Marc's Blog.

Not sure if this is true - but it sounds scary...this brings me back to an old point - don't run untrusted apps off the Internet - and be careful with technologies that allow this by default ;)

 


Work in Progress
Thursday, December 07, 2006 10:02:19 PM UTC  #   
 Wednesday, December 06, 2006

"Manage Private Key" on Vista

A while ago I wrote how to set ACLs on a private key container.

Today I spotted a new context menu item in the "Certificates" MMC snap-in on Vista. Right-click a certificate and select "All Actions->Manage Private Key" to get to the ACL dialog of the key container. nice!

 


Work in Progress
Wednesday, December 06, 2006 9:17:58 PM UTC  #   
 Friday, December 01, 2006

TVP Slides

Thanks to everyone who attended the Connected Systems Roadshow this week in Reading! We had great fun.

You can find the slides and the architecture sample I wrote during the talk here.

Mike - who did a great talk on hosting Workflow in ASP.NET has also uploaded his slides and demo here. Thanks Mike!

 


Conferences | Work in Progress
Friday, December 01, 2006 9:52:17 AM UTC  #   
 Monday, November 20, 2006

HttpSysCfg

A (kind of) polished version of my HTTP.SYS ACL/SSL helper tool can be found on the thinktecture tools page.

 


Tools
Monday, November 20, 2006 11:16:30 PM UTC  #   

AntiXss 1.5

Finally...the new version of the AntiXss library is now available for download. Go get it!

New features include:

  • support for partial trust :)
  • more encoding functions
  • tutorials

Happy encoding!

 


For Your Favourites
Monday, November 20, 2006 8:49:55 PM UTC  #   
 Tuesday, November 14, 2006

AzManBulkImport Update

Joe sent me a new version of his AzMan bulk importer - in the .zip is a changes document. enjoy!

AzManBulkImport123.zip (6.25 KB)

 


Tools
Tuesday, November 14, 2006 2:43:38 PM UTC  #   
 Thursday, November 02, 2006

SecureString Redux

Read more over at Shawn's

http://blogs.msdn.com/shawnfa/archive/2006/11/01/securestring-redux.aspx

 


For Your Favourites
Thursday, November 02, 2006 5:51:38 PM UTC  #   
 Wednesday, November 01, 2006

CAS und ClickOnce Webcast

Ich habe total vergessen die versprochenen Samples für den CAS & ClickOnce Webcast hochzuladen (danke Andreas für die Erinnerung).

ClickOnce und NoTouch.zip (873.58 KB)

 



Wednesday, November 01, 2006 5:10:09 PM UTC  #   
 Monday, October 30, 2006

Interview mit Mike Downen

Mike Downen ist der Security Program Manager der CLR - dieses Interview habe ich im Sommer für das Reach Magazine geführt, und ist jetzt online auf MSDN.

http://www.microsoft.com/germany/msdn/security/interview27102006.mspx


Microsoft Deutschland Security Portal
Monday, October 30, 2006 10:30:47 PM UTC  #   
 Friday, October 27, 2006

So much for SecureString

Every once in a while questions come up regarding the usefulness of SecureString.

StaceyW posted this link today...:O

Interestingly, Ian told me that the latest build of WPF also removed the SecureString functionality from the PasswordBox and replaced it with an ordinary string...

 


Work in Progress
Friday, October 27, 2006 6:18:28 AM UTC  #   
 Wednesday, October 25, 2006

Certificate References in Configuration

When you are doing STS work (that goes beyond the hardcoded SDK samples), you need programmatic access to certificates from the store. To make this easier I hacked together a configuration section for certificate references, e.g.

<certificateReferences>

  <add name="Sts"

       findValue="CN=STS"

       x509FindType="FindBySubjectDistinguishedName"

       storeLocation="LocalMachine"

       storeName="My" />

 

  <add name="http://localhost:9000/IssuedToken"

       findValue="CN=Service"

       x509FindType="FindBySubjectDistinguishedName"

       storeLocation="LocalMachine"

       storeName="AddressBook" />

</certificateReferences>

...and a static class that gives you easy access to the certificate information (e.g. in your STS):

// get the encryption certificate for the requested service

private void SetTargetToken(string appliesTo)

{

  CertificateReferenceElement config =

    CertificateReference.GetReference(appliesTo);

 

  ProofKeyEncryptionToken = FederationUtilities.GetX509TokenFromCert(

    config.StoreName,

    config.StoreLocation,

    config.FindValue);

}

CertificateReference.zip (14.95 KB)

 


Work in Progress
Wednesday, October 25, 2006 9:00:53 AM UTC  #   

TechEd 2006

TechEd is in two weeks - and I am really looking forward to it!

I will do a talk on the architecture track -

ARC309 Security is a Feature - Best Practices for Designing Secure Distributed .NET Applications 
Thu Nov 9 17:30 - 18:45
 
Security is nothing you can buy or bolt onto a product at the end. The most common mitigation techniques are not hard to implement, but have to be planned and designed right from the start. Furthermore the .NET Framework and the Windows platform provide a vast amount of security APIs and technologies to choose from. Find out which are the right ones for you and how they can improve your design and architecture. Furthermore you'll get some common best practices, tools and tips to make your life easier.

Since I am only doing one talk, but will hang out the whole week - there will be extended time for networking and partying :) Stop by and say hello!

 


Conferences
Wednesday, October 25, 2006 8:23:54 AM UTC  #   
 Tuesday, October 24, 2006

Simple Sandboxing API Artikel

Es haben mich schon ein paar Leute danach gefragt, der Artikel (ursprünglich erschienen im DotNet Magazin) ist nun auch als .pdf bei MSDN verfügbar.

 


Microsoft Deutschland Security Portal
Tuesday, October 24, 2006 12:45:16 PM UTC  #   
 Monday, October 23, 2006

MSDN Webcast: Zertifikate in .NET 2.0

Danke an alle Teilnehmer des Zertifikate Webcasts. Anbei finden Sie die Slides & den Code. Bei Rückfragen einfach Mail an mich.

WebCastDEZertifikate.zip (558.36 KB)

 


Microsoft Deutschland Security Portal
Monday, October 23, 2006 1:54:49 PM UTC  #   

ADC Nachtrag

Danke an alle Teilnehmer meiner beiden Vorträge auf der ADC. Ich hoffe es hat euch genauso viel Spass gemacht wie mir :)

Bei weiteren Fragen - einfach Email oder Comment an mich.

 


Microsoft Deutschland Security Portal
Monday, October 23, 2006 10:13:06 AM UTC  #   

IIS7 loads User Profiles

That's excellent news.

This enables using user-scoped DPAPI keys and certificate stores/key containers.

 


Work in Progress
Monday, October 23, 2006 10:06:08 AM UTC  #   
 Friday, October 20, 2006

WCF proxies in partially trusted ASP.NET Apps

Summary: OK - I got this working - but you may not like the solution.

So it still bugs me that WCF won't directly support partial trust in V1. This means that it is much harder for partially trusted ASP.NET applications to host or use WCF services (same applies of course to all WCF clients like ClickOnce applications).

Today I decided to give it a go and find out how hard it really is. Here is what happened.

<sidebar>
If you want to call something from partial trust which does not allow partially trusted callers, you have to wrap it in/assert full trust (keep that in mind - we will need this later on) - or as my good friend Marcus would say: "the devil is in the detail" :)
</sidebar>

OK - so after you have a working client/service in full trust, these are the necessary steps:

  • Move the WCF proxy to a separate assembly.
  • Give that assembly a strong name.
  • To be able to call the proxy from partial trust, you have to add a [assembly: AllowPartiallyTrustedCallers] attribute to the proxy assembly.
  • Assert full trust in the proxy. The easiest way to do this is by adding an attribute on top of the proxy class.

[SecurityPermission(SecurityAction.Assert, Unrestricted=true)]

public class Proxy

{

    ...

}

  • Create a new policy file. It is recommended to use the medium trust policy as a starting point. You can find the policy files in the framework configuration directory. The medium trust policy is called 'web_mediumtrust.config'

  • You have to add a new code group for your proxy assembly to the policy file granting full trust. This code group should go directly under the 'AllCode' grop. Use a StrongNameMembershipCondition to identify the proxy (you get strong names in the right format from secutil.exe with the -hex and -s option).

<CodeGroup

  class="UnionCodeGroup"

  version="1"

  PermissionSetName="FullTrust">

 

  <IMembershipCondition

    class="StrongNameMembershipCondition"

    version="1"

    PublicKeyBlob="00..C9" />

</CodeGroup>

  • Add a new trust level to global web.config that points to your policy file

<securityPolicy>

  <trustLevel name="WCF" policyFile="web_WCF.config" />

</securityPolicy>

 

  • Apply this trust level to your application (either in your local web.config or via a location element in an upstream config)

<trust level="WCF" />

So far so good - the proxy is separated from the application and has full trust. But when you try running the application now, you will get an ugly ConfigurationErrorException saying the system.serviceModel/client configuration section cannot be accessed because the assembly does not allow partially trusted callers..WTF?!

After following an adventurous code path through the .NET configuration system and seeing variables named like isTrusted and isLocationTrusted - I suddenly knew what is going on.

I remember vaguely that ASP.NET has this concept of trusted configuration locations - e.g. a configuration handler that is registered in machine.config gets full trust even if the application using that section is running in partial trust. This on the other hand means that if a configuration handler is demanding full trust - and thats what System.ServiceModel.dll is essentially doing - the configuration section can't be in a partially trusted location.

I then tried to move the <system.serviceModel> configuration section to a location element in global web.config - and (drum roll) - it worked...

<location path="Default Web Site/PartialTrustWcfClient">

  <system.serviceModel>

    ...

  </system.serviceModel>

</location>

By moving the config section we basically "wrapped" it in full trust. The only other option I see is wrapping the configuration section classes instead. This is quite some work and you would loose intellisense.

OK - so this just shows that partial trust is an un-supported and un-tested scenario in WCF V1. But it works and is - if you have to use WCF - better than running ASP.NET in full trust.

You can find the artifacts here.


ASP.NET | WCF | Work in Progress
Friday, October 20, 2006 10:09:22 AM UTC  #   
 Tuesday, October 17, 2006

Webcasts im Oktober

Nächste Woche mache ich zwei Webcasts rund um Zertifikate und CAS. Bei Interesse einfach reinschauen.

Arbeiten mit Zertifikaten und PKCS#7/CMS in .NET 2.0
Montag, 23.10.2006 14:00-15:00 Uhr
Eines der meist verlangten Features für .NET 2.0 war ohne Zweifel die Unterstützung für X.509-Zertifikate sowie die kryptografischen Operationen, die damit nach PKCS#7/CMS-Standard konform durchgeführt werden können. Dieser Webcast beleuchtet die beiden neuen Namensräume System.Security.Cryptography.X509Certificates und Pkcs und gibt Ihnen einen Überblick, wie man mit Zertifikaten und dem Windows Zertifikat-Speicher arbeitet. Außerdem beschäftigen wir uns mit der Anwendung von Verschlüsselung und mit digitalen Signaturen. (Anmelden)

Den Client im Griff mit Code Access Security
Donnerstag, 26.10.2006 14:00-15:00 Uhr
Code Access Security (CAS) ist eine Technologie, die Benutzer vor bösartigem oder auch einfach nur fehlerhaftem Code schützen soll. In der Praxis stolpert man über dieses Sicherheits-Feature immer dann, wenn man z.B. eine Anwendung von einem Netzwerk-Laufwerk oder Web Server starten will. Dieser Webcast gibt eine Einführung in die Funktionsweise von CAS und der dazugehörgen Security Policy sowie Tipps & Tricks, die einem die Arbeit mit dieser Technologie erleichtern können. Abgerundet wird das ganze mit einem Blick auf ClickOnce, einem Deployment-Feature von .NET 2.0, das die typischsten CAS-Probleme zu lösen verspricht. (Anmelden)


Microsoft Deutschland Security Portal
Tuesday, October 17, 2006 11:39:26 AM UTC  #