论坛首页 Java企业应用论坛

session的混乱与安全

浏览 8910 次
精华帖 (5) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (4)
作者 正文
   发表时间:2010-11-19   最后修改:2010-11-20

[说明: 本文为 http://www.smithfox.com/?e=32 原创, 转载请注明原文, 谢谢]

session的安全有两层意思:

1> 对最终客户来说, 不会因为session的share和造成混乱, 使end-user的信息泄漏以及其他安全问题

2> 对系统本身来说, 不会因为有hacker通过模拟sessionid和cookie来获取server信任进而进行恶意破坏

让我们逐层解释和展开问题:

1> 首先说明, 本文所有session专指Servlet HttpSession

2> 后台Session和Browser之间通过JSESSIONID来关联, JSESSIONID是Servlet标准,也是关键字, Servle规定Browser用Mem Cookie来存储JSESSIONID, 注意并不是disk cookie.一旦浏览器关闭后JSESSIONID就从PC消失, 更加安全.

3> Session也是一种很好的安全认证机制, 后台会标识session是不是已经被认证了, 如果是,就不会让用户再输入password. JSESSIONID可以被理解成为一个已经认证的key, 所以Session有安全问题.

4> Servlet容器不会构造相同的JSESSIONID, 客户端也很难预期JSESSIONID

5> HTTPS SSL等技术可以防止网络传输中有人恶意篡改JSESSIONID

6> 禁用Cookie的情况JSESSIONID就必须用URLRewrite. 我们可以通过对URL本身采用摘要算法,自认证来防止恶意篡改JSESSIONID.

比如:  http://www.smithfox.com/abc?x=x&y=y&JSESSIONID=sdfdfsdfsdfsdfsdf&HWD=4FE23AD9892C

HWD的值是对整个URL的一个摘要算法, 如果有人改动了URL,这个HWD值就对不上了, 前提应该是这个算法别人不知道的.

7> 用户在自己的PC上肯定是可以看到当前的JSESSIONID的, 就象就你在自己的日记中看到了自己备忘的password一样, 这个不是技术安全问题.

8> 一台机器有多个自然人在使用, 出现的JSESSIONID欺骗, 应该没有技术办法可以解决. 只能是end-user自己小心,用完就关闭Browser. 我想这应该是在情理之中的事, 你是合租被盗应该是怪不得小区保安的, 也是需要自己平时提高防盗意识,呵呵.

9> 最近看到Tomcat7有个新的特性说是支持"防JSESSIONID劫持", 这个需要更多了解.

10> User和Session的关系.

Session是只认JSESSIONID不认人的, 包括自然人和系统Account. 这个问题比较搞.

我们用EndUser来表示自然人, User-Account表示系统帐号, 我们分析以下几种情况

10.1> 两个EndUser共用一个UserAccount并且在同一台PC, 这个混乱不是技术问题, 大家都可以理解

10.2> 两个EndUser分别使用不同的UserAccount在同一台PC, 这个是合租情况, 造成混乱不一定是技术问题

10.3> 某EndUser有两个UserAccount在同一台PC上, 我们需要考虑JSESSIONID在client端可以会混乱的问题.

因为不同的浏览器对于Cookie share的策略不同, 我们按程序设计必须按最容易出问题的Case想,比如IE8.

无论你是IE多窗口还是多TAB都是Share Cookie的. 所以总的指导方针是在client端做一些机制不允许用户这么做.

Google的gmail就是这么做的, 你可以一台机器上用IE打开两个不同的gmail account(两个窗口或是两个TAB都行),点新email或是其他需要和后台交互的行为时,gmail会退出一个,提示让你重新login并且gmail account已经固定为后输入的User-Account.

具体在Client怎么防止两个Account还需高手指点.

10.4> 某EndUserA用自己的UserAccountA先已经login,再访问另一个UserAccountB的资源,而且该资源是需要访问密码的. 

这种情况,往往因为后台Session设计的层次不清晰,造成了UserAccountA无需Password就直接访问到了UserAccountB的资源. 而且这个解决方案不能放在Client端, 因为访问UserAccountB的资源可能就是一个在Email中的Link,这个click动作客户端程序JavaScript是无法拦截的.

10.5> 总结来说:  

11> 从第10>点可以看出, session和自然人或是UserAccount有着千丝万缕的联系,但不是所有的系统只有User这一层业务概念,所以我们需要理解后台的Session分划和设计好Session.Attribute层次.

我们以一个假设业务模型为例说明问题: 这是一个只面向企业的图片共享web服务, 可以为多个公司(企业)提供服务, 用户必须属于某一个公司, 用户可以创建"图片分组", 图片分组可以设置为private(需要密码访问), 也可以直接公开. 图片分组是公司财产, user可以创建"图片分组", 但是图片分组资源是归属公司, 同一公司内部的所有user可以直接访问图片分组(如果是公开), 也可以通过password(如果需要)访问图片分组.

这个业务模型中, 既有比User更高层的概念, 比如公司. 也有比User更底的概念, 比如用户的上传图片分组(imageGroup).

11.1> 不同的war包部署在tomcat,不同的war包之间的session是不会混乱的, 这个是由tomcat架构决定的. 另他的没有做过调查, 也有可能是Servlet标准, 有高手可以帮确认一下.

11.2> 多个公司又是运行在同一个tomcat application内, 怎么防止不同公司之间的session混乱

可以采用类似于防止重复提交的技术, 首先做一个优先级很高的filter, 每次reqeust和response都需要经过这个filter

在所有login模块, 设置一个ticket cookie,写入当前company信息, 每个reqeust到达的第一步就是检测client cookie和当前的URL信息, 以及session信息是否一致, 如果enduser是从一个company中click了一个其他company的link, 该filter就会发现ticket信息不一致, 然后就强制logout, 再次让user login. 并且每次response时做ticket的改动, 使client无法模拟

11.3> 怎么防止imageGroup信息混乱

Session本身是一个集合, 具体还是使用session.attribute["key"]

Session本身是User level的, 对于低于User level的信息, 需要好好规划attribute key

想像这样的case:

有两个imageGroup, 一个是public的, 一个是需要password的, 

http://www.smithfox.com/companyIBM/public_images/

http://www.smithfox.com/companyIBM/password_images/

后台对imageGroup输入密码逻辑的伪代码如下:

boolean needpasswd = true;
if(session.getAttribute("NEED_PASSWORD") == null){
session.setAttribute("NEED_PASSWORD", needpasswd);
boolean needpasswd = 一个很耗时很复杂的验证函数(user, imageGroup, xxx);
} else{
needpasswd session.getAttribute("NEED_PASSWORD");
}
if (needpasswd ){
showPasswordDialog() ;

看出什么问题没?

应该将上面的代码中的所有attribute key改成 "NEED_PASSWORD"+{imageGroupID}

否则用户只要先看了一个public后, 后面的所有图片分组都无需passwd就可以访问了, 即使这个imageGroup是private的.

13> 在用session之前一定需要检查是否真的一定需要session来解决, 比如只是想传value到JSP page, request.setAttribte()更适合

14> 比较小而多的业务对象,如果必须save在session一定要及时removeAttribute否则session用的内存会暴涨.

因为Session不会因为客户端不用了,就会自动清理,而是必须到SessionTimeOut才会,如果在SessionTimeOut期间内有很多的对象在Session内,就会有问题。所以需要即时清理已经不用的Session.Attribute

15> Cookie和Session一样, 同样需要注意 cookie key的层次问题,以及过期问题,domain, path问题等等

 

   发表时间:2010-11-20  
在 junxy(xieyujun2006) 同学的提醒下,重新整理了这篇Blog,完善了User和Session关系一节.

欢迎大家指正我的错误.
0 请登录后投票
   发表时间:2010-11-21  
写的很好,对于 10.3 的情况在你博客中我举了个163邮箱的例子,和你举的gmail例子是一样的,期待高手的解决方案,呵呵。。。
0 请登录后投票
   发表时间:2010-11-22  
haitaohehe 写道
写的很好,对于 10.3 的情况在你博客中我举了个163邮箱的例子,和你举的gmail例子是一样的,期待高手的解决方案,呵呵。。。


普通的web应用倒是可以使用cookie记录的形式,直接定位为后输入的user,提示重新login的就不知道了。同样期待高手
0 请登录后投票
   发表时间:2010-11-22  
原创地址是tomcat的主页了,在调整中么?
0 请登录后投票
   发表时间:2010-11-22  
lz_cleaner 写道
原创地址是tomcat的主页了,在调整中么?

http://www.smithfox.com 的托管方有一些问题, 大家可以在javaeye里讨论. 呵呵
0 请登录后投票
   发表时间:2010-11-24  
写的很好,我往往在写程序时忽略session的重要性,看到该贴子收益很多
0 请登录后投票
   发表时间:2010-11-26  
没有高手给出解决方案啊? 另外楼主如果把这篇帖子的内容格式整理一下,并且画几张图前来围观的人会更多的,呵呵。。
0 请登录后投票
   发表时间:2010-11-26  
haitaohehe 写道
没有高手给出解决方案啊? 另外楼主如果把这篇帖子的内容格式整理一下,并且画几张图前来围观的人会更多的,呵呵。。

猜测一下,我看gmail都在页面上保留一个user account, 每次访问是不是可以用这个页面上的account和服务器端session进行比较,如果不一致的话,就认为是这个account登录已经过期, 要求重新登录.这时只有第二个account是有效的.

不确定是不是这样的原理. 我现在想不允许同时使用一个account在多台机器登录简单一点的方法,不知道怎么做更简单有效.
0 请登录后投票
   发表时间:2010-11-26  
grandboy 写道
haitaohehe 写道
没有高手给出解决方案啊? 另外楼主如果把这篇帖子的内容格式整理一下,并且画几张图前来围观的人会更多的,呵呵。。

猜测一下,我看gmail都在页面上保留一个user account, 每次访问是不是可以用这个页面上的account和服务器端session进行比较,如果不一致的话,就认为是这个account登录已经过期, 要求重新登录.这时只有第二个account是有效的.

不确定是不是这样的原理. 我现在想不允许同时使用一个account在多台机器登录简单一点的方法,不知道怎么做更简单有效.


"不允许同时使用一个account在多台机器登录": 我没有写在这篇文章上面, 因为我认为这个不是session的问题,而是User方面的问题. 管理他们之间有联系

我在文章中的gmail问题是:
"不允许在同一台机器上同时用多个account",

其实这个问题主要还是client share cookie的问题.
不在一台机器上, 或是一台机器上的两种不同浏览器, 都没有问题, 因为不share cookie, 就不会share jsessionid, 也就不会混乱
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics