安全的数字化身份互连(二)--会话安全

2020-12-11  本文已影响0人  大树人vs大白

        登录完成后,用户不可能每一次操作都需要输入密码。因此系统需要记录用户的登录状态,又称会话状态。常见的做法是系统保存session。session存入用户信息,生成随机数sessionId,将sessionId返回浏览器,并存入浏览器的cookie中,下一次用户访问系统,携带cookie,系统通过cookie找到session,就可以知道用户是谁。

        对于集群服务,用户首次登陆,访问的A服务器,A服务器存入session,下次访问到了B服务器,B服务没有session,认为用户没有登陆,提示用户需登陆,这是一个bug。我们将每台服务器都识别到有session就可以解决这个问题了。session存入redis,登陆时往redis存session,之后都从redis取session。或者每台服务器都有session,每台服务器的session同步也能解决这个问题

        不管采用哪种方式,都有一个安全风险,sessionId给出去了,不论sessionId是随机数生成还是加密算出来的字符串,黑客并不关心,黑客只关心这个字符串代表了用户的会话状态。黑客也不需要拿到密码只需要拿到这个字符串,就可以模拟用户进行诈骗,转账,发表非法政治评论等非法活动。

        保护sessionId不被非法利用与保护密码同等重要。大多数情况下sessionId存储在cookie中,我们先了解cookie。

        我登录某系统后生成一个cookie,有name,value,domain,path,Expires/Max-Age,Httponly,Secure等属性,这里重点介绍其中几个。

Domain:cookie对于哪个域有效。这个cookie的域是xxx.yyy.com,则只有访问xxx.yyy.com下的api,浏览器才会将该cookie发送至后端服务器。这个值可以包含子域,如设置domain为yyy.com时,访问xxx.yyy.com也会带上该cookie。

HttpOnly:当值为true时,告诉浏览器不能通过js访问到该cookie,只有在发送请求到后端时,才会携带该cookie。

Secure:当值为true时,告诉浏览器,只有访问协议问https的api时,才会携带该cookie。

Expires/Max-Age:cookie有两种,本地cookie与session cookie。如果设置了cookie的过期时间则为本地cookie,不设置为session cookie。session cookie的特点是没有具体的过期时间,随着浏览器关闭而清除。本地cookie即使浏览器关闭也不会清除,而是到了时间自动清除。这也是为什么关闭浏览器后再次打开浏览器有些系统需要重新登录,而有些不需要的原因。

        知道cookie的几个特性后我们再来看看攻击人常用的几种攻击方式:XSS攻击,CSRF攻击。

        XSS攻击叫做跨站脚本攻击,指用户的输入拼接了正常的html+js+css,变成了带有攻击性的html+js+css。浏览器可能无法识别具有攻击性的html+js+css,按照正常的逻辑执行代码,这可能会导致攻击人偷走cookie(XSS还有其他的危害,但这里仅讨论与会话标识相关)。如果黑客在html中插入隐藏的form表单,通过document.cookie()获取到浏览器中cookie,作为参数并自动发送post请求到攻击人的后端api中,攻击人就可以拿到用户的cookie,也就可以拿到sessionId了。这种方式可以通过设置cookie的HttpOnly为true来防止js获取cookie值。从而避免通过XSS攻击获取sessionId。

        大多数浏览器有同源策略(协议\主机\端口组成源),其中一个限制是同源的网页才会共享cookie。但浏览器对html标签有白名单,img就是其中之一,通过img标签的src就可以发送get 请求,因访问的是xxx(银行)的域名,携带了cookie,银行认为是合法请求,转账成功。因img是get请求,那把转账等高危操作改成post接口不就可以了? 也不行,因为form表单的post请求也在白名单中。

        CSRF攻击之所以成功,是因为攻击人可以完全伪造用户的请求,那让攻击人无法伪造就可以解决这个问题了。在转账时,要求用户再次输入密码或输入验证码,就可以解决CSRF攻击。转账操作可以这么做,发表评论这类的操作,每次都要求用户输入密码或验证码用户体验就很很差了。

        还有Referer check,浏览器发送请求时,携带Referer header,值为网站url中的域名,异常转账时,虽然调用的www.xxx.com的api,但referer 值为www.yyy.com。在服务端只要验证Referer值就可以判断这是不是一个CSRF攻击。这种方式也有问题,就是完全相信了第三方(浏览器)。对于低版本的浏览器已经有办法可以篡改Referer值,高版本的浏览器目前无法篡改,如用户使用低版本的浏览器,Referer check将无法保证安全性。

        那还有什么办法可以解决CSRF攻击的问题? 我们来看下某国际知名身份管理系统是如何做到解决这个问题的。我们登陆该系统成功后,打开网页源代码查看html,搜索token可以看到

        在span中保存了一个token值

        我们再创建一个创建菜单

        打开浏览器的f12,查看网络请求,可以看到request header中有x-xxx-xcrftoken这个header。

        这就是为了解决CSRF攻击的方式:CSRF Token方式.

        CSRF Token工作原理就是在用户登录成功后,服务端生成token并保存一段时间,返回给浏览器,浏览器保存在html标签中。当用户操作访问后端api时,将该token放入request header中。后端验证该token 的合法性即可判断是否是CSRF攻击。这种方式能生效的重点在于攻击人无法拿到目标网站的html。

        最近在思考一个问题,就是如果黑客同时发起XSS攻击和CSRF攻击,这种方式是不是也失效了?黑客通过XSS攻击,获取到了CSRF token,攻击人立马发送钓鱼邮件给目标用户,目标用户点击了链接,网站打开时,先从黑客处获取CSRF Token,并携带CSRF Token发起了CSRF攻击,还有个前提是浏览器版本太低没有Referer,那不就可以攻击成功了?(我杞人忧天了吗?)

        cookie+session有这么多安全需要考虑,那不要cookie+session不就没这么多问题吗?现在流行的jwt就可以做到无session的登录认证,但jwt也有各种各样的安全问题。

        下回再聊jwt与单点登录中的安全。

上一篇下一篇

猜你喜欢

热点阅读