https://peterwong.net/blog/asp-net-session-and-forms-authentication/

The title can be misleading, because in concept, one is not related to the other.  However, a lot of web applications mix them up, causing bugs that are hard to troubleshoot, and, at worst, causing security vulnerabilities.

A little bit of background on each one.  ASP.NET sessions are used to keep track and keep information related to a “user” session.  When a web server is initially accessed by a browser, the server generates a unique session ID, and sends that session ID to the browser as the value of a cookie (the name of the cookie is ASP.NET_SessionId).  Along with that session ID, a dictionary of objects on the server, often referred to as session state, is allocated corresponding to that session ID.  This dictionary can be used to keep track of information unique to that session.  For example, it could be used to keep track of items placed in a shopping cart metaphor.

Note that this “session” can exist even if the user has not authenticated.  And this is often useful.  In a retail web site (like Amazon), you can put items in your shopping cart, and only need to authenticate or sign on when you are ready to checkout — and even then, you can actually make a purchase without needing to authenticate, provided, of course, that a valid credit card is used.

Because this “session” is disjoint from authentication, it is better referred to as a “browser” session instead of as a “user” session.  In a kiosk environment, if a user walks away from the kiosk while there are items in a shopping cart, the next user to use the kiosk will still see the same shopping cart.  The web server doesn’t know any better that a different user is using the kiosk, because the same session ID is being sent back in the session cookie during interaction with the web server.

That dictionary of objects on the server, the session state, also poses certain complications that most developers are aware of.  In a web farm, some form of sticky load balancer has to be used so that session state can be kept in memory.  Or a centralized store for the session state is used to make the state consistent across the servers in the web farm.  In either case, service performance can be affected.  I have a very strong opinion against using session state.  I avoid it, if at all possible.

What about Forms Authentication?  Forms Authentication is the most common authentication mechanism for ASP.NET web sites.  When a user is authenticated, most commonly using a user ID and password, a Forms Authentication cookie is generated and is sent to the browser (the name of the cookie, by default, is .ASPXAUTH).  The cookie contains the encrypted form of an authentication ticket that contains, among other things, the user ID that uniquely identifies the user.  The same cookie is sent to the web server on each HTTP request, so the web server has an idea of the user identity to correlate to a particular HTTP request.

Everything I mentioned above is common knowledge for web developers.  Trouble and confusion only comes about when an expectation is made that an ASP.NET session can be associated with ASP.NET authentication.  To be clear, it can be done, but precautionary measures have to be taken.

The problem is related to session hijacking, but better known as session fixation.  Assuming that you’ve done your diligence of using SSL/TLS and HttpOnly cookies, there isn’t a big risk of having the session ID stolen/hijacked by sniffing the network.  And most applications also perform some session cleanup when the user logs out.  Some applications even ensure that a new session ID is created when the user logs in, thinking that this is enough to correlate a session state with a user identity.

Remember that the session cookie and the forms authentication cookie are two different cookies.  If the two are not synchronized, the web server could potentially allow or disallow some operations incorrectly.

Here’s a hypothetical (albeit unrealistic) scenario.  A banking application puts a savings account balance into session state once the user logs in.  Perhaps it is computationally expensive to obtain the account balance, so to improve performance, it is kept at session state.  The application ensures that a new session ID is created after the user logs in and clears the session state when the user logs out.  This prevents the occurrence of one user reusing the session state of another user.  Does it really prevent it?  No.

As an end-user having control of my browser, I am privy to the traffic/data that the browser receives.  With the appropriate tools like Fiddler2 or Firebug, I can see the session and forms authentication cookies.  I may not be able to tamper them (i.e., the forms authentication cookie is encrypted and hashed to prevent tampering), but I could still capture them and store them for a subsequent replay attack.

In the hypothetical banking application above, I initially log in and get SessionIDCookie1 and FormsAuthCookie1.  Let’s say the account balance stored in session state corresponding to SessionIDCookie1 is $100.

