Category Archives: Security

HTTPS is here

During the last few months, I have written several blog posts in my company’s blog about how to secure a site with HTTPS. I started off talking about how to encrypt an Azure web site with Let’s encrypt, and then continued on to discuss how to try to prevent the browser being tricked into making non-HTTPS requests to the server. Finally, I talked about how to narrow the range of certificate issuers we want the browser to trust for our site in order to prevent ill-behaving issuers to make our site insecure, using so-called certificate pinning.

Quite recently, there has been discussions on how HTTPS is gaining traction, and that HTTPS is becoming the norm. Your web site should use it, too.

Getting user information programmatically from Windows Identity Foundation

You can use the Windows Identity Foundation SDK to replace the authentication scheme of your ASP.NET web application. Most notably, this is useful for making your application claims-aware, which allows it to seamlessly play together with solutions like Active Directory Federation Services or the Windows Azure AppFabric Access Service. This is useful for a various number of SSO and federated authentication scenarios.

Basically, what you do is that you switch off the built-in authentication in ASP.NET like forms-based authentication, and let WIF act as a proxy in front of your application. WIF uses the authorization settings in web.config (/configuration/system.web/authorization and /configuration/location/system.web/authorization elements) and authenticates the user before the ASP.NET application receives the request. See WS-Federated Authentication Module Overview for details

So, when the application receives the request, the user is already authenticated, which is fine. However, there are times when the application needs to know who the user is, or getting access to the other claims that were provided from the identity service. Luckily, this is available on the HTTP context. Say, for instance, if you wish to find the email address of the logged-in user, you can do it like so:

protected void Page_Load(object sender, EventArgs e)
{
    var claimsIdentity = Context.User.Identity as IClaimsIdentity;
    foreach (var claim in claimsIdentity.Claims)
    {
        if (claim.ClaimType == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress")
        {
            var email = claim.Value;
        }
    }
}

If the user was authenticated using claims, Context.User.Identity will be an IClaimsIdentity which will contain a number of claims about the user. We can then iterate over these claims to find the one that we want.

The claim types are denoted using XML namespaces, which are a little bit cumbersome to work with. So, to make it easier to access, we iterate over the list of claims, and make all the claims available on a common object:

public static class IdentityExtension
{
    public static DynamicUser GetUserFromClaims(this HttpContext context)
    {
        var claimsIdentity = context.User.Identity as IClaimsIdentity;
        if (claimsIdentity == null) throw new FailedAuthenticationFaultException();
        return new DynamicUser(claimsIdentity.Claims);
    }
}
public class DynamicUser : DynamicObject
{
    private readonly ClaimCollection _claims;
    public DynamicUser(ClaimCollection claims)
    {
        _claims = claims;
        Id = ClaimsValue("nameidentifier")[0];
    }
    public string Id { get; private set; }
    public bool IsInRole(string role)
    {
        return ClaimsValue("role").Any(c => c.Equals(role, StringComparison.OrdinalIgnoreCase));
    }
    private string[] ClaimsValue(string claimSuffix)
    {
        return _claims.Where(c => c.ClaimType.EndsWith(claimSuffix)).Select(c => c.Value).ToArray();
    }
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        var claimValue = ClaimsValue(binder.Name.ToLowerInvariant());
        if (claimValue.Length == 0)
        {
            return base.TryGetMember(binder, out result);
        }
        if (claimValue.Length == 1)
        {
            result = claimValue[0];
        }
        else
        {
            result = claimValue;
        }
        return true;
    }
}

Then, we can access the claim values using a prefix of the actual XML namespace of the claim type:

protected void Page_Load(object sender, EventArgs e)
{
    var user = Context.GetUserFromClaims();
    var id = user.Id;
    var username = user.Name; // "John Doe"
}

When hooking up the application to Windows Azure AppFabric Access Control Service (ACS), which claims that the application will receive depends on your rule group configuration. Here are some examples:

Claim type Shorthand Example value
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier user.Id NHsTR1UXFI9xYk1xIRUNfucZ4/a5OWiILHlNyNEXozP=
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name user.Name John Doe
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress user.Emailaddress john.doe@hotmail.com

If you set up role claim rules in ACS, you can even get information about the user’s roles so that you can do authorization in the code:

protected void Page_Load(object sender, EventArgs e)
{
    var user = Context.GetUserFromClaims();
    var isAdmin = user.IsInRole("administrator"):
}

Atlassian products hacked

