posted on 30 January 2013

5 comments

Prevent Session Hijacking (Man-In-The-Middle Attacks) in ASP.NET

TAGS: Asp.Net,Security,VB

PART 1 – Introduction

Session hijacking is a collective term used to describe methods that allow one client to impersonate another, thereby giving the hijacking client the same access rights as the target client. The general rule is: Nothing that goes across the network over the http protocol is safe (except if it is encrypted and it is used in certain way).

The first obvious way to protect our web site from Session Hijacking attacks is to force SSL at all times. This will provide the ultimate protection, but unfortunately will come at a price. The main problem with this approach is that there will be some level of overhead due to the encryption SSL require. This highly dependent on the server hardware, server software, number of site users, typical session length etc.

Because of the above concerns, most web sites nowadays use SSL only for the login page. By doing this they ensure that the user’s login credentials are safely transmitted to the web server, so there is no way for the malicious user to obtain them. Usually after the web server authenticates the user, it issues authentication cookie, so it can recognize the user for all following user’s requests. The downside of this approach is that the authentication cookie is transferred unsecurely i.e. over http and therefore they are extremely vulnerable.

Diagram 1: Session hijacking




1. Credential transmission (assuming the connection is over https i.e. it is safe) 
2. Credential confirmation. The web server issue an authentication cookie (assuming the connection is over https i.e. it is safe)
3. Data request over http. The authentication cookie is also transmitted.
4. Data response over http.
5. The hacker capture all data, transmitted over http i.e. points 3 and 4. This includes the authentication cookie which the web server issue.
6. The hacker makes a request using the captured authentication cookie.
7. The web server validates the authentication cookie. At this point the web server does not make any difference between the hacker and the victim.

PART 2 – The Problem

To illustrate the problem I wrote a simple web site (please find the download link below) which contains the following pages.

1. Default.aspx – insecure page 2. MyAccount.aspx – secured page, using the build in asp.net forms authentication mechanism. 2. Login.aspx 3. LogOff.aspx

You can switch between secured and unsecured version of my web site by changing the value of the FORCE_SECURE key in the web.config file. If FORCE_SECURE is set to False, you are running an insecure version of the web site. Otherwise if you set the FORCE_SECURE to True, you will switch to the safe version of the web site.

First let’s have some fun with FORCE_SECURE set to False. For this example I’ll use the Chrome browser, you can use IE if you want. Just do not use Firefox for now, as I will use it for the second part of the demo.

To make things easier to understand I’ve added a simple user control (to all pages) which just lists all currently stored cookies. I suggest you clear your cookies before running the example (via ctrl-shift-delete). This is however optional, but if you don’t do it, you will probably see some of your previously stored cookies for your localhost. Please follow the steps below:

Figure 1: Home page

Figure 1 just shows the home page while the user is not logged in.

Figure 2: Login page

Figure 2 the user is entering the login details. Note that this page is accessed via HTTPS, so it is secured. Please note until this point there are no cookies stored.

Figure 3: Home page. The user is authenticated.

At this point the user is authenticated and the web site issued an authentication cookie. Just for clarification I named this cookie AUTHENTICATIONCOOKIE.

<authentication mode="Forms">
      <forms name=".AUTHENTICATIONCOOKIE" loginUrl="login.aspx" protection="All" timeout="240" slidingExpiration="true" />
</authentication>

Note that here the home page is accessed via HTTP, this basically means that the traffic is not encrypted and can easily be sniffed.
There are lot of software available for sniffing and analysing the web traffic. Some apps can even do the whole hacking procedure for you i.e. using your android phone you can hack into someone’s Facebook account with just a few clicks (Assuming he browse over HTTP and you are both connected to the same router). Basically as we already know if the data is transmitted over http, it can easily be stolen. So let’s assume that the malicious user stole (by using some software) the AUTHENTICATIONCOOKIE in the example above.

Figure 4: My Account page accessed over SSL.

Figure 4 shows the My Account page. Note that this page is accessed via HTTPS, so it is secured (or as we will see in a bit, it is supposed to be).

Figure 5: Trying to access the My Account page in different browser.

Now let’s open a different browser (in my case Firefox) and try to access the my account page. Of course as the page is protected via asp.net forms authentication mechanism, this actually redirects to the login page. The malicious user does not have a valid user name and password, however what he has is the stolen AUTHENTICATIONCOOKIE.

Figure 6: Inject the stolen cookie using JavaScript.

This is where the fun starts! Using firebug and simple JavaScript, the hacker injects the stolen cookie.

Figure 7: The My Account page is now accessible.

At this point, the web site does not make any difference between the victim and the hacker. As you see the hacker can now access the “secured” My Account page.

Just to be clear, this is not ASP.NET vulnerability. If you want a more real life example you can try the same with your Facebook account. I’ll not go into details here, but if you run the code below, replacing the ‘XXX’ values with the one you “stole” from YOUR account, you should be able to login successfully.

Of course I strongly discourage you to play with someone else’s account.

Javascript:void(document.cookie="c_user=XXXXXXX"); 
Javascript:void(document.cookie="lu=XXXXXXXXXXX"); 
Javascript:void(document.cookie="xs=XXXXXXXXXXX");

Please note this works at the time of writing this article, Facebook may of course change this at any time.

PART 3 – The Solution

The main goal here is to fully protect the My Account page. In a real life web site you may want to add this protection to you shopping basket, payment page etc.

To accomplish this we are going to use a new SECURED Cookie along with the asp.net forms authentication.

Login.aspx

Dim user As Users = Users.getCollection.Where(Function(o) o.UserName = sUserName AndAlso o.Password = sPassword).FirstOrDefault

If user IsNot Nothing Then

'Should we enforce the security
If CBool(ConfigurationManager.AppSettings("FORCE_SECURE")) Then
         	'set secure login cookie
Helpers.CookieHelper.StoreSecureCookie(Helpers.EncryptionHelper.Encrypt(user.Token))
               End If

                'login
                FormsAuthentication.RedirectFromLoginPage(user.UserId, False)
Else
                lblMessage.Text = "Invalid user name or password!"
End If

CookieHelper.vb

        Public Shared Sub StoreSecureCookie(ByVal sToken As String)
            Dim cookie As New HttpCookie(SecureCookie)
            cookie.Secure = True
            cookie.Value = sToken
            cookie.Expires = DateTime.UtcNow.AddDays(1)
            HttpContext.Current.Response.Cookies.Add(cookie)
        End Sub

For this example, I am going to use a simple class to represent the user accounts.

Users.vb

Public Class Users

    Public Property UserId As Integer
    Public Property UserName As String
    Public Property Password As String
    Public Property Token As String

    Public Shared Function GetUserByUserId(ByVal UserId As Integer) As Users
        Return Users.getCollection.Where(Function(o) o.UserId = UserId).FirstOrDefault
    End Function

    Public Shared Function getCollection() As List(Of Users)
        Dim li As New List(Of Users)

        'Emulate data storage. The token here is generated with System.Guid.NewGuid.ToString()
        li.Add(New Users With {.UserId = 1, .UserName = "Dimitar", .Password = "asd123", .Token = "ff4d3376-9b92-4215-b544-f423b6484e11"})
        li.Add(New Users With {.UserId = 2, .UserName = "John", .Password = "zxc123", .Token = "da7faf53-ba5d-4b3e-8091-e153610031f5"})
        Return li
    End Function
End Class

You will notice that I make use of the EncryptionHelper class to encrypt the token. It is a good practise to do this.

Secured version:

So now let’s switch the FORCE_SECURE key to True and rerun the example.

Figure 8: Login

Figure 9: Home page. The user is authenticated.

Up to this point nothing has changed. The hacker can still steal the AUTHENTICATIONCOOKIE and start the attack.

Figure 10: My Account page accessed over SSL.

