Friday, December 26, 2008

ASP.NET 2.0 does not clear Session on Logout

Web application logout process does not clear Session properly


Situations :
Session to maintain the login and logout process. Everything is running perfect and smooth. The thing i want to know and clear is that, i want to clear system cache or web cache on log out. Actually some of the Session enabled pages opens once after logging out on the systems that are on LAN and using as Linux SQUID server on the backend. The copy of the page is stored in the cache, and opens the page without asking to log in if opened directly from the address bar. Once refreshed, the page then moves to Login page. Is there anyway to solve this?

After I logout and kill session in my web application, In internet explorer 6.0 user copy url and paste url and show web site like he login. I think because of internet explorer buffer in firebox 3.0 it don’t be how can we solve it on internet explore 6 ? How can we cancel internet explorer buffer cache?


Problem:
Midway through the project, I noticed that this Session information was not clearing itself when a user logged out of the system. I confirmed by logging in as "User 1", setting the Session value via a search, logging out, and subsequently logggin in as "User 2." User 2 was able to view the search criteria
entered by User 1 -- definitely NOT a desired behaviour.


Cause:
Does not clear Session when a Logout occurs. The control does perform a FormsAuthentication.Signout(), and it clears the Response with a status code of
200. But, it does not clear Session.


Solution:
The fix was simple. Use below code to fix the issue
font color="#003366">
protected void logout()
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Session.Clear();
FormsAuthentication.SignOut();
DisableBufferingOnPage()
}

protected void DisableBufferingOnPage()
{
Response.Buffer = true;
Response.ExpiresAbsolute = DateTime.Now.AddDays(-1); // set expiry date in the
past
Response.Expires = 0;
Response.CacheControl = "no-cache";
Response.Cache.SetNoStore();
Response.AppendHeader("Pragma", "no-cache");
}


Tuesday, December 23, 2008

ASP.NET Session State and Modes

ASP.NET Session State and Modes

The following terms are specific to this document:

Application Domain: A virtual process space within which ASP.NET is hosted and executed. On a Web server, it is possible to have multiple ASP.NET Web applications running inside a single process. Each ASP.NET application runs within its own application domain and is isolated from other ASP.NET applications that are running in separate application domains. An application domain has a unique identifier used as part of the identifying key on a state server when storing and retrieving session data.

ASP.NET: A Web server technology for dynamically rendering HTML pages using a combination of HTML, Javascript, CSS, and server-side logic.

ASP.NET State Server: Alternately, StateServer mode uses a stand-alone Microsoft Windows service to store session variables. Because this service is independent of Microsoft Internet Information Server (IIS), it can run on a separate server. You can use this mode for a load-balancing solution because multiple Web servers can share session variables. Although session variables are not lost if you restart IIS, performance is impacted when you cross process boundaries. .

InProc: In-Proc mode stores values in the memory of the ASP.NET worker process. Thus, this mode offers the fastest access to these values. However, when the ASP.NET worker process recycles, the state data is lost.

Session State: A feature for temporarily storing data associated with a browser session. Session state can be stored outside the process space of a session state client. The ASP.NET State Server is the default implementation for storing session state out of process.

URL: A uniform resource locator that identifies network-addressable endpoints. In the context of the ASP.NET State Server Protocol, a URL is used to identify a running instance of a state server implementation. The format of a state server URL is as specified in [RFC1738].

User Session Identifier: A unique identifier used as part of the identifying key when storing and retrieving session data.

Web Application Identifier: Each ASP.NET application running on a Web server is uniquely identified with a Web application identifier. The Web application identifier is the virtual path of the Web application on the Web server. A Web application identifier is used as part of the identifying key on a state server when storing and retrieving session data for a specific browser session.

ASP.NET session state enables you to store and retrieve values for a user as the user navigates ASP.NET pages in a Web application. HTTP is a stateless protocol. This means that a Web server treats each HTTP request for a page as an independent request. The server retains no knowledge of variable values that were used during previous requests. ASP.NET session state identifies requests from the same browser during a limited time window as a session, and provides a way to persist variable values for the duration of that session. By default, ASP.NET session state is enabled for all ASP.NET applications.