I don’t log out, but open up another window/tab and somehow prevent (through Fiddler2 maybe) the cookies from being sent through the second window.  I log in to that second window.

The web server, noting that the request from the second window has no cookies, starts off another session state, and also returns SessionIDCookie2 and FormsAuthCookie2.

Browsers usually overwrite cookies with the same names, so my SessionCookieID2 and FormsAuthCookie2 are my new session ID and forms authentication cookies.

But remember that I captured SessionIDCookie1 and FormsAuthCookie1 to use in a future attack.

In that second window, I transfer $80 away from my account, thereby updating the session state corresponding to SessionIDCookie2 to be $20.  I cannot make another $80 transfer in the second window because I do not have sufficient funds.

Note that SessionIDCookie1 has not been cleaned up and there is a session state on the server corresponding to SessionIDCookie1 which still thinks that the account balance is $100.  I now perform my replay attack, sending to the web server SessionIDCookie1 and FormsAuthCookie1.  For that given session state, I can make another $80 transfer away from my account.

You might say that the application could easily keep track of the forms authentication cookie issued for a particular user, so that when FormsAuthCookie2 is issued, FormsAuthCookie1 becomes invalid and will be rejected by the server.  But what if I use SessionIDCookie1 and FormsAuthCookie2 on the second window?  It’s the same result — I can make another $80 transfer away from my account.

Oh, you might say that the application should invalidate SessionIDCookie1 when SessionIDCookie2 is issued.  Sure, but how?  Unlike the forms authentication cookies, where the user identity is the same within both cookies, there is nothing common between SessionIDCookie1 and SessionIDCookie2.  And since there is nothing relating SessionIDCookies with FormsAuthCookies, there’s no mechanism to search for and invalidate SessionIDCookie1.

The only workaround for this is custom code that ties a SessionIDCookie with the FormsAuthCookie that was issued for the same logical session.  One of the following options should provide a solution.

  • Key your session states by an authenticated user ID instead of by a session ID.  No need for the session cookie.  This will not work for applications that need to keep track of session without authentication (e.g., online shopping).
  • Store the session ID as part of the payload for the forms authentication cookie.  Verify that the session ID in the session cookie is the same as that stored in the forms authentication cookie.  Keep track of the forms authentication issued for each user so that only a single forms authentication cookie (the most recently issued) is valid for the same user.

Maybe an overarching solution is to avoid storing user-specific information in the session state.  Remember that it is a “browser” session state, and has nothing to do with an authenticated user.  If you keep that in mind and only store “browser”-related information into session state, then you could avoid the problems altogether.

ASP.NET session fixation is not a very publicized problem, but is potentially a big risk, specially if improper assumptions are made with regard to session and authentication.  ASP.NET session fixation is also described long back in http://software-security.sans.org/blog/2009/06/14/session-attacks-and-aspnet-part-1/, and been reported through Microsoft Connect http://connect.microsoft.com/feedback/viewfeedback.aspx?FeedbackID=143361, but to my knowledge, has not been addressed within the ASP.NET framework itself.