Please note that this time when we accessed the My Account page a new cookie has been transferred. As this page is accessed via SSL, the hacker does not have access to this cookie. He does not even know that this cookie exist.

Figure 11: Trying to access the My Account page in different browser.

Figure 12: Inject the stolen cookie using JavaScript.

Now let’s once again pretend we are the hacker and try to use the stolen cookie in Firefox.

Figure 13: The home page is now accessible.

The home page is accessible and the hacker may think “Job done” or is it..

Figure 14: The My Account page is NOT accessible. The user is redirected to the Login page.

Now let’s try to access our precious My Account page. The hacker presented the AUTHENTICATIONCOOKIE and this was enough for the unsecured home page, but because the SecureCookie is missing, the hacker has been refused access to the My Account page and redirected back to the login page.


MyAccount.aspx

    Dim user As Users = Users.GetUserByUserId(Page.User.Identity.Name)

            'Should we enforce the security
            If CBool(ConfigurationManager.AppSettings("FORCE_SECURE")) Then

                Dim sToken As String = Helpers.CookieHelper.FetchTokenBySecureCookie

                'Check if the user has been logged in securely
                If String.IsNullOrWhiteSpace(sToken) OrElse Not String.CompareOrdinal(user.Token, Helpers.EncryptionHelper.Decrypt(sToken)) = 0 Then
                    Response.Redirect(String.Format("https://{0}LogOff.aspx", ConfigurationManager.AppSettings("SITE_URL")))
                End If
            End If

CookieHelper.vb

        Public Shared Function FetchTokenBySecureCookie() As String
            Dim sToken As String = String.Empty
            Dim cookie As HttpCookie = HttpContext.Current.Request.Cookies(SecureCookie)

            If cookie IsNot Nothing Then
                sToken = cookie.Value
            End If
           
            Return sToken
        End Function

At this point the next logical step for the hacker would be to create an account for himself and investigate the transmitted data. He will quickly realize that the problem with his previous attempt was the omission of the “SecurityCookie”. So, he may attempt to use his own secure cookie and the stolen AUTHENTICATIONCOOKIE to access our My Account page. We however prevent this with the code outlined below.

If String.IsNullOrWhiteSpace(sToken) OrElse Not String.CompareOrdinal(user.Token, Helpers.EncryptionHelper.Decrypt(sToken)) = 0

Basically, what I am doing here is decrypting the token stored in the “SecurityCookie” and compare it with the token stored in the database for the currently authenticated user using the build in ASP.NET forms authentication (which make use of the AUTHENTICATIONCOOKIE) using the Page.User.Identity.Name property.

I hope you enjoy reading my article as much as I enjoyed writing it.

Please feel free to leave any positive :) comment or ask question.

Download

Dimitar

Find out more about Dimitar here.

5 comments

Mayank said:

Nice article...

suresh said:

Awesome article. I have been searching in the internet to stop man-in-the-middle and unable to find it.Bingo i found it here in your blog.nice article.But i'm unable to understand some parts of this article.I will be so grateful to you if you show me it in a video, so that i can understand the concept more clearly. Please sir.Mail me the video

Matthew Sharp said:

The title is misleading and incorrect. A man in the middle is different to a session hijack. A man in the middle is where the attacker impersonates the server to the client, and impersonates the client to the server. A session hijack is just where the attacker acquires the client cookie and replays it to the server, so it is only half of a man in the middle attack. The difference is that the attacker never actively communicates with the client in a session hijack.

Pingpong said:

Great article. You said: "the malicious user stole the AUTHENTICATIONCOOKIE". Is it possible to steal the AUTHENTICATIONCOOKIE when https is used? In general, is it possible to steal cookies when https is used?

minnie said:

hi dimitar, Thanks for the great article. After reading your article, I got a question. What if my web site doesn't have a login page and global page, and it's not using the session feature, how to i prevent the hijacking by hackers. It would be great if you provide a right solution for me. Thanks in advance. Regards, MM

add your comment

Email me when other users reply