Alternatives to session state include the following:

  • Application state, which stores variables that can be accessed by all users of an ASP.NET application.
  • Profile properties, which persists user values in a data store without expiring them.
  • ASP.NET caching, which stores values in memory that is available to all ASP.NET applications.
  • View state, which persist values in a page.
  • Cookies.

The query string and fields on an HTML form that are available from an HTTP request.

Session Variables

Session variables are stored in a SessionStateItemCollection object that is exposed through the HttpContext..::.Session property. In an ASP.NET page, the current session variables are exposed through the Session property of the Page object.

The collection of session variables is indexed by the name of the variable or by an integer index. Session variables are created by referring to the session variable by name. You do not have to declare a session variable or explicitly add it to the collection. The following example shows how to create session variables in an ASP.NET page for the first and last name of a user, and set them to values retrieved from TextBox controls.

Visual Basic

Session("FirstName") = FirstNameTextBox.Text

Session("LastName") = LastNameTextBox.Text

C#

Session["FirstName"] = FirstNameTextBox.Text;

Session["LastName"] = LastNameTextBox.Text;

Session variables can be any valid .NET Framework type. The following example stores an ArrayList object in a session variable named StockPicks. The value returned by the StockPicks session variable must be cast to the appropriate type when you retrieve it from the SessionStateItemCollection.

Visual Basic

' When retrieving an object from session state, cast it to

' the appropriate type.

Dim stockPicks As ArrayList = CType(Session("StockPicks"), ArrayList)

' Write the modified stock picks list back to session state.

Session("StockPicks") = stockPicks

C#

// When retrieving an object from session state, cast it to

// the appropriate type.

ArrayList stockPicks = (ArrayList)Session["StockPicks"];

// Write the modified stock picks list back to session state.

Session["StockPicks"] = stockPicks;

Note: When you use a session-state mode other than InProc, the session-variable type must be either a primitive .NET type or serializable. This is because the session-variable value is stored in an external data store. For more information, see Session-State Modes.

Session Identifiers

Sessions are identified by a unique identifier that can be read by using the SessionID property. When session state is enabled for an ASP.NET application, each request for a page in the application is examined for a SessionID value sent from the browser. If no SessionID value is supplied, ASP.NET starts a new session and the SessionID value for that session is sent to the browser with the response.

By default, SessionID values are stored in a cookie. However, you can also configure the application to store SessionID values in the URL for a "cookieless" session.

A session is considered active as long as requests continue to be made with the same SessionID value. If the time between requests for a particular session exceeds the specified time-out value in minutes, the session is considered expired. Requests made with an expired SessionID value result in a new session.

Cookieless SessionIDs

By default, the SessionID value is stored in a non-expiring session cookie in the browser.

However, you can specify that session identifiers should not be stored in a cookie by
setting the cookieless attribute to true in the sessionState section of the Web.config file.
The following example shows a Web.config file that configures an ASP.NET application to cookieless session identifiers. 

<configuration>

<system.web>

<sessionState cookieless="true"

regenerateExpiredSessionId="true" />

</system.web>

</configuration>

ASP.NET maintains cookieless session state by automatically inserting a unique session ID into the page's URL. For example, the following URL has been modified by ASP.NET to include the unique session ID lit3py55t21z5v55vlm25s55:

http://www.example.com/(S(lit3py55t21z5v55vlm25s55))/orderform.aspx

When ASP.NET sends a page to the browser, it modifies any links in the page that use an application-relative path by embedding a session ID value in the links. (Links with absolute paths are not modified.) Session state is maintained as long as the user clicks links that have been modified in this manner. However, if the client rewrites a URL that is supplied by the application, ASP.NET may not be able to resolve the session ID and associate the request with an existing session. In that case, a new session is started for the request.

The session ID is embedded in the URL after the slash that follows the application name and before any remaining file or virtual directory identifier. This enables ASP.NET to resolve the application name before involving the SessionStateModule in the request.

Session Modes

