Introduction
In a web application development, there are various security issues that need to be addressed. One of the ASLC (Application Security Life Cycle) / RRR (Risk Residual Report) point states:
“Restrict a user to a single browser window”
HTTP is called a stateless protocol because each request is executed independently, without any knowledge of the requests that came before it. Since HTTP is stateless in nature, it has some shortcomings when it comes to the security and performance of a website. Session swapping, request-response overhead, data concurrency issues are the names of a few problems occurring due to the use of multiple windows or tabs in a web browser..
Challenges
There are two challenges in preventing multiple windows or tab usage in web applications:
- How can we differentiate two requests (GET or POST) at server side, whether the request originated from the same window or from tabbed/different windows?
Below is a sample conversation between an HTTP client and an HTTP server running on http://www.example.com port 80.
GET /index.html HTTP/1.1
Host: www.example.com
- How can we stop the user from generating a request (GET or POST) from two tabbed/different windows at client side?
Below are the sample instructions using which a user can request a tabbed/new window:
Ctrl+N / Ctrl+T
File->New Window / File->New Tab
Note: All windows open from the above action share the same session/cookies when communicated with web server.
Solution to Detect and Prevent Multiple Windows or Tabs Usage in Web Applications
There are two approaches we can use in web applications:
- Use of
window.name
at client side using JavaScript.
- Checking the HTTP Referer header at server side.
1. Use of window.name at client side using JavaScript
Here are the details of objects/events/properties/methods used in this approach:
Objects
window |
The window object is the top level object in JavaScript, and contains in itself several other objects. |
Events
onload |
Fires when the page has finished loading, including images. This is a popular event to use to run some JavaScript once everything on the page has loaded/ is available. |
Properties
name |
The name of the window as optionally specified when calling window.open() . |
opener |
Contains a reference to the window that opened the secondary window via window.open() . |
top |
A synonym for the topmost browser window. |
Methods
open(URL, [name], [features], [replace]) |
Opens a new browser window. The "name " argument specifies a name that you can use in the target attribute of your <a> tag. "features " allows you to show/hide various aspects of the window interface. "replace " is a boolean argument that denotes whether the URL loaded into the new window should add to the window's History list.
window.open("http://www.example.com",
"mywindow", "width=800px,
height=600px, resizable=1")
|
close() |
Closes a window. |
Window features in window.open()
The table below lists the string features you can pass into the "feature
" parameter of window.open()
to manipulate its interface. Most features support a value of true
or false
, though in general, simply including the name of the feature implies it should be added to the window (yes), while not including it means it shouldn't (no). Separate each feature with a comma (,).
Feature |
Description |
channelmode |
Specifies if window should be opened in channel mode. IE only. |
fullscreen |
Specifies if window should be opened in full screen mode. IE only. |
height |
Specifies the height of the window. |
left |
Specifies the x coordinates of the window in pixels. IE only. See "screenX " as well. |
location |
Specifies if the location bar of the window should be included. |
menubar |
Specifies if the menu bar of the window should be included. |
resizable |
Specifies if window should be resizable. |
screenX |
Specifies the x coordinates of the window in pixels. NS only. See "left " as well. |
screenY |
Specifies the y coordinates of the window in pixels. NS only. See "top " as well. |
scrollbars |
Specifies if window should contain scrollbars |
status |
Specifies if the status bar of the window should be included |
toolbar |
Specifies if the toolbar of the window (i.e., reload button) should be included. |
top |
Specifies the y coordinates of the window in pixels. IE only. See "screenY " as well. |
width |
Specifies the width of the window. |
How does the approach “Use of window.name at client side using JavaScript” work?
In Brief
A Default.aspx page opens the Home.aspx by setting a unique window.name
using JavaScript. Whenever a page is opened in other tab/window, the script checks the window.name
property and redirects to the InvalidAccess.aspx page if it finds an invalid name.
In detail, step by step:
First, the Default.aspx page is requested.
*To enhance performance, we start from the Default.aspx page, as there is no extra processing at the server and client side.
On page load, the following script will execute:
<script language="javascript" type="text/javascript">
if (window.name == "default") {
var windowFeatures ='channelmode=0, directories=0, location=1, menubar=0,
resizable=1, scrollbars=1,status=1,titlebar=0,toolbar=0,top=0,left=0,
width=1010,height=550';
window.open("Home.aspx", "<%=GetWindowName()%>");
window.opener = top;
window.close();
}
else if (window.name == "") {
window.name = "default";
window.open("Default.aspx", "_self");
}
else if (window.name == "invalidAccess") {
window.close();
}
else {
window.name = "invalidAccess";
window.open("Default.aspx", "_self");
}
</script>
And in Default.aspx.cs, we have a function GetWindowName()
which returns a unique name.
public string GetWindowName()
{
Session["WindowName"] =
Guid.NewGuid().ToString().Replace("-", "");
return Session["WindowName"].ToString();
}
When the page loads the first time, the window.name
of Default.aspx is blank (“”). The script sets window.name
to “default” and then opens itself in the same window. Now, a unique window name (using a server side function GetWindowName()
) is set, and the Home.aspx page is opened.
*It is optional to disabling the location, menubar, scrollbars, titlebar etc. when opening the Home.aspx.
The script closes Default.aspx after opening the Home.aspx page.
Note: Whenever a new window opens, window.name
is blank (“”). If the window.name
is blank, then Internet Explorer 7 & above shows a confirmation message:

But using the above script, it will not ask for confirmation while closing the window.
On all other pages (excluding Default.aspx), we use the following script in the Head
section.
<script language="javascript" type="text/javascript">
if(window.name != "<%=GetWindowName()%>")
{
window.name = "invalidAccess";
window.open("InvalidAccess.aspx", "_self");
}
</script>
(The above script can be put in the Common.js file.)
And, the following code will be put in the respective code-behind file (e.g., Home.aspx.cs):
public string GetWindowName()
{
return Session["WindowName"].ToString();
}
(The above code can be put in a common utility class which inherits from the System.Web.UI.Page
class.)
2. Checking the HTTP Referer header at server side
Details of the terms used in this approach are given below.
Referer
This optional header field allows the client to specify, for the server's benefit, the address (URL) of the document (or element within the document) from which the URI in the request was obtained.
This allows a server to generate lists of back-links to documents, for interest, logging, etc. It allows bad links to be traced for maintenance.
Example:
Referer: http://www.w3.org/hypertext/DataSources/Overview.html
If a request doesn’t have referer, then it indicates that the request is not generated using options.
Ctrl + N/Ctrl + T + K & File->New Window / File->New Tab
(Please note: when opening a page in a new window or tab using a mouse right/center click, the UrlReferer
property value will be available. But the window.name
will be blank. And, this condition will be handled at client side using script, which we have already set.)
protected void Page_Load(object sender, EventArgs e)
{
if (Request.UrlReferrer == null)
{
Response.Redirect("~/InvalidAccess.aspx");
}
}
Conclusion
The implementation of the above two points restricts a user to a single browser window.
Note:
- The article is based and tested for ASP.NET 2.0 and Internet Explorer 7.0, but the same concept can be applied to other technologies and browsers also.
- It is not 100% possible to detect and prevent multiple windows or tab usage in web applications.
History
- 24th April 2009 - Created.