月度归档:2022年01月

WEB 会话管理杂谈

1 前言

某一天,有同事在产品问题反馈大群里扔出一个问题:登录后隔两天再打开页面就需要重新登录。在查问题的过程中,我们有提到 7 天过期,老板对此也扔出了一个问题:为什么是 7 天。于是有了今天这篇文章。首先我们先看一下 WEB 会话管理的概念。

2 概念

在说 WEB 会话管理之前,我们需要先说一下 HTTP 协议。这里我们暂且不提 HTTP2.0 和 HTTP3.0,本文的 HTTP 协议主要是指现在使用最广泛,使用历史最久的 HTTP1.x 版本。

HTTP 协议是一个无连接无状态的协议。

  • 无连接是指限制每次连接只处理一个请求,服务端处理完客户端的请求,并收到客户端的应答后,即断开连接。后面协议中增加了 Keep-Alive,这个特性使得客户端到服务器端的连接持续有效,当出现对服务端的后继请求时,Keep-Alive 功能避免了建立或者重新建立连接。
  • 无状态是指在协议层面对于事务处理没有记忆能力,服务端不知道客户端是什么状态。当我们给服务器发送 HTTP 请求之后,服务端根据请求内容给我们返回数据,但是返回数据后,服务端不会记录任何信息。

在互联网早期,这样的协议完全能满足 WEB 应用的需要,但随着 WEB 应用复杂度的提升,识别用户是谁,记录用户的行为,有用户状态变成了刚性需求,或者说是核心功能点。 此时,会话管理应运而生,会话管理是一种控制和维持用户交互状态的机制,它定义了一系列用于管理用户和 WEB 应用系统交互状态的措施。

会话管理有两个关键点,一个是怎样存储,另一个是存储什么。

3 存储方式

3.1 服务端 session

在早期的有会话管理的 WEB 应用中,会话经常存储在服务端的 session 中,常见的 WEB 编程语言都自带 session 的处理逻辑,如 PHP 和 Java 都默认带有 session 的扩展或组件,如 PHP 中的全局变量 $_SESSION。客户端存储 sessionid,通过 cookie / 隐藏的表单字段 / 重写 URL 的方式传递 sessionid,后两种方式一般在禁用 cookie 的时候启用。

服务端 seesion 的优势

  • 安全性好,客户端与服务端保持会话状态的媒介始终只是一个 sessionid 串,我们一般会保证这个串的随机性,以防止攻击者遍历或穷举;除非通过 CSRF 或 HTTP 劫持等方式,才有可能冒充别人进行操作。最坏的情况就算是冒充成功,在服务端我们也会有一些登录凭证的验证来进行纵深的防御;
  • 可控度高,在服务端集中存储,后台同学可以对其进行操作,比如踢下线之类的操作。

针对服务端的存储方式,就会出现了我们在前言中提到的过期问题,为什么要有过期?

  1. 为了节省服务器资源,登录态相关信息存储在服务器还是需要一定资源的,如果一直不过期,几千万上亿的用户登录态数据将是较大的一个成本,而这个成本是完全可以省下来的;
  2. 为了安全,用户长时间未操作,如果有人用了他的账号干了点别的,这样就存在较大的风险;另外在业务逻辑上可以实现抢登等逻辑以规避一些安全上的风险。

有了过期,就会有过期时间,常见的过期时间有 1 小时( 3600 秒),2 小时( 7200 秒),1 天, 7 天(一周),15 天,30 天(一个月)。这个过期时间更多的是经验值,或者说是一个大家认为合适的值。这个值对业务的影响,貌似没有一个客观的评价。

服务端的 seesion 的常见存储方案如下:

  • 单机方案,存储要么是硬盘,要么是内存,二者的区别在于获取和写入的速度,对于海量的互联网应用来说,存储到内存方案更常见一些。单机存储方案是有一定上限的,其上限是单机存储的上限。
  • 分布式方案,分布式的内存数据库如 Redis / Memecached,Tomcat 等都有现成的共享 session 方案。分布式存储方案从理论上来讲是没有存储上限的,可以给 Redis 做分布式部署。

考虑到服务器的负担和架构的复杂性,依赖于浏览器每次请求都会带上 cookie 的特性,我们可以把用户的登录凭证直接存到客户端(浏览器)中。当用户登录成功之后,把登录凭证写到 cookie 里面,并给 cookie 设置有效期,后续请求直接验证存有登录凭证的 cookie 是否存在以及凭证是否有效,即可判断用户的登录状态。当年 Rails 的默认会话存储方案是用 cookie 方案。

优点

  • 实现了服务端的无状态化,彻底移除了服务端对会话管理的逻辑,服务端只负责创建和验证登录 cookie 即可;
  • 不同应用间的登录态可以通过算法或密钥的一致性来保持,以实现会话共享。

缺点

  • cookie 有大小限制,存储不了太多数据,同时会话会占用其它业务场景的空间,从而导致 cookie 空间紧张;
  • cookie 在每次请求时都会带上,当会话中有较多的冗余数据时,会对性能有一些影响,并且产生一些不必要的网络带宽;
  • 多应用时可能会有跨域问题,浏览器在发起请求时会检查所有存储的 cookie ,如果某个 cookie 所声明的作用范围大于等于将要请求的资源所在的位置,则会把该 cookie 附在请求资源的 HTTP 请求头上发送给服务器。当作用范围小了,或者交错了,则会出现跨域问题。

3.3 令牌方案

相对于前面两种方案,令牌方案是前后端分离后的常见方案,session 的概念在这个方案里面更淡一些。

在讲令牌方案之前我们先讲一下安全上两个非常重要的点:认证和授权。有时候会把这两个东西弄混,其定义如下:

  • 认证是这样一种验证过程:通过让用户、网站、应用程序通过提供合法证书或验证方式,以证明他们符合自己所宣称的身份。
  • 授权是指的是一个验证某用户能访问什么的过程。在授权过程中,某用户 / 应用程序的权限级别被确定后,才被允许访问特定的 APIs / 模块。通常,授权发生在用户身份被认证之后。
区别 认证 授权
作用 确定用户所宣称的身份 确定用户可访问的权限
方式 通过合法凭证校验用户 通过规则和策略校验访问
时机 早于授权 在认证成功后执行
实现 通过 ID tokens 实现 用 Access Tokens 实现

基于令牌的认证和授权是现在最流行的的一种技术,当用户在某处输入一次其用户名和密码后,作为交换会得到一个唯一生成的已加密令牌。该令牌随后会替代登陆凭证,用以访问受保护的页面或资源。当我们要进行下一步的业务操作,会通过令牌获取到用户的的信息和会话的信息,此时一般是通过进程内的缓存或者某个特定的微服务来获取,这些微服务的后端的存储因公司技术架构和服务而异。一般来说,对于海量的互联网应用来说,这里最终还是从内存中获取的数据,如前面说到的分布式 NoSQL 数据库。

一个令牌就是服务器生成的一段数据,包含了唯一性识别一个用户的信息,一般被生成为一长串随机字符和数字。

比如看起来可能像这样:bb74324734bcf34748bb08bu2842f3288 或更复杂些比如: eyJ0eXAiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ1bXMiLCJzdWIiOjY1NDA1NjI5NCwiYXVkIjoiZ2FvZGluZ3giLCJleHAiOjE2NDE5MDgzOTZ9.8MZaB55vlScSDZxBmO-N9ol9UTvYPVvgUFab7dFe6fY 这个令牌本身是无意义和无用的,但结合适当的令牌系统,就会变成保证应用安全性的重要一环。

基于令牌的实现过程一般如下:

  1. 用户通过用户名和密码(或者其它登录方式,如国内的微信扫码)请求访问;
  2. 应用验证登录凭证;
  3. 应用向客户端发放已签名的令牌;
  4. 客户端存储令牌,并将其附加在其后的每次请求中一同发送(一般是带在 cookie 中,和 sessionid 类似);
  5. 服务器验证令牌并响应数据。

我们常用的基于令牌的方案有两个:

关于这两个方案的更详细的说明见:深入 OAuth2.0 和 JWT

