锁定老帖子 主题:session的混乱与安全
精华帖 (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; 看出什么问题没? 应该将上面的代码中的所有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问题等等
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-11-20
在 junxy(xieyujun2006) 同学的提醒下,重新整理了这篇Blog,完善了User和Session关系一节.
欢迎大家指正我的错误. |
|
返回顶楼 | |
发表时间:2010-11-21
写的很好,对于 10.3 的情况在你博客中我举了个163邮箱的例子,和你举的gmail例子是一样的,期待高手的解决方案,呵呵。。。
|
|
返回顶楼 | |
发表时间:2010-11-22
haitaohehe 写道 写的很好,对于 10.3 的情况在你博客中我举了个163邮箱的例子,和你举的gmail例子是一样的,期待高手的解决方案,呵呵。。。
普通的web应用倒是可以使用cookie记录的形式,直接定位为后输入的user,提示重新login的就不知道了。同样期待高手 |
|
返回顶楼 | |
发表时间:2010-11-22
原创地址是tomcat的主页了,在调整中么?
|
|
返回顶楼 | |
发表时间:2010-11-22
lz_cleaner 写道 原创地址是tomcat的主页了,在调整中么? http://www.smithfox.com 的托管方有一些问题, 大家可以在javaeye里讨论. 呵呵 |
|
返回顶楼 | |
发表时间:2010-11-24
写的很好,我往往在写程序时忽略session的重要性,看到该贴子收益很多
|
|
返回顶楼 | |
发表时间:2010-11-26
没有高手给出解决方案啊? 另外楼主如果把这篇帖子的内容格式整理一下,并且画几张图前来围观的人会更多的,呵呵。。
|
|
返回顶楼 | |
发表时间:2010-11-26
haitaohehe 写道 没有高手给出解决方案啊? 另外楼主如果把这篇帖子的内容格式整理一下,并且画几张图前来围观的人会更多的,呵呵。。
猜测一下,我看gmail都在页面上保留一个user account, 每次访问是不是可以用这个页面上的account和服务器端session进行比较,如果不一致的话,就认为是这个account登录已经过期, 要求重新登录.这时只有第二个account是有效的. 不确定是不是这样的原理. 我现在想不允许同时使用一个account在多台机器登录简单一点的方法,不知道怎么做更简单有效. |
|
返回顶楼 | |
发表时间: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, 也就不会混乱 |
|
返回顶楼 | |
浏览 8910 次