SharePoint User A authenticated as User B

How could that happen ?

Let me give a some information about the problem:

Issue:
Intermittently Users authenticated with reverse proxy, impersonate incorrectly and User A may become User B . Based on user privileges , end users experiencing either access denied or having different user identity and permissions.

Receipts

  • 1 In the middle Device ,who redirects authentication or re-authenticate. (I am not meaning a hacker device , if you are using SSL, it is not possible easily but your system admins can). It is mostly a Reverse Proxy configured officially by your system admins.All most every modern proxy has a feature that uses Port Sharing or Re-use Session functionality. It is perfectly fine , provides high performance , prevent reauthentication and port exhaustion problem.It is works for well almost every scenario . Almost!!!
  • Session-Based Authentication , (Like NTLM or Certificate Authentication). In our scenario,We have one web application with two Authentication Provider , 1 for default CBA/NTLM and 1 for CBA/Form-Based Authentication. (Issue happens on CBA/NTLM part)
    • This configuration provides another authentication layer on SharePoint ,and force SharePoint to use Federated Authentication mechanizm , so you will see Fed Auth cookies are in use.

Some important information:

Federated Authentication over CBA/NTLM. Despite the fact that it is a token/cookie based architecture, it is depending on NTLM authentication under the cover. It means it is still a Session Based Authentication.

Why we have a problem:
Because Any middle device setting for “same TCP session re-use” is not suitable/unsupported for any “Session Based” authentication type.

The issue, It is not related directly SharePoint implementation , It is related that how the Session Based Authentication works.

Also same problem may occur ; faulty middle device software and other incorrect configurations.

How the issue happens,
Lets have a look in details for Federated Authentication over CBA/NTLM.

In TCP/Network Layer – We don’t have any authentication in this layer.
We have two end points . Point A (Reverse Proxy) to Point B (SharePoint WFE)
Before autentication a TCP connection estabilishes between that two points.

Example
Point A – IP 10.10.0.5 , Source Port : 45000  -> Point B – IP : 10.10.0.25 port 443
We are now calling this “A TCP Channel” or “A TCP Session” .

After TCP connection is estabilished then HTTP start to work in that channel.

HTTP Layer
User go to the server anymously first , the server provides authentication challanges it supported. And user provides its credential assets . This is called NTLM Handshake;

NTLMNTLM2

TCP Channel should not closed until NTLM handshake complete. It is a requirement for
NTLM authentication . Thats why , all modern web servers , use a standart/feature called HTTP Keep Alive which provides “Persistent Connection” not only NTLM handshake duration , also several requests are handled in same TCP Channel until Client or Server close the connection.

Keep-Alive-Sessions

After NTLM HandShake completed , IIS Stores the Session Information ,
TCP Channel  X  -> [Point A]  [IP], [Port] <=> Identity : Authenticated User A.  (Or Anonymous)

(If we don’t use , HTTP Keep Alive,  For every request we need to do re-authenticate . (it is not a session based authentication it is called Request Based Authentication . Well NTLM fails in that scenario. You will see flooding 401 responses on NTLM handshake.)

CBA/NTLM

Now SharePoint come in the scenario , It builds claims and tokens on IIS/NTLM Identity , creates the tokens via Security Token Service , caches the tokens with Distributed Cache or Local Cache.

SharePoint and IIS believe and trust , underlayer TCP Session belong to only one verified authenticated identity.

If you have more than one authentication provider , SharePoint also builds Federated Authentication Cookies , default 5 days duration .Cookie – Token pairs must be match for user verification.
Fed Auth Cookie sent to client with last response in NTLM handshake (Status 200 or 302).
and corresponding Token has been cached in server (default 10 hours).

All incomming requests are considered valid/authenticated based on Fed Auth Cookie – Security token pair.

What happens if SharePoint can’t find token in the cache:
If the cookie valids , It rebuilds the token  and cache the token again and updates the cookie.  (You will have another 5 days, “sliding” )
It do not re-authenticate.

What happens if the Cookie expires: Well you need to reauthenticate.

What happens if the TCP Channel closed : you need to reauthenticate. Even client send close channel , in the middle devices can prevent it. Because It wants to reuse that TCP Channel.

So far so good,

But what if someone , some other user  use the same TCP Channel and send requests to the server . Well exactly what is happening if the reverse proxy does in session-reuse functionality.

SharePoint and IIS believe and trust , underlayer TCP Session belong to only one verified authenticated identity.Because how the bible says for Session-Based Authentication works.

Problematic Scenario:
Lets assume User A authenticated , have a valid cookie and continue communication without re-autheticate using Cookie-Token pairs for validation.

In mean while User B make a request (anonymous first) from same TCP Channel and requesting authentication.It is NTLM.  Well the TCP Channel is not closed , it is the same channel,  There is no possibility to understand it is the different user, Server reuthenticate the user.

After NTLM HandShake completed , IIS Stores the Session Information by overriding ,
TCP Channel  X  -> [Point A]  [IP], [Port] <=> Identity : Authenticated User B.  (Or Anonymous)
IP is the always Reverse proxy it isn’t changed.Also we have using the same TCP Channel so the port also same. It is absolute override.

Now the channel is belong to USER B instead of USER A.
Well User A still have no issues, he has a valid cookie and we have a valid token , so User A and User B communicates with the server without any problem in same tcp channel.

But the problem happen when the token is missed/expired (default 10 hours) .
What SharePoint does , verify the channel in that point ,ask to the IIS what was the Identity  ? IIS tells : it is UserB . SharePoint recreates the token and updates the cookie for UserB in a request which belong to UserA.
Now User A gets inccorect cookie and have inccorect token cached . It becomes User B by now.

Depends on permissions , either facing access denieds or have access UserB’s resources.

This problem is called “Session Hijacking“.
This is not a security hole in Sharepoint ,IIS or NTLM .

An anology :
Lets assume , you have a internet faced web site under authentication have must protected resources and if you enable anonymous access on that server in same resources .Is it considered security hole in authentication mechanizm or your code ? Of course not.

Well, there is still a security issue because of unsupported or incorrect configuration . Also it is not depended on Sharepoint, It may happen any ASP.NET application on any kind of Session-Based Authentication.

In conclusion,

Any “Session Based” authentication (like NTLM, Certificate auth etc.)  to work needs one TCP Channel per authenticated user.

SharePoint Federated Authentication for Claims Based Authentication over NTLM is depending on the underlying NTLM Authentication. NTLM is a session based authentication . Any middle device setting for “same TCP session re-use” is not suitable/unsupported for these type of authentications.

Suggestions:

  • Disabling “TCP Channel/Session re-use” feature in middle devices
  • Update in the middle devices firmware for any faulty software
  • Not using Session-Based Authentication with Reverse Proxy “Session re-use” feature or changing authentication type for any/suitable “Request-based” authentication or “token based” authentication (like ADFS) or Form based authentication.

Note: Don’t mess with “Session ” that is TCP level Session/Channel, not an application level session object or structure !! (OSI Layer 5)

Advertisements

ASP.NET store Viewstate data in Session

Consider you have a web control as an assembl y and you dont have the source code of this . And the control store its data in viewstate and that data is really big. You can not able to change viewstate usage for this control . And much worse you have to use this important control.Thats may be help you to reduce output and use viewstate process at same time.

I mean you can use viewstate and store in session and reduce the weight of output.Ok that cost as server resources. And I dont really discuss it is proper or efficent or not. I Just show how to do it.

My other article about viewstate deal with compression and how to override base page functions of
LoadPageStateFromPersistenceMedium and SavePageStateToPersistenceMedium
I also use that functions in this article.
https://blog.bugrapostaci.com/2010/02/02/asp-net-compress-viewstate/

We are using one unique session key as path  for each page in session like
 Session[“ViewState_” + this.Request.Path]
You should better if you define a specific Guid value in your pages and use it for Session key.

protected override object LoadPageStateFromPersistenceMedium()
{
    string viewState = string.Empty;
    // try to get state data form Session.
    viewState = Session["ViewState_" + this.Request.Path] != null ? Session["ViewState_"
                      + this.Request.Path].ToString() : string.Empty;
 
    // Decompress the encoded and compressed state data than return it.
    byte[] bytes = Convert.FromBase64String(viewState);
    bytes = Utilities.MemoryCompressor.Decompress(bytes);
    LosFormatter formatter = new LosFormatter();
    return formatter.Deserialize(Convert.ToBase64String(bytes));
}
protected override void SavePageStateToPersistenceMedium(object state)
{
    //Encode state data
    LosFormatter formatter = new LosFormatter();
    StringWriter writer = new StringWriter();
    formatter.Serialize(writer, state);
    string viewStateString = writer.ToString();
    byte[] bytes = Convert.FromBase64String(viewStateString);
    bytes = Utilities.MemoryCompressor.Compress(bytes);
    //Save to session
    if (Session["ViewState_" + this.Request.Path] != null)
        Session["ViewState_" + this.Request.Path] = Convert.ToBase64String(bytes);
    else
        Session.Add("ViewState_" + this.Request.Path, Convert.ToBase64String(bytes));
}
Happy Codding...

HttpHandler with Session State

If you are developing httphandler in asp.net realized that httphandlers can not use session as default.If you want to access session object do it as below.

Add  “System.Web.SessionState” namespace to your handler code.

There are two interface . one of them  must be inherited by your httphandler object:

IRequiresSessionState Interface

Specifies that the target HTTP handler requires read and write access to session-state values. This is a marker interface and has no methods.

IReadOnlySessionState Interface
Specifies that the target HTTP handler requires only read access to session-state values. This is a marker interface and has no methods.
 
 Example :
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.SessionState;
 
namespace PostmanExamples
{
 
    // IRequireSessionState if you want write access
    public class MyHttpHandlerWithSessionState
        : IHttpHandler, IReadOnlySessionState
    {
        public void ProcessRequest(HttpContext context)
        {
            string s = context.Session["SomeSessionVariable"];
        }
 
        public bools IsReusable { get { return true; } }
    }
}

Session state with web services

 The extra trick needed is on the caller side.  You have to save and store the cookies used by the web service. 

If an XML Web service method uses session state, then a cookie is passed back in the response headers to the XML Web service client that uniquely identifies the session for that XML Web service client. In order for an XML Web service to maintain session state for a client, the client must persist the cookie. Clients can receive the HTTP cookie by creating a new instance of CookieContainer and assigning that to the CookieContainer property of the proxy class before calling the XML Web service method. If you need to maintain session state beyond when the proxy class instance goes out of scope, the client must persist the HTTP cookie between calls to the XML Web service. For instance, a Web Forms client can persist the HTTP cookie by saving the CookieContainer in its own session state. Because not all XML Web services use session state and thus clients are not always required to use theCookieContainer property of a client proxy, the documentation for the XML Web service should state whether session state is used.

See the MSDN documentation on HttpWebClientProtocol.CookieContainer property. 

However, please note if you’re using proxy object to call a web service from your page, the web service and your page cannot share the same session state due to architecture limitation. 

This can be done if you call your web service through redirect. 

Example:

    public class UseWebServiceWithSessionState
    {
        public static void Example()
        {
            // Create a new instance of a proxy class for your XML Web service.
            WebServiceInstance ws = new WebServiceInstance();
            CookieContainer cookieJar;
 
            // Check to see if the cookies have already been saved for this session.
            if (Session["CookieJar"] == null)
                cookieJar = new CookieContainer();
            else
                cookieJar = (CookieContainer)Session["CookieJar"];
 
            // Assign the CookieContainer to the proxy class.
            ws.CookieContainer = cookieJar;
 
            // Invoke an XML Web service method that uses session state and thus cookies.
            int count = ws.PerSessionServiceUsage();
 
            // Store the cookies received in the session state for future retrieval by this session.
            Session["CookieJar"] = cookieJar;
 
            // Populate the text box with the rewslts from the call to the XML Web service method.
            Logger.Log(count.ToString());
        }
 
    }
more info about HttpWebClientProtocol:
http://msdn.microsoft.com/en-us/library/system.web.services.protocols.httpwebclientprotocol(VS.71).aspx

Session_End is not fired

Remarkable Question :
1. Remember Session_End event is supported only in InProc mode.  
2. Session_End won’t be fired if you close your browser. HTTP is a stateless protocol, and the server has no way to know if your browser has closed or not. 
3. Session_End will be fired only (i) after n minutes of inactivity (n = timeout value), or (ii) if someone calls Session.Abandon(). 
4. For case (i) (pt. 3), Session_End will be run by a background thread, which implies:

    a. Your code in Session_End is running using the worker process account. You may have permission problem if you’re accessing resource such as database.
    b. If an error happens in Session_End, it will fail silently.
5. For case (ii), please note that in order for Session_End to be fired, your session state has to exist first.  That means you have to store some data in the session state and has completed at least one request.  
6. Again for case (ii), Session_End will be called only if the abandoned session is actually found. As a result, if you create and abandon a session inside the same request, because the session hasn’t been saved and thus can’t be found, Session_End won’t be called.  This is a bug in v1 and upcoming v1.1.