在令牌的生命周期中存在两个较大的安全薄弱环节:

  1. 会话令牌生成过程中的薄弱环节,令牌的生成依赖于用户通过用户名/邮箱或密码生成,这里存在较大的泄漏风险;
  2. 所有处理会话令牌的薄弱环节,如传输过程中(没有加密的链路或被劫持等),日志记录中等。

4 存储内容

会话从本质上来讲是一种缓存,一种强关联用户的缓存,所以与用户相关的一些常用数据可以放在会话里面,如头像、用户名、真实姓名、积分等等。这些缓存数据都只读,当要更新时还是需要从数据库中获取后再次更新写入,而不是依赖于会话的数据。

除了常用数据我们经常还会把购物车或者菜单、权限等写入会话中,此时除了用户属性,还带上了业务属性,我们可以称之为业务会话。业务会话一般是指某个业务场景中需要临时缓存起来的数据,而且这部分数据大多数是要落库的,当用户会话过期重新登录后这部分数据还是要从数据库重新获取,加载到会话中。

5 小结

最后这个问题的原因是业务逻辑里面针对不同的渠道有抢登的业务逻辑,而这个逻辑在某个时候是不需要触发的。 此外,老板最后在群里问了一个触及灵魂的问题:

我们做一件事情的时候是依着惯性做事,还是基于深度思考后的决策?

自我反省中~~

这篇文章墨迹了几周,一直不知道如何写好,总觉得写得有点不如人意,如果往协议本身来写,好像也没有想写的,就这样吧。

6 参考资料

  • https://juejin.cn/post/6844904000811171847
  • https://www.cnblogs.com/lyzg/p/6067766.HTML
  • https://blog.csdn.net/tennysonsky/article/details/44562435

除了眼前的苟且,还有架构与远方。

介绍创业路上的技术选型和架构、大型网站架构、高性能高可用可扩展架构实现,技术管理等相关话题,紧跟业界主流步伐。

qrcode_for_gh_5d3f534e15fe_344 (1)

创业中的应用安全体系

1. 源起

在创业进程中,可能最开始我们会想着快速上线,一些性能、可用性或安全的问题是有时间就搞搞,没时间就放着;或者对于用户的一些异常行为,一些薅羊毛的行为没有特别的关注;又或者对于用户上传的个人资产没有做特别安全的隔离或保护等等。虽然现在看起来都没有引发大的问题,但是这些都是应用安全隐患,都是隐藏的雷,一旦被公众引爆,将惊天动地。

从更大的层面看应用安全,根据咨询公司 Gartner 统计数据显示,超过 75% 的安全攻击发生在代码应用层面。

Forrester 2020 年发布的调查报告 《 Forrester Analytics Global Business Technographics Security Survey,2020》中显示,在 480 家全球企业已经确认的外部攻击中, Web 应用程序和利用丢失/被盗资产,软件漏洞分别位于第1,2,4名,占比达到了 39%、35% 和 30%,其中软件漏洞主要指对于安全漏洞的利用攻击,攻击 Web 应用程序主要指基于程序的 SQL 注入、跨站脚本攻击、远程文件包含等。具体如图 1 所示:

从上图来看,应用安全,资源保护是目前我们安全防护的最佳切入点。

应用安全是应用级别的安全措施,旨在保护应用内的数据或代码免遭窃取和劫持。它涵盖了在应用开发、设计、测试、部署,上线后运营期间等发生的安全注意事项,及相对应的保护系统和方法。我们主要解决应用层和数据层的问题,网络层,物理层的问题不在本文的讨论范围之内。

从创业过程来看,我们有哪些数据泄漏的问题,我们有哪些敏感信息很容易被人看到,我们运营活动上线后有没有被薅羊毛,我们的用户里面有多少是机器注册的,我们的系统存在多少应用级漏洞,黑产是不是可以无门槛或门槛很低的获取到我们的数据或资源,我们的新业务上线时有没有东西能保证其是安全靠谱的,我们有没有办法及时发现这些问题并解决这些问题,从流程,机制,工具,系统各个层面,这就是我们这里所说的应用安全体系。

1.1 是什么

  • 是在部署常用防御工具和手段(比如防火墙、WAF 和 IDS 等)的基础上我们能做的流程、机制,工具、系统;
  • 是要在应用层面,去解决我们工作中经常会碰到的安全问题;
  • 是我们有意识的,主动的发现应用中的安全问题,发现用户的行为异常,业务异常,并给予解决。

1.2 不是什么

  • 不是公司的安全防御体系;
  • 不解决非技术安全相关问题;
  • 不解决所有的安全问题;
  • 不解决安全合规的问题;
  • 不解决超大规模类 DDoS 攻击的资源性攻击。

2. 安全问题梳理

这里我们从外部安全和内部安全来看可能面对的安全问题,外部是指对外的服务,内部是指企业内部的管理和控制,这里通过一些问题来反思现状。

外部安全
后台安全
    存储安全
        系统备份和恢复
            如果现在数据库被人删了,怎么办?如何快速恢复?
            如果现在代码全部被人删了或者 github 的账号完全不可用了,怎么办?如何快速恢复?
            如果现在阿里云的账号被封了,怎么办?如果有备用的账号,如何快速切换?
        配置存储
            如果配置中心挂了,有没有办法快速恢复?
            账号密码安全如何防护,代码配置中有吗?现在线上环境 apollo 的权限控制如何?
        MQ安全
            是否有必要的业务隔离?
            如果突破内网,是否有一定的鉴权逻辑?
    服务安全
        对外服务
            身份鉴权/访问控制
                用户资源安全(资产保护)
                    用户资源是否有访问鉴权?
                    用户资源或资产是否存在越权访问的情况?
            安全审计
                对用户的登录、注册和交易日志的审计
                对系统资源的异常使用的审计
                对重要系统功能的执行等的审计
                对其它重要用户行为的审计
            通信保密性
                传输通道加密
                内容加密
                传输加密(密钥是否存在漏洞的可能?)
            抗抵赖
                日志保留 6 个月
                操作详细流水日志
            容量安全
                各服务的 QPS 上限,容量评估
                资源消耗类服务的容量安全,是否存在很容易的攻击行为,如一些上传文件后的解析或者 AI 识别之类的
                MQ / DB 等是否有业务隔离和容量
            容错
                出错信息保护
                部分出错降级
        对内服务
            身份鉴权/访问控制
                服务间/接口访问控制
                服务间鉴权
                调用方身份识别
            抗抵赖
                详细调用日志
            应用生命周期的管理和隔离
            数据(包括用户数据)的管理和隔离
        安全框架
    资源安全
        商业化资源业务风控
        用户账号风控
        活动地址,接口地址,兑换码防穷举遍历
        在活动流程和规则上提高薅羊毛的门槛,形成规范
    数据安全
        数据量级泄漏
        业务数据泄漏
        敏感数据泄露
        防拖库、撞库
前台安全
    应用安全
        代码混淆
        应用加固
        安全密码控件
        敏感资料保护
        防代理
        常见 Web 攻击
            SQL 注入
            CSRF
            XSS
            爬虫
    接口安全
        SSL 加密传输
        参数加密
        防恶意调用,频控,降级
    账户安全
        身份验证
        登录验证码
        超时控制
        单点登录
        防信息泄漏 内部安全
管理后台安全
    严格且精细的权限控制
    商业化资源需要有审核流程,更细的权限控制,只能看到自己创建或者自己有权限的
    敏感信息(用户/订单/商业化)需要有针对敏感信息查阅的追溯手段和管控措施(是否考虑形成日报上报)
    对于钱相关的资源需要有监控和视图
代码和部署安全
    核心代码是否有专人管控
    上线的代码是否有必要的审核或 Review
    是否配置如同代码一样管控
    CI / CD 系统是否有必要的权限控制和安全管控
    CI / CD 流程是否实现自动化
    CI / CD 流程是否有必要的安全保护策略,如签名和密钥

如图 2 所示:

3. 如何建立应用安全体系

业界应用安全体系的建立有两主流方法论:一个是 SDL,另一个是 DevSecOps。

3.1 SDL 简介