ASP.NET session state supports several storage options for session variables. Each option is identified as a session-state Mode type. The default behavior is to store session variables in the memory space of the ASP.NET worker process. However, you can also specify that session state should be stored in a separate process, in a SQL Server database, or in a custom data source. If you do not want session state enabled for your application, you can set the session mode to Off.

For more information, see Session-State Modes.

Session Events

ASP.NET provides two events that help you manage user sessions. The Session_OnStart event is raised when a new session starts, and the Session_OnEnd event is raised when a session is abandoned or expires. Session events are specified in the Global.asax file for an ASP.NET application.

The Session_OnEnd event is not supported if the session Mode property is set to a value other than InProc, which is the default mode.

Session-State Modes

ASP.NET session state supports several different storage options for session data. Each option is identified by a value in the SessionStateMode enumeration. The following list describes the available session state modes:

  • InProc mode, which stores session state in memory on the Web server. This is the default.
  • StateServer mode, which stores session state in a separate process called the ASP.NET state service. This ensures that session state is preserved if the Web application is restarted and also makes session state available to multiple Web servers in a Web farm.
  • SQLServer mode stores session state in a SQL Server database. This ensures that session state is preserved if the Web application is restarted and also makes session state available to multiple Web servers in a Web farm.
  • Custom mode, which enables you to specify a custom storage provider.
  • Off mode, which disables session state.

You can specify which mode you want ASP.NET session state to use by assigning a SessionStateMode enumeration values to the mode attribute of the sessionState element in your application's Web.config file. Modes other than InProc and Off require additional parameters, such as connection-string values as discussed later in this topic. You can view the currently selected session state by accessing the value of the HttpSessionState..::.Mode property.

Inproc Mode

In-process mode is the default session state mode and is specified using the InProc SessionStateMode enumeration value. In-process mode stores session state values and variables in memory on the local Web server. It is the only mode that supports the Session_OnEnd event. For more information about the Session_OnEnd event, see Session-State Events.

Caution: If you enable Web-garden mode by setting the webGarden attribute to true in the processModel element of the application's Web.config file, do not use InProc session state mode. If you do, data loss can occur if different requests for the same session are served by different worker processes.

State Server Mode

StateServer mode stores session state in a process, referred to as the ASP.NET state service, that is separate from the ASP.NET worker process or IIS application pool. Using this mode ensures that session state is preserved if the Web application is restarted and also makes session state available to multiple Web servers in a Web farm.

To use StateServer mode, you must first be sure the ASP.NET state service is running on the server used for the session store. The ASP.NET state service is installed as a service when ASP.NET and the .NET Framework are installed. The ASP.Net state service is installed at the following location:

systemroot\Microsoft.NET\Framework\versionNumber\aspnet_state.exe

To configure an ASP.NET application to use StateServer mode, in the application's Web.config file do the following:

  • Set the mode attribute of the sessionState element to StateServer.
  • Set the stateConnectionString attribute to tcpip=serverName:42424.

Note: To improve the security of your application when using StateServer mode, it is recommended that you protect your stateConnectionString value by encrypting the sessionState section of your configuration file. For details, see Encrypting Configuration Information Using Protected Configuration.

The following example shows a configuration setting for StateServer mode where session state is stored on a remote computer named SampleStateServer:

<configuration>

<system.web>

<sessionState mode="StateServer"

stateConnectionString="tcpip=SampleStateServer:42424"

cookieless="false"

timeout="20"/>

</system.web>

</configuration>

Note: Objects stored in session state must be serializable if the mode is set to StateServer. For information on serializable objects, see the SerializableAttribute class.

To use StateServer mode in a Web farm, you must have the same encryption keys specified in the machineKey element of your Web configuration for all applications that are part of the Web farm. For information on how to create machine keys, see article 313091, "How to create keys by using Visual Basic .NET for use in Forms authentication," in the Microsoft Knowledge Base at http://support.microsoft.com.

SQL Server mode

SQLServer mode stores session state in a SQL Server database. Using this mode ensures that session state is preserved if the Web application is restarted and also makes session state available to multiple Web servers in a Web farm.

Note: Objects stored in session state must be serializable if the mode is SQL Server. For information on serializable objects, see the SerializableAttribute class.

