Working with Multiple Cookies

Background

When we build our web-application, we all use cookies for some of the other reason. Reasons could be keeping session id, certain user information, or any other page related data, etc. Whatever purpose it may be, as the best practice developer should always mark their cookie as HttpOnly. The advantages of marking cookie as HttpOnly are listed here.

Problem

In order to follow the best practice, developer will mark the cookie as HttpOnly. But what if application is using more than one cookie? In this case most likely developer will mark any one of the cookie as HttpOnly. But what about the rest of cookies, as those are still readable by JavaScript code.

Working example in ASP.NET

Let’s start with creating an web application project in Visual Studio 2010.

Create a ASP.NET web application project in Visual Studio 2010. For more details use this link. This will create a Default.aspx page automatically for you. We need following controls to execute this exercise

  1. Label: For displaying entered data
  2. TextBox: For user input
  3. Button: For event to trigger

After placing these controls in required order the design would look like this

Step 1 - Page design

Step 1 - Page design

Or else you can replace the body tag with the following code in Default.aspx

<body>
    <form id="form1" runat="server">
    <div>
    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:Button ID="Button1"
        runat="server" Text="Button" onclick="Button1_Click" /><br /><asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    </div>
    </form>
</body>

After this double click on the Button(Button1) and you will be landed to Default.aspx.cs (Code Behind). Over here we just have to take the input from TextBox control(TextBox1) and paste that in the Label control(Label1). So the code would be as follows

protected void Button1_Click(object sender, EventArgs e)
{
    Label1.Text = TextBox1.Text;
}

In order to run the project press F5 and browser window will open with your page which would ideally look like this.

Step 2 - First run

Step 2 - First run

In order to verify that things are working fine, we will add the most apt XSS vector to see whether it is working or not

"><script>alert(1);</script>
Step 3 - Trying XSS

Step 3 - Trying XSS

It will show the following error

Step 4 - Script Error

Step 4 - Script Error

In order to eliminate this error we have to modify the page directive of our Default.aspx page and add the ValidateRequest attribute to the page tag with “false” as its value.

Step 5 - Change page directive

Step 5 - Change page directive

After this modification we are able to execute the XSS vector successfully.

Step 6 - XSS

Step 6 - XSS

Now, lets add certain cookie programmatically so that we can control their behavior. First we will mark all the cookie as HttpOnly. Following is the code to add cookies in the page.

protected void Page_Load(object sender, EventArgs e)
{
	if (!IsPostBack)
	{
		Response.Cookies["LastVisit"].Value = DateTime.Now.ToString();
		Response.Cookies["LastVisit"].Expires = DateTime.Now.AddDays(1);

		HttpCookie cookie = new HttpCookie("LastVisit");
		cookie.HttpOnly = true;
		cookie.Value = DateTime.Now.ToString();
		cookie.Expires = DateTime.Now.AddDays(1);
		Response.Cookies.Add(cookie);

		HttpCookie cok = new HttpCookie("NoHttpOnly");
		cok.Expires = DateTime.Now.AddDays(1);
		cok.HttpOnly = true;
		cok.Value = "Cookie not marked as HttpOnly";
		Response.Cookies.Add(cok);

		HttpCookie session = new HttpCookie("SessionID");
		session.Value = Session.SessionID;
		session.Expires = DateTime.Now.AddDays(1);
		session.HttpOnly = true;
		Response.Cookies.Add(session);
	}
}

In the code above we have three cookie variables viz., LastVisit, NoHttpOnly, SessionID. All cookies are marked as HttpOnly using the HttpCookie.HttpOnly property and setting its value to true. In order to read the cookie I have added following JavaScript code in the <head> tag

<script type="text/javascript">
function getCookie(c_name) {
	var i, x, y, ARRcookies = document.cookie.split(";");
	for (i = 0; i < ARRcookies.length; i++) {
		x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
		y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
		x = x.replace(/^s+|s+$/g, "");
		if (x == c_name) {
			alert(unescape(y));
		}
	}
}
</script>

Now let’s try to read any of the cookies using following injection in the TextBox control, but as all the cookies are marked as HttpOnly we will not be able to read them.

Step 7 - Not able to read cookie

Step 7 - Not able to read cookie

Now let’s change HttpCookie.HttpOnly property to value false for one of the cookie variable (SessionID) and then try to read the cookie with same injection.

Step 8 - Reading cookie

Step 8 - Reading cookie

And we are able to read the cookie value 🙂

Remediation

Mark all cookies as HttpOnly

Tagged with: ,