ASP.NET Session and Forms Authentication and Session Fixation的更多相关文章

  1. ASP.NET 4.0 forms authentication issues with IE11

    As I mentioned earlier, solutions that rely on User-Agent sniffing may break, when a new browser or ...

  2. How does ASP.NET Forms Authentication really work?

    I've always wondered how exactly ASP.NET forms authentication works. Yes, I know how to configure Fo ...

  3. IIS下Asp.Net应用程序多进程设置及Session共享

    背景: 目前项目中在单个进程的应用程序经常会遇到w3c.exe崩溃的情况,于是就设想是否可以通过IIS多进程的方案来避免出现该问题. 于是搜了下“怎么实现多进程的方案”,找到了这篇文章:http:// ...

  4. ASP.NET 使用mode=”InProc”方式保存Session老是丢失,无奈改成StateServer 模式。

    http://blog.csdn.net/fox123871/article/details/8165431 session是工作在你的应用程序进程中的.asp.net进程.iis往往会在20分钟之后 ...

  5. asp.net 类库中获取session c#类中获取session

    asp.net  类库中获取session c#类中获取session 1. 先引入命名空间 using System.Web; using System.Web.SessionState; 在使用H ...

  6. Forms Authentication in ASP.NET MVC 4

    原文:Forms Authentication in ASP.NET MVC 4 Contents: Introduction Implement a custom membership provid ...

  7. 在ASP.Net MVC 中如何实现跨越Session的分布式TempData

    Hi,guys!Long time no see! 1.问题的引出 我相信大家在项目中都使用过TempData,TempData是一个字典集合,一般用于两个请求之间临时缓存数据或者页面之间传递消息.也 ...

  8. asp.net core系列 43 Web应用 Session分布式存储(in memory与Redis)

    一.概述 HTTP 是无状态的协议. 默认情况下,HTTP 请求是不保留用户值或应用状态的独立消息. 本文介绍了几种保留请求间用户数据和应用状态的方法.下面以表格形式列出这些存储方式,本篇专讲Sess ...

  9. 窥探ASP.Net MVC底层原理 实现跨越Session的分布式TempData

    1.问题的引出 我相信大家在项目中都使用过TempData,TempData是一个字典集合,一般用于两个请求之间临时缓存数据或者页面之间传递消息.也都知道TempData是用Session来实现的,既 ...

随机推荐

  1. http 400报错

    http 400报错---springmvc相关: 1.使用了json入参,传递给了对象,如果对象里的属性,如这里的Bonus是int类型,你传入了非int类型,这里就会报400 2.使用了@Requ ...

  2. poj 3304 判断是否存在一条直线与所有线段相交

    Segments Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8579   Accepted: 2608 Descript ...

  3. golang测试框架--smartystreets/goconvey

    视频教程和配套博客:goconvey - 课时 1:优雅的单元测试 Go 语言虽然自带单元测试功能,在 GoConvey 诞生之前也出现了许多第三方辅助库.但没有一个辅助库能够像 GoConvey 这 ...

  4. 用“道”的思想解决费用流问题---取/不取皆是取 (有下界->有上界) / ACdreamoj 1171

    题意: 给一个矩阵,给出约束:i(0<i<n)行至少去ai个数,j行至少取bi个数,要求取的数值之和最小. 开始一见,就直接建了二分图,但是,发现这是有下界无上界最小费用流问题,肿么办.. ...

  5. Unity3D 异步加载 在 场景加载 中的使用

    异步加载 我们想一想玩过的一些游戏,基本都会有加载界面——因为游戏场景数据较大,所以需要加载一小段时间.那为什么一些2D游戏也会有加载界面呢?按理说2D游戏场景会很小,这样做是为了让游戏跑在低端设备上 ...

  6. Unity3D游戏开发之C#编程中常见数据结构的比较

    一.前言 Unity3D是如今最火爆的游戏开发引擎,它可以让我们能轻松创建诸如三维视频游戏.建筑可视化.实时三维动画等类型的互动内容.它支持2D/3D游戏开发,据不完全统计,目前国内80%的手机游戏都 ...

  7. BZOJ——1649: [Usaco2006 Dec]Cow Roller Coaster

    http://www.lydsy.com/JudgeOnline/problem.php?id=1649 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 7 ...

  8. luogu P3865 【模板】ST表

    题目背景 这是一道ST表经典题——静态区间最大值 请注意最大数据时限只有0.8s,数据强度不低,请务必保证你的每次查询复杂度为 O(1)O(1) 题目描述 给定一个长度为 NN 的数列,和 MM 次询 ...

  9. ETCD 单机安装

    由于测试的需要,有时需要搭建一个单机版的etcd 环境,为了方便以后搭建查看,现在对单机部署进行记录. 一.部署单机etcd 下载 指定版本的etcd下载地址 ftp://ftp.pbone.net/ ...

  10. [Testing] Static Analysis Testing JavaScript Applications

    The static code analysis and linting tool ESLint is the de-facto standard for linting JavaScript pro ...