To use SQLServer mode, you must first be sure the ASP.NET session state database is installed on SQL Server. You can install the ASP.NET session state database using the Aspnet_regsql.exe tool, as described later in this topic.

To configure an ASP.NET application to use SQLServer mode, do the following in the application's Web.config file:

  • Set the mode attribute of the sessionState element to SQLServer.
  • Set the sqlConnectionString attribute to a connection string for your SQL Server database.

Note: to improve the security of your application when using SQLServer mode, it is recommended that you protect your sqlConnectionString value by encrypting the sessionState section of your configuration file. For details, see Encrypting Configuration Information Using Protected Configuration.

The following example shows a configuration setting for SQLServer mode where session state is stored on a SQL Server named "SampleSqlServer":

<configuration>

<system.web>

<sessionState mode=" SQLServer "

sqlConnectionString="Integrated Security=SSPI;data

source=SampleSqlServer;" />

</system.web>

</configuration>

Configuring Session State

Session state is configured by using the sessionState element of the system.web configuration section. You can also configure session state by using the EnableSessionState value in the @ Page directive.

The sessionState element enables you to specify the following options:

  • The mode in which the session will store data.
  • The way in which session identifier values are sent between the client and the server.
  • The session Timeout value.
  • Supporting values that are based on the session Mode setting.

The following example shows a sessionState element that configures an application for SQLServer session mode. It sets the Timeout value to 30 minutes, and specifies that session identifiers are stored in the URL.

<sessionState mode="SQLServer"

cookieless="true "

regenerateExpiredSessionId="true "

timeout="30"

sqlConnectionString="Data Source=MySqlServer;Integrated Security=SSPI;"

stateNetworkTimeout="30"/>

You can disable session state for an application by setting the session-state mode to Off. If you want to disable session state for only a particular page of an application, you can set the EnableSessionState value in the @ Page directive to false. The EnableSessionState value can also be set to ReadOnly to provide read-only access to session variables. Examples:

Save Values in Session State

Visual Basic

Dim firstName As String = "John"

Dim lastName As String = "Smith"

Dim city As String = "Seattle"

Session("FirstName") = firstName

Session("LastName") = lastName

Session("City") = city


C#

string firstName = "Jeff";

string lastName = "Smith";

string city = "Seattle";

Session["FirstName"] = firstName;

Session["LastName"] = lastName;

Session["City"] = city;

Read Values from Session State

Visual Basic

Dim firstName as String = CType(Session.Item("FirstName"), String)

Dim lastName as String = CType(Session.Item("LastName"), String)

Dim city as String = CType(Session.Item("City"), String)


C#

string firstName = (string)(Session["First"]);

string lastName = (string)(Session["Last"]);

string city = (string)(Session["City"]);

Cross-Site Scripting in ASP.NET








Overview

Cross-site scripting attacks exploit vulnerabilities in Web page validation by injecting client-side script code. The script code embeds itself in response data, which is sent back to an unsuspecting user. The user's browser then runs the script code. Because the browser downloads the script code from a trusted site, the browser has no way of recognizing that the code is not legitimate, and Microsoft Internet Explorer security zones provide no defense. Cross-site scripting attacks also work over HTTP and HTTPS (SSL) connections.

One of the most serious examples of a cross-site scripting attack occurs when an attacker writes script to retrieve the authentication cookie that provides access to a trusted site and then posts the cookie to a Web address known to the attacker. This enables the attacker to spoof the legitimate user's identity and gain illicit access to the Web site.

Common vulnerabilities that make your Web application susceptible to cross-site scripting attacks include:

  • Failing to constrain and validate input.
  • Failing to encode output.
  • Trusting data retrieved from a shared database.

Guidelines

The two most important countermeasures to prevent cross-site scripting attacks are to:

  • Constrain input.
  • Encode output.

Constrain Input

Start by assuming that all input is malicious. Validate input type, length, format, and range.

  • To constrain input supplied through server controls, use ASP.NET validator controls such as RegularExpressionValidator and RangeValidator.
  • To constrain input supplied through client-side HTML input controls or input from other sources such as query strings or cookies, use the System.Text.RegularExpressions.Regex class in your server-side code to check for expected using regular expressions.
  • To validate types such as integers, doubles, dates, and currency amounts, convert the input data to the equivalent .NET Framework data type and handle any resulting conversion errors.