SDL 是由微软最早提出的概念,安全开发流程(Security Development Lifecycle),在需求分析、设计、开发、发布所有阶段都引入安全和隐私原则,帮助解决软件安全问题,重点在于开发阶段,而安全培训是 SDL 最核心的概念。

SDL 大概流程如图 3 所示:

3.2 DevSecOps 简介

DevSecOps 是”开发、安全和运营”的缩写。它是一种文化取向、自动化方法和平台设计方法,将安全性作为整个 IT 生命周期的共同责任。 DevSecOps 的出现是为了改变和优化之前安全工作的一些现状,比如安全测试的孤立性、滞后性、随机性、覆盖性、变更一致性等问题;通过固化流程、加强不同人员协作,通过工具、技术手段将可以自动化、重复性的安全工作融入到研发体系内,让安全属性嵌入到整条流水线。

DevSecOps 是应用安全 (AppSec) 领域一个相对较新的术语,通过在 DevOps 活动中扩大开发和运营团队之间的紧密协作,将安全团队也包括进来,从而在软件开发生命周期的早期引入安全。这就要求改变开发、安全、测试、运营等核心职能团队的文化、流程和工具。基本上,DevSecOps 意味着安全成为共同的责任,而参与 SDL 的每个人都有责任在 DevOps CI/CD 工作流中构建安全。把安全融入到敏捷流程中,使得敏捷性与安全性并重。

DevSecOps 在软件开发生命周期更早期切入安全相关内容,就能更容易的收敛安全问题,让安全问题的解决成本更低,暴露在线上的完全问题更少。

DevSecOps 的过程有三个关键要素:

  • 授权(empowerment)
  • 赋能(enablement)
  • 教育(education)

授权或者放权,将控制权下放给团队,团队在理性分析的前提下,做出独立决定而不用害怕失败或影响。这里的团队成员不仅仅有开发,还有商务,产品,安全,QA 等等,所有项目成员都是奔着同一个目标:打造自己的产品。

赋能是指正确的使用掌握在团队手中的工具和资源,使其具体可操作性,如打造一种注重自动化、通过工具来解决重复任务,并尽可能减少以后的操作并增强安全性的理念。赋能不仅仅是提供知识和工具,而是让这种知识和工具能够通过多种渠道和媒介可快速获取且好用,以便它可以被团队或是个人以他喜欢的方式去使用和分享。

教育,在团队中建立安全文化,通过分享和培训让所有的成员都具备安全意识和技能是整个过程中最重要的点。

最终 DevSecOps 落地时,对整个研发团队的要求是这样的:

  • 安全测试由研发团队完成;
  • 测试期间发现的问题由研发团队管理;
  • 线上安全问题由研发团队负责处理;
  • 解决安全问题的责任在于研发团队。

3.3 选择适合自己的

SDL 相对于 DevSecOps 更偏于传统,如果要严格执行起来,其存在流程重、人员要求重等问题,一般是需要有专职的安全团队来执行。 但是要想直接达到 DevSecOps 的理想状态对于一个新创业的团队来说也是不现实的。

对于一个创业公司,可能需要更敏捷一些的方式,让敏捷性和安全性并重,所以我们更倾向于在 SDL 的基础上,融入部分 DevSecOps 的手段。

3.3.1 核心理念

  • 研发团队对安全负责,一切安全问题都是研发团队的问题,专门的安全团队只提供技术支持和技术培训(可以适当花钱请第三方专业机构),规避安全信息共享壁垒和在有专职开发团队时,开发绕过安全监管等情况;
  • 研发流程中全链条增加安全环节,安全不再是流程外的冗余流程,安全可以做轻,但是必须要有,特别是核心的逻辑,将安全前置;
  • 专职的安全团队从实战的角度,以攻击者的角度来发现问题,反馈给研发团队自己解决(提供标准解决方案),反向考核整个研发团队的安全绩效;
  • 建立高效的 SRC。

3.3.2 SDL 通用版

安全培训
| 安全概念、威胁评估、WEB 安全、安全测试及隐私保护
    提高全体项目人员的安全意识
    进行安全培训
需求分析
| 建立安全标准;创建安全指标;风险点评估
    确定安全需求标准,制定安全需求表,供后续开发检测