Yesterday I got an email from Atlassian, the makers of applications such as Confluence and JIRA, that said that their own hosted customer site had been hacked and that my password was possibly compromised. Apparently, some passwords were stored in clear text in the database and that the hackers had gotten hand on these (See Atlassian’s blog post about the incident).

One thing is that the perpetrators could use this information to get details about my relationship with Atlassian, among other things my license keys for Atlassian products. Even worse is that they could try and use the passwords to get into my accounts at other sites. That would be successful if I used the very usual and very baaad practice of reusing the same (user name and) password on several sites and applications. Luckily I don’t.

Here is what Atlassian states about why this could happen:

During July 2008, we migrated our customer database into Atlassian Crowd, our identity management product, and all customer passwords were encrypted. However, the old database table was not taken offline or deleted, and it is this database table that we believe could have been exposed during the breach

Trying to act as a responsible company, Atlassian goes on to list what they have learned from the incident. Among other things, they state that

The legacy customer database, with passwords stored in plain text, was a liability. Even though it wasn’t active, it should have been deleted. There’s no logical explanation for why it wasn’t, other than as we moved off one project, and on to the next one, we dropped the ball and screwed up.

I am sorry, but I find it hard to believe that this is the entire truth. Yesterday afternoon (European time) I went to their site and on the login screen I used their “Forgot my password” functionality. Can you guess what happened? They sent me an email with my password in clear text! So, I would indeed say that this “legacy database” is indeed active…

Later on the day yesterday, I also got an email from the Apache Software Foundation that their JIRA instance also have been hacked. See their blog entry about the issue. According to the blog entry, the situation is a bit better than it is at Atlassian. They state that

If you are a user of the Apache hosted JIRA, Bugzilla, or Confluence, a hashed copy of your password has been compromised.

JIRA and Confluence both use a SHA-512 hash, but without a random salt. We believe the risk to simple passwords based on dictionary words is quite high, and most users should rotate their passwords.

At least, the password was not stored in clear text, which is of course much better than having it in clear text. However, the compromised passwords could still be useful for an attacher because they are not salted. It allows an hacker to compare hashes of other accounts with hashes of a known password which would allow a dictionary attack (as is stated).

This is not security for the crowds (pun intended).

The mother lode for IIS, Kerberos and IWA information

I just came across Ken Schaefer’s blog, and I found that he has posted a series of excellent posts concerning various aspects of getting Integrated Windows Authentication / Kerberos to work on IIS:

Simply a great source of information!

Getting Integrated Windows Authentication to work on your laptop

When developing an ASP.NET solution for a customer, I run the application locally on my laptop (IIS 5.1, Win XP). For a realistic test scenario I had set up a separate host name for my local computer in my hosts file. I then enabled my application for Integrated Windows Authentication, and was a bit puzzled by why it did not work.

Internet Explorer did not automatically authenticate me when wisiting the web application. The problem turned out to be that there was no Service Principal Name registered in Active Directory that associated the hostname with my computer. Hence, the client could not request a Kerberos service ticket for my web application.

The solution was to run the setspn.exe tool (available in the Windows Server 2003 Support Tools package) to create the desired SPN entry in Active Directory. For example:

setspn -A HOST/my.fake.hostname.com MYCOMPUTER

(where MYCOMPUTER is the network computer name for my workstation). You have to be a domain administrator to run this command.

The effect of running this command is that ‘HOST/my.fake.hostname.com’ will be added to the multi value field ‘servicePrincipalName’ on my computer’s entry in Active Directory.

Windows CardSpace anyone?

I was at a presentation about Windows CardSpace a couple of days ago. Beautiful technology it might be, but I cannot help questioning the adoption of CardSpace in the real world. I cannot say I have ever come across any site that supports it. Have you? (If so, please let me know). On the other hand, OpenId seems to get quite a bit of momentum being supported by some of the big Internet companies out there (Yahoo!, Google, AOL to name a few).

OK, CardSpace and OpenId do not offer exactly the same solution, and are in some respects not comparable. Biggest difference would be OpenId’s reliance of passwords as authentication mechanism (which is one of the reasons for its lack of phishing attack protection), while CardSpace solves this problem using cryptography. However, there are a lot of similarities:

  • Both offer a distributed model that accepts various Identity providers (the user can choose from a number of IdPs)
  • Both address the challenge with maintaining several user account/password for different Internet services

“OpenId is no good because it isn’t secure”

When asking the presenter about the adoption of CardSpace versus the adoption of OpenId, this was his response. I think that this is a gross oversimplification that serves no other purpose than spreading FUD about security.