For more information about and examples of how to constrain input, see .

Encode Output

Use the HttpUtility.HtmlEncode method to encode output if it contains input from the user or from other sources such as databases. HtmlEncode replaces characters that have special meaning in HTML-to-HTML variables that represent those characters. For example, < is replaced with &lt; and " is replaced with &quot;. Encoded data does not cause the browser to execute code. Instead, the data is rendered as harmless HTML.

Similarly, use HttpUtility.UrlEncode to encode output URLs if they are constructed from input.

Summary of Steps

To prevent cross-site scripting, perform the following steps:

<system.web>


<pages buffer="true" validateRequest="true" />
</system.web>

You can disable request validation on a page-by-page basis. Check that your pages do not disable this feature unless necessary. For example, you may need to disable this feature for a page if it contains a free-format, rich-text entry field designed to accept a range of HTML characters as input. For more information about how to safely handle this type of page.

To test that ASP.NET request validation is enabled

  1. Create an ASP.NET page that disables request validation. To do this, set ValidateRequest="false", as shown in the following code example.

    <%@ Page Language="C#" ValidateRequest="false" %>
    
    <html>
    <script runat="server">
    void btnSubmit_Click(Object sender, EventArgs e)
    {
    // If ValidateRequest is false, then 'hello' is displayed
    // If ValidateRequest is true, then ASP.NET returns an exception
    Response.Write(txtString.Text);
    }
    </script>
    <body>
    <form id="form1" runat="server">

    <asp:TextBox id="txtString" runat="server"
    Text="<script>alert('hello');</script>" />
    <asp:Button id="btnSubmit" runat="server"
    OnClick="btnSubmit_Click"
    Text="Submit" />
    </form>
    </body>
    </html>

  2. Run the page. It displays Hello in a message box because the script in txtString is passed through and rendered as client-side script in your browser.
  3. Set ValidateRequest="true" or remove the ValidateRequest page attribute and browse to the page again. Verify that the following error message is displayed.

    A potentially dangerous Request.Form value was detected from the client (txtString="<script>alert('hello...").
    

    This indicates that ASP.NET request validation is active and has rejected the input because it includes potentially dangerous HTML characters.

    Response.Write
    

    <% =

    Search your pages to locate where HTML and URL output is returned to the client.

    Step 3. Determine Whether HTML Output Includes Input Parameters

    Analyze your design and your page code to determine whether the output includes any input parameters. These parameters can come from a variety of sources. The following list includes common input sources:

    • Form fields, such as the following.
      Response.Write(name.Text);
      
      Response.Write(Request.Form["name"]);
      Query Strings
      Response.Write(Request.QueryString["name"]);
    • Query strings, such as the following:

      Response.Write(Request.QueryString["username"]);
      
    • Databases and data access methods, such as the following:
      SqlDataReader reader = cmd.ExecuteReader();
      
      Response.Write(reader.GetString(1));

      Be particularly careful with data read from a database if it is shared by other applications.

    • Cookie collection, such as the following:
      Response.Write(
      
      Request.Cookies["name"].Values["name"]);
    • Session and application variables, such as the following:

      Response.Write(Session["name"]);
      
      Response.Write(Application["name"]);
      <%@ Page Language="C#" AutoEventWireup="true"%>
      

      <html>
      <form id="form1" runat="server">
      <div>
      Color:&nbsp;<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><br />
      <asp:Button ID="Button1" runat="server" Text="Show color"
      OnClick="Button1_Click" /><br />

      <asp:Literal ID="Literal1" runat="server"></asp:Literal>
      </div>
      </form>
      </html>

      <script runat="server">
      private void Page_Load(Object Src, EventArgs e)
      {
      protected void Button1_Click(object sender, EventArgs e)
      {
      Literal1.Text = @"<span style=""color:"
      + Server.HtmlEncode(TextBox1.Text)
      + @""">Color example</span>";
      }
      }
      </Script>

      Potentially Dangerous HTML Tags

      While not an exhaustive list, the following commonly used HTML tags could allow a malicious user to inject script code:

      <img src="javascript:alert('hello');">
      

      <img src="java&#010;script:alert('hello');">
      <img src="java&#X0A;script:alert('hello');">
      <style TYPE="text/javascript">
      

      alert('hello');
      </style>

      When you find ASP.NET code that generates HTML using some input, you need to evaluate appropriate countermeasures for your specific application. Countermeasures include:

      Response.Write(HttpUtility.HtmlEncode(Request.Form["name"]));
      
      Response.Write(HttpUtility.UrlEncode(urlString));
      
      <%@ Page Language="C#" ValidateRequest="false"%>
      

      <script runat="server">

      void submitBtn_Click(object sender, EventArgs e)
      {
      // Encode the string input
      StringBuilder sb = new StringBuilder(
      HttpUtility.HtmlEncode(htmlInputTxt.Text));
      // Selectively allow <b> and <i>
      sb.Replace("&lt;b&gt;", "<b>");

      sb.Replace("&lt;/b&gt;", "");
      sb.Replace("&lt;i&gt;", "<i>");
      sb.Replace("&lt;/i&gt;", "");
      Response.Write(sb.ToString());
      }
      </script>

      <html>
      <body>

      <form id="form1" runat="server">
      <div>
      <asp:TextBox ID="htmlInputTxt" Runat="server"
      TextMode="MultiLine" Width="318px"
      Height="168px"></asp:TextBox>
      <asp:Button ID="submitBtn" Runat="server"
      Text="Submit" OnClick="submitBtn_Click" />
      </div>
      </form>

      </body>
      </html>


Monday, December 22, 2008

Making server side decision based on client side JavaScript

Many of you might have come across the situation where you need to making server side discussion based on client side JavaScript confirm message value. Though this may sound very basic feature, surprisingly large developers struggle when implementing this. In this article, I will show you how to.


<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="Server">

<table style="margin-top:100px;">

<tr style="padding-bottom:10px">

<td>

<asp:Label ID="lblitemName" Text="Item Value" runat="server">asp:Label>td>

<td>

<asp:TextBox ID="txtitemval" runat="server">asp:TextBox>td>

tr>

table>

<div style="padding-bottom:10px">

<asp:Label ID="lblMsg" runat="server">asp:Label>

div>

<div style=" margin-bottom:100px; margin-left:120px">

<asp:HiddenField ID="hdnField" runat="server" Value="false" />

<asp:Button ID="btnSubmit" runat="server" Text="Check Val" OnClick="btnSubmits_Click" />

div>

asp:Content>


And the code behind for this page is like

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.Data.SqlClient;

public partial class Test : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

}

protected void btnSubmits_Click(object sender, EventArgs e)

{

string itemValue = Convert.ToString(txtitemval.Text);

if (hdnField.Value == "false")

{

lblMsg.Visible = false;

AddJavascriptCode(itemValue);

}

else if (hdnField.Value == "true")

{

lblMsg.Visible = true;

lblMsg.Text = string.Format("You have entered {0}", itemValue);

hdnField.Value = "false";

}

}




private void AddJavascriptCode(string itemValue)

{

string script = @"<script language=""JavaScript"" type=""text/javascript"">

window.onload=function()

{

var IsConfirm = 1;

objField = document.getElementById('" + hdnField.ClientID + @"');

objSubmit = document.getElementById('" + btnSubmit.ClientID + @"');

IsConfirm = newConfirm('Test','You have entered " + itemValue + @" value. Are you sure you want to go next page?',1,1,0);

if(IsConfirm == true)

{

objField.value = 'true';

objSubmit.click();

}

else

{

objField.value = 'false';

}

}

function newConfirm(title,mess,icon,defbut,mods)

{

if (document.all)

{

retVal = confirm(mess);

retVal = (retVal==1)

}

else

{

retVal = confirm(mess);

}

return retVal;

}

</script>";

Page.ClientScript.RegisterStartupScript(this.GetType(), "Test", script);

}

}


See the Result below