Security Frame: Session Management

Product/Service Article
Azure AD
IoT Device
Azure Document DB
ADFS
Identity Server
Web Application
Web API

Implement proper sign-out using MSAL methods when using Azure AD

Title Details
Component Azure AD
SDL Phase Build
Applicable Technologies Generic
Attributes N/A
References Enable your Web app to sign-in users using the Microsoft Identity Platform
Steps The ASP.NET Core OpenIdConnect middleware enables your app to intercept the call to the Microsoft identity platform logout endpoint by providing an OpenIdConnect event named OnRedirectToIdentityProviderForSignOut

Example

services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
    options.Events.OnRedirectToIdentityProviderForSignOut = async context =>
    {
        //Your logic here
    };
});

Use finite lifetimes for generated SaS tokens

Title Details
Component IoT Device
SDL Phase Build
Applicable Technologies Generic
Attributes N/A
References N/A
Steps SaS tokens generated for authenticating to Azure IoT Hub should have a finite expiry period. Keep the SaS token lifetimes to a minimum to limit the amount of time they can be replayed in case the tokens are compromised.

Use minimum token lifetimes for generated Resource tokens

Title Details
Component Azure Document DB
SDL Phase Build
Applicable Technologies Generic
Attributes N/A
References N/A
Steps Reduce the timespan of resource token to a minimum value required. Resource tokens have a default valid timespan of 1 hour.

Implement proper logout using WsFederation methods when using ADFS

Title Details
Component ADFS
SDL Phase Build
Applicable Technologies Generic
Attributes N/A
References N/A
Steps If the application relies on STS token issued by ADFS, the logout event handler should call WSFederationAuthenticationModule.FederatedSignOut() method to log out the user. Also the current session should be destroyed, and the session token value should be reset and nullified.

Example

        [HttpPost, ValidateAntiForgeryToken]
        [Authorization]
        public ActionResult SignOut(string redirectUrl)
        {
            if (!this.User.Identity.IsAuthenticated)
            {
                return this.View("LogOff", null);
            }

            // Removes the user profile.
            this.Session.Clear();
            this.Session.Abandon();
            HttpContext.Current.Response.Cookies.Add(new System.Web.HttpCookie("ASP.NET_SessionId", string.Empty)
                {
                    Expires = DateTime.Now.AddDays(-1D),
                    Secure = true,
                    HttpOnly = true
                });

            // Signs out at the specified security token service (STS) by using the WS-Federation protocol.
            Uri signOutUrl = new Uri(FederatedAuthentication.WSFederationAuthenticationModule.Issuer);
            Uri replyUrl = new Uri(FederatedAuthentication.WSFederationAuthenticationModule.Realm);
            if (!string.IsNullOrEmpty(redirectUrl))
            {
                replyUrl = new Uri(FederatedAuthentication.WSFederationAuthenticationModule.Realm + redirectUrl);
            }
           //     Signs out of the current session and raises the appropriate events.
            var authModule = FederatedAuthentication.WSFederationAuthenticationModule;
            authModule.SignOut(false);
        //     Signs out at the specified security token service (STS) by using the WS-Federation
        //     protocol.            
            WSFederationAuthenticationModule.FederatedSignOut(signOutUrl, replyUrl);
            return new RedirectResult(redirectUrl);
        }

Implement proper logout when using Identity Server

Title Details
Component Identity Server
SDL Phase Build
Applicable Technologies Generic
Attributes N/A
References IdentityServer3-Federated sign out
Steps IdentityServer supports the ability to federate with external identity providers. When a user signs out of an upstream identity provider, depending upon the protocol used, it might be possible to receive a notification when the user signs out. It allows IdentityServer to notify its clients so they can also sign the user out. Check the documentation in the references section for the implementation details.

Applications available over HTTPS must use secure cookies

Title Details
Component Web Application
SDL Phase Build
Applicable Technologies Generic
Attributes EnvironmentType - OnPrem
References httpCookies Element (ASP.NET Settings Schema), HttpCookie.Secure Property
Steps Cookies are normally only accessible to the domain for which they were scoped. Unfortunately, the definition of "domain" does not include the protocol so cookies that are created over HTTPS are accessible over HTTP. The "secure" attribute indicates to the browser that the cookie should only be made available over HTTPS. Ensure that all cookies set over HTTPS use the secure attribute. The requirement can be enforced in the web.config file by setting the requireSSL attribute to true. It is the preferred approach because it will enforce the secure attribute for all current and future cookies without the need to make any additional code changes.

Example

<configuration>
  <system.web>
    <httpCookies requireSSL="true"/>
  </system.web>
</configuration>

The setting is enforced even if HTTP is used to access the application. If HTTP is used to access the application, the setting breaks the application because the cookies are set with the secure attribute and the browser will not send them back to the application.

Title Details
Component Web Application
SDL Phase Build
Applicable Technologies Web Forms, MVC5
Attributes EnvironmentType - OnPrem
References N/A
Steps When the web application is the Relying Party, and the IdP is ADFS server, the FedAuth token's secure attribute can be configured by setting requireSSL to True in system.identityModel.services section of web.config:

Example

  <system.identityModel.services>
    <federationConfiguration>
      <!-- Set requireSsl=true; domain=application domain name used by FedAuth cookies (Ex: .gdinfra.com); -->
      <cookieHandler requireSsl="true" persistentSessionLifetime="0.0:20:0" />
    ....  
    </federationConfiguration>
  </system.identityModel.services>
Title Details
Component Web Application
SDL Phase Build
Applicable Technologies Generic
Attributes N/A
References Secure Cookie Attribute
Steps To mitigate the risk of information disclosure with a cross-site scripting (XSS) attack, a new attribute - httpOnly - was introduced to cookies and is supported by all major browsers. The attribute specifies that a cookie is not accessible through script. By using HttpOnly cookies, a web application reduces the possibility that sensitive information contained in the cookie can be stolen via script and sent to an attacker's website.

Example

All HTTP-based applications that use cookies should specify HttpOnly in the cookie definition, by implementing following configuration in web.config:

<system.web>
.
.
   <httpCookies requireSSL="false" httpOnlyCookies="true"/>
.
.
</system.web>
Title Details
Component Web Application
SDL Phase Build
Applicable Technologies Web Forms
Attributes N/A
References FormsAuthentication.RequireSSL Property
Steps The RequireSSL property value is set in the configuration file for an ASP.NET application by using the requireSSL attribute of the configuration element. You can specify in the Web.config file for your ASP.NET application whether Transport Layer Security (TLS), previously known as SSL (Secure Sockets Layer), is required to return the forms-authentication cookie to the server by setting the requireSSL attribute.

Example

The following code example sets the requireSSL attribute in the Web.config file.

<authentication mode="Forms">
  <forms loginUrl="member_login.aspx" cookieless="UseCookies" requireSSL="true"/>
</authentication>
Title Details
Component Web Application
SDL Phase Build
Applicable Technologies MVC5
Attributes EnvironmentType - OnPrem
References Windows Identity Foundation (WIF) Configuration – Part II
Steps To set httpOnly attribute for FedAuth cookies, hideFromCsript attribute value should be set to True.

Example

Following configuration shows the correct configuration:

<federatedAuthentication>
<cookieHandler mode="Custom"
                       hideFromScript="true"
                       name="FedAuth"
                       path="/"
                       requireSsl="true"
                       persistentSessionLifetime="25">
</cookieHandler>
</federatedAuthentication>

Mitigate against Cross-Site Request Forgery (CSRF) attacks on ASP.NET web pages

Title Details
Component Web Application
SDL Phase Build
Applicable Technologies Generic
Attributes N/A
References N/A
Steps Cross-site request forgery (CSRF or XSRF) is a type of attack in which an attacker can carry out actions in the security context of a different user's established session on a web site. The goal is to modify or delete content, if the targeted web site relies exclusively on session cookies to authenticate received request. An attacker could exploit this vulnerability by getting a different user's browser to load a URL with a command from a vulnerable site on which the user is already logged in. There are many ways for an attacker to do that, such as by hosting a different web site that loads a resource from the vulnerable server, or getting the user to click a link. The attack can be prevented if the server sends an additional token to the client, requires the client to include that token in all future requests, and verifies that all future requests include a token that pertains to the current session, such as by using the ASP.NET AntiForgeryToken or ViewState.
Title Details
Component Web Application
SDL Phase Build
Applicable Technologies MVC5, MVC6
Attributes N/A
References XSRF/CSRF Prevention in ASP.NET MVC and Web Pages
Steps Anti-CSRF and ASP.NET MVC forms - Use the AntiForgeryToken helper method on Views; put an Html.AntiForgeryToken() into the form, for example,

Example

@using (Html.BeginForm("UserProfile", "SubmitUpdate")) { 
    @Html.ValidationSummary(true) 
    @Html.AntiForgeryToken()
    <fieldset> 

Example

<form action="/UserProfile/SubmitUpdate" method="post">
    <input name="__RequestVerificationToken" type="hidden" value="saTFWpkKN0BYazFtN6c4YbZAmsEwG0srqlUqqloi/fVgeV2ciIFVmelvzwRZpArs" />
    <!-- rest of form goes here -->
</form>

Example

At the same time, Html.AntiForgeryToken() gives the visitor a cookie called __RequestVerificationToken, with the same value as the random hidden value shown above. Next, to validate an incoming form post, add the [ValidateAntiForgeryToken] filter to the target action method. For example:

[ValidateAntiForgeryToken]
public ViewResult SubmitUpdate()
{
// ... etc.
}

Authorization filter that checks that:

  • The incoming request has a cookie called __RequestVerificationToken
  • The incoming request has a Request.Form entry called __RequestVerificationToken
  • These cookie and Request.Form values match Assuming all is well, the request goes through as normal. But if not, then an authorization failure with message “A required anti-forgery token was not supplied or was invalid”.

Example

Anti-CSRF and AJAX: The form token can be a problem for AJAX requests, because an AJAX request might send JSON data, not HTML form data. One solution is to send the tokens in a custom HTTP header. The following code uses Razor syntax to generate the tokens, and then adds the tokens to an AJAX request.

<script>
    @functions{
        public string TokenHeaderValue()
        {
            string cookieToken, formToken;
            AntiForgery.GetTokens(null, out cookieToken, out formToken);
            return cookieToken + ":" + formToken;                
        }
    }

    $.ajax("api/values", {
        type: "post",
        contentType: "application/json",
        data: {  }, // JSON data goes here
        dataType: "json",
        headers: {
            'RequestVerificationToken': '@TokenHeaderValue()'
        }
    });
</script>

Example

When you process the request, extract the tokens from the request header. Then call the AntiForgery.Validate method to validate the tokens. The Validate method throws an exception if the tokens are not valid.

void ValidateRequestHeader(HttpRequestMessage request)
{
    string cookieToken = "";
    string formToken = "";

    IEnumerable<string> tokenHeaders;
    if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
    {
        string[] tokens = tokenHeaders.First().Split(':');
        if (tokens.Length == 2)
        {
            cookieToken = tokens[0].Trim();
            formToken = tokens[1].Trim();
        }
    }
    AntiForgery.Validate(cookieToken, formToken);
}
Title Details
Component Web Application
SDL Phase Build
Applicable Technologies Web Forms
Attributes N/A
References Take Advantage of ASP.NET Built-in Features to Fend Off Web Attacks
Steps CSRF attacks in WebForm based applications can be mitigated by setting ViewStateUserKey to a random string that varies for each user - user ID or, better yet, session ID. For a number of technical and social reasons, session ID is a much better fit because a session ID is unpredictable, times out, and varies on a per-user basis.

Example

Here's the code you need to have in all of your pages:

void Page_Init (object sender, EventArgs e) {
   ViewStateUserKey = Session.SessionID;
   :
}

Set up session for inactivity lifetime

Title Details
Component Web Application
SDL Phase Build
Applicable Technologies Generic
Attributes N/A
References HttpSessionState.Timeout Property
Steps Session timeout represents the event occurring when a user does not perform any action on a web site during an interval (defined by web server). The event, on server side, change the status of the user session to 'invalid' (for example "not used anymore") and instruct the web server to destroy it (deleting all data contained into it). The following code example sets the timeout session attribute to 15 minutes in the Web.config file.

Example

<configuration>
  <system.web>
    <sessionState mode="InProc" cookieless="true" timeout="15" />
  </system.web>
</configuration>

Enable Threat detection on Azure SQL

Title Details
Component Web Application
SDL Phase Build
Applicable Technologies Web Forms
Attributes N/A
References Forms element for authentication (ASP.NET Settings Schema)
Steps Set the Forms Authentication Ticket cookie timeout to 15 minutes

Example

<forms  name=".ASPXAUTH" loginUrl="login.aspx"  defaultUrl="default.aspx" protection="All" timeout="15" path="/" requireSSL="true" slidingExpiration="true"/>
</forms>
Title Details
Component Web Application
SDL Phase Build
Applicable Technologies Web Forms, MVC5
Attributes EnvironmentType - OnPrem
References asdeqa
Steps When the web application is Relying Party and ADFS is the STS, the lifetime of the authentication cookies - FedAuth tokens - can be set by the following configuration in web.config:

Example

  <system.identityModel.services>
    <federationConfiguration>
      <!-- Set requireSsl=true; domain=application domain name used by FedAuth cookies (Ex: .gdinfra.com); -->
      <cookieHandler requireSsl="true" persistentSessionLifetime="0.0:15:0" />
      <!-- Set requireHttps=true; -->
      <wsFederation passiveRedirectEnabled="true" issuer="http://localhost:39529/" realm="https://localhost:44302/" reply="https://localhost:44302/" requireHttps="true"/>
      <!--
      Use the code below to enable encryption-decryption of claims received from ADFS. Thumbprint value varies based on the certificate being used.
      <serviceCertificate>
        <certificateReference findValue="4FBBBA33A1D11A9022A5BF3492FF83320007686A" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
      </serviceCertificate>
      -->
    </federationConfiguration>
  </system.identityModel.services>

Example

Also the ADFS issued SAML claim token's lifetime should be set to 15 minutes, by executing the following powershell command on the ADFS server:

Set-ADFSRelyingPartyTrust -TargetName "<RelyingPartyWebApp>" -ClaimsProviderName @("Active Directory") -TokenLifetime 15 -AlwaysRequireAuthentication $true

Implement proper logout from the application

Title Details
Component Web Application
SDL Phase Build
Applicable Technologies Generic
Attributes N/A
References N/A
Steps Perform proper Sign Out from the application, when user presses log out button. Upon logout, application should destroy user's session, and also reset and nullify session cookie value, along with resetting and nullifying authentication cookie value. Also, when multiple sessions are tied to a single user identity, they must be collectively terminated on the server side at timeout or logout. Lastly, ensure that Logout functionality is available on every page.

Mitigate against Cross-Site Request Forgery (CSRF) attacks on ASP.NET Web APIs

Title Details
Component Web API
SDL Phase Build
Applicable Technologies Generic
Attributes N/A
References N/A
Steps Cross-site request forgery (CSRF or XSRF) is a type of attack in which an attacker can carry out actions in the security context of a different user's established session on a web site. The goal is to modify or delete content, if the targeted web site relies exclusively on session cookies to authenticate received request. An attacker could exploit this vulnerability by getting a different user's browser to load a URL with a command from a vulnerable site on which the user is already logged in. There are many ways for an attacker to do that, such as by hosting a different web site that loads a resource from the vulnerable server, or getting the user to click a link. The attack can be prevented if the server sends an additional token to the client, requires the client to include that token in all future requests, and verifies that all future requests include a token that pertains to the current session, such as by using the ASP.NET AntiForgeryToken or ViewState.
Title Details
Component Web API
SDL Phase Build
Applicable Technologies MVC5, MVC6
Attributes N/A
References Preventing Cross-Site Request Forgery (CSRF) Attacks in ASP.NET Web API
Steps Anti-CSRF and AJAX: The form token can be a problem for AJAX requests, because an AJAX request might send JSON data, not HTML form data. One solution is to send the tokens in a custom HTTP header. The following code uses Razor syntax to generate the tokens, and then adds the tokens to an AJAX request.

Example

<script>
    @functions{
        public string TokenHeaderValue()
        {
            string cookieToken, formToken;
            AntiForgery.GetTokens(null, out cookieToken, out formToken);
            return cookieToken + ":" + formToken;                
        }
    }
    $.ajax("api/values", {
        type: "post",
        contentType: "application/json",
        data: {  }, // JSON data goes here
        dataType: "json",
        headers: {
            'RequestVerificationToken': '@TokenHeaderValue()'
        }
    });
</script>

Example

When you process the request, extract the tokens from the request header. Then call the AntiForgery.Validate method to validate the tokens. The Validate method throws an exception if the tokens are not valid.

void ValidateRequestHeader(HttpRequestMessage request)
{
    string cookieToken = "";
    string formToken = "";

    IEnumerable<string> tokenHeaders;
    if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
    {
        string[] tokens = tokenHeaders.First().Split(':');
        if (tokens.Length == 2)
        {
            cookieToken = tokens[0].Trim();
            formToken = tokens[1].Trim();
        }
    }
    AntiForgery.Validate(cookieToken, formToken);
}

Example

Anti-CSRF and ASP.NET MVC forms - Use the AntiForgeryToken helper method on Views; put an Html.AntiForgeryToken() into the form, for example,

@using (Html.BeginForm("UserProfile", "SubmitUpdate")) { 
    @Html.ValidationSummary(true) 
    @Html.AntiForgeryToken()
    <fieldset> 
}

Example

The example above will output something like the following:

<form action="/UserProfile/SubmitUpdate" method="post">
    <input name="__RequestVerificationToken" type="hidden" value="saTFWpkKN0BYazFtN6c4YbZAmsEwG0srqlUqqloi/fVgeV2ciIFVmelvzwRZpArs" />
    <!-- rest of form goes here -->
</form>

Example

At the same time, Html.AntiForgeryToken() gives the visitor a cookie called __RequestVerificationToken, with the same value as the random hidden value shown above. Next, to validate an incoming form post, add the [ValidateAntiForgeryToken] filter to the target action method. For example:

[ValidateAntiForgeryToken]
public ViewResult SubmitUpdate()
{
// ... etc.
}

Authorization filter that checks that:

  • The incoming request has a cookie called __RequestVerificationToken
  • The incoming request has a Request.Form entry called __RequestVerificationToken
  • These cookie and Request.Form values match Assuming all is well, the request goes through as normal. But if not, then an authorization failure with message “A required anti-forgery token was not supplied or was invalid”.
Title Details
Component Web API
SDL Phase Build
Applicable Technologies MVC5, MVC6
Attributes Identity Provider - ADFS, Identity Provider - Azure AD
References Secure a Web API with Individual Accounts and Local Login in ASP.NET Web API 2.2
Steps If the Web API is secured using OAuth 2.0, then it expects a bearer token in Authorization request header and grants access to the request only if the token is valid. Unlike cookie based authentication, browsers do not attach the bearer tokens to requests. The requesting client needs to explicitly attach the bearer token in the request header. Therefore, for ASP.NET Web APIs protected using OAuth 2.0, bearer tokens are considered as a defense against CSRF attacks. Please note that if the MVC portion of the application uses forms authentication (i.e., uses cookies), anti-forgery tokens have to be used by the MVC web app.

Example

The Web API has to be informed to rely ONLY on bearer tokens and not on cookies. It can be done by the following configuration in WebApiConfig.Register method:

config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

The SuppressDefaultHostAuthentication method tells Web API to ignore any authentication that happens before the request reaches the Web API pipeline, either by IIS or by OWIN middleware. That way, we can restrict Web API to authenticate only using bearer tokens.