First of all, if OpenId is good enough for Yahoo! and the like, it will probably be good enough for 80% of the Internet sites out there. I can think of a lot more sites out there that require “less security” than Yahoo! out there, than sites  that require a higher security level.

Secondly, security is not binary (secure – not secure). There are different levels of security. Saying that one solution is secure and another one isn’t, is being ignorant towards the field of security. Basically, security (as everything else) come at a cost. In the case of CardSpace, the cost is maintenance of your cards and the corresponding public/private key infrastructure. I do not know CardSpace in detail, but a main challenge here I suspect will be exactly the same as for other public/private key based solutions: how do you bring your keys with you? For instance, if you created a card in a CardSpace on your workstation at work, how do you bring them with you when you want to log in from your home computer or from an Internet café? Having them on a USB stick would probably be a choice, but even that limits the usage quite a lot. Passwords, on the other hand, you carry with you in your head (at least, that’s the idea ;)).

OOPSLA’07 – Security

My second day at OOPSLA consisted of two security related workshops. The first one as entitled “Security Patterns and Secure Software Architecture” and was presented by Munawar Hafiz. Security patterns seems to be an interesting topic and will perhaps be an important tool for security professionals.

The second tutorial was “Software Security: Building Security in” by Gary MacGraw. Although I have read a couple of his books, I found the tutorial very interesting. Many good insights (and some funny ones) were touched upon.

Perimeter defense does not work

One of the important things is that making an insecure application secure by putting up a firewall in front of it is flawed for many reasons. Trying to shield the application from the world is kind of the opposite of what we want to do. We want to be on the net, hence we should make the applications secure accordingly. Furthermore, it will not prevent attacks from insiders.

Security people’s job is to say “no”!

I can honestly say that this has crossed my mind one or few times. Although I am often involved with security, my job is not to say no, so hence I can deduce that I am not a “security person”. 🙂

Does the choice if programming language matter for security?

According to Gary MacGraw, it certainly does. For security, keep away from C and C++. In general, you should select a language that offers type safety. (This excludes C and C++). Furthermore, a question is if a statically typed language is better for security than a dynamically typed language. In my opinion, the answer here is not clear, although the presenter would probably go for a statically typed language.

More code – more bugs

This holds true for any bugs, not only those related to security. Hence, this is a fact that all people dealing with software development should be aware of. When your codebase grows, your number of bugs grow. Simple as that. You should honestly work on reducing your codebase as much as possible.

Security is not a feature or a function

Security is more of a quality aspect rather than a feature. I think this makes very much sense, and in fact I think that is reflected in Microsoft’s notion of “trustworthy computing”.

One-pager architecture

A good starting point for doing a security review of the architecture is to start with a one-page logical overview of the application as a starting point for discussion. I guess this is not only a practice related to security.

Penetration testing has limited use

I guess this can be summarized as follows: Penetration testing cannot verify that your code is good. It can only verify that your code stinks. The thought here is that penetration testing can only discover the uttermost serious problems, and running penetration testing is alone not enough to conclude that your application is secure.

Attackers use same tools as software people do

Attackers use compilers, decompilers, static analysis tools, coverage tools the same way as software developers do. Hence, developers who are familiar with these tools should learn how attackers use them so that they can defend against it. Network people would not know a compiler if it bit them.

Time and state will be biggest problem in the future

Today, proper input handling is regarded as the biggest security problem in applications. Looking into the crystal ball, time and state will probably move up to be the most important one since we see applications getting more distributed all the time and keeping track of time and state across locations will be more important.

Norwegian sites leaking information

Norwegian tabloid Dagbladet revealed yesterday that several commercial and non-commercial sites can be exploited to perform identity theft.

In Norway, all persons get assigned a unique number (‘fødselsnummer in Norwegian), similar to the US Social Security Number. Altough law restrictions apply, several sites use this number for uniquely identifying a person.

In this particular case, a hacker created a tool that could reveal identity information by collecting information from several sites, including the following steps:

  • Generate a random identifier. The format and the algorithm for creating one is publicly known.
  • Use site 1 to test whether the generated identifier is in use. This is possible because site 1 uses the number as user name. The logon procedure acts differently depending on whether the user name exists.
  • Use site 2 to get personal details about the person to which the generated identifier belongs. (Surname, given name, address)

This is of course possible because the sites are designed poorly and leak information (OWASP Top Ten vulnerability #6). Second mistake is that site number two use the unique number for authentication.