设计阶段
| 建立设计方案标准;提出安全方案;风险评估建模
    建立技术方案安全标准
    对不同的业务形态提出不同的安全方案
    建立风险评估模型
开发阶段
| 使用安全的工具、弃用不安全的函数或方法;静态扫描
    使用安全的工具:包括开发团队使用的编译器,框架,组件等
    弃用不安全的函数或方法
    | 安全规范编写代码,并在开发过程中对代码进行 Review
    静态分析
    | 对代码进行安全脆弱性分析和渗透性测试
测试阶段
| 动态安全扫描;模糊测试;评估安全方案
    动态分析(其实就是黑箱测试)- QA
    模糊测试
    | 故意向应用程序引入随机不良数据及格式,诱发程序产生故障。模糊测试的基础是必须了解熟悉程序的功能状态、设计规范等
    代码审计 - SRE
    | 代码安全扫描,开发过程中,开发人员每次更新代码都要进行扫描,并有权限查看相关项目漏洞情况,进行整改(不允许有中高危以上漏洞)。开发有权对漏洞进行忽略处理,但需要承担相应后果。若不知道如何处理,可请安全组提供解决方案。
    WEB 应用扫描 - QA
    人工渗透扫描 - 第三方专业安全团队
部署阶段
| 应急响应计划或预案;安全流程确认;发布归档
    明确安全应急响应计划
    构建发布流程工具卡点 AST 工具集
        静态应用安全测试 (SAST)
        软件组件分析 (SCA)
        交互式应用安全测试 (IAST)
        动态分析测试 (DAST)
    发布归档
线上阶段
| 执行线上应急响应流程
    第三方专业安全团队发现问题
    安全问题等级制度
    安全问题响应流程

脑图如图 5 所示:

3.3.3 我们现在可以做什么

在项目早期进行如下的投入是合适的,并且只需要开发同学的增量工作来保持良好的测试覆盖率和持续的构建

  • 单元测试和集成测试的覆盖范围要足够全面,以确保生产版本的缺陷风险低到可接受的程度,而不需要主要依赖人工进行的质检工作;
  • 本身安全可靠的 CI/CD 流水线;
  • 经常使用的、可靠的基础设施,可用于分开部署生产环境的回滚;
  • 允许代码和配置分开交付的软件架构,如配置中心。

应用安全是一个系统化的,长期的工程,对于现在的我们来说,不可能一次全链条都上,也不可能一次性的把大家的安全意识提到理想的水平。如何在保障业务快速发展的前提下,兼顾安全防护是当下我们需要考量的问题。

参照 SDL 通用版,建立较好的流程规范,安全问题等级制度和响应流程。有必要的话请第三方安全团队作为专职安全团队,定期对公司内外部做安全扫描,参照安全问题等级制度和响应流程,处理线上的问题,并且反向考核现有公司内部研发团队的安全绩效。同时研发团队在流程和意识上逐步增加安全卡点,提升开发过程中的安全质量,通过一些初步的安全工具链,快速自动识别安全问题。

4. 结语

以上纯属个人对现有应用安全的理解,供大家参考,有错误或不明确的地方欢迎指正,有更好的更完善的方法,欢迎评论探讨。

最近在看一本书,里面有一句守夜人的誓言:“若暗夜终临,吾必立于万万人之前,横刀向渊,血染天穹”,而安全于业务就是那个立于万万人之前的我们。

5. 参考资料

  • https://zhuanlan.zhihu.com/p/146149814
  • https://zhuanlan.zhihu.com/p/73675141
  • https://www.jianshu.com/p/ba886a6a28d8
  • https://cloud.tencent.com/developer/article/1587312
  • https://www.whitesourcesoftware.com/wp-content/media/2021/04/forrester-report-the-state-of-application-security-2021.pdf

 

除了眼前的苟且,还有架构与远方。

介绍创业路上的技术选型和架构、大型网站架构、高性能高可用可扩展架构实现,技术管理等相关话题,紧跟业界主流步伐。

qrcode_for_gh_5d3f534e15fe_344 (1)