在前端开发的教程中我们做了个重要断言:“一切前端安全措施都是纸老虎”,因此在实施后端系统安全措施时必须加倍用心。确保后端系统的安全性,不仅时系统工程师的责任,每个项目经理和开发工程师也都应该了解相关的知识并且在设计开发的过程中融汇贯通。

274.1 最严重的Web 应用程序安全风险

Open Web Application Security Project (OWASP) 维护了一个 最严重的10个 Web 应用程序安全风险(OWASP Top 10) 清单。它是开发人员和Web应用程序安全性的标准意识文档,代表了关于web应用程序最关键的安全风险的广泛共识。Web 软件系统建设者应对照这个清单进行检查,并且确保将这些风险降至最低。

  1. A01:2021-Broken Access Control
    94% 的应用程序被测试到存在某种形式的损坏的访问控制。映射到损坏的访问控制的34个常见弱点枚举 (CWEs) 在应用程序中的出现次数比任何其他类别都多。

  2. A02:2021-Cryptographic Failures
    又被称为敏感数据曝光,这是广泛的症状,而不是根本原因。这是与加密相关的故障,这些故障通常会导致敏感数据泄露或系统受损。

  3. A03:2021-Injection
    对94% 的应用程序进行了某种形式的注射测试,并且映射到该类别的33个CWEs在应用程序中出现次数第二多。跨站点脚本(XSS)现在在此版本中属于此类别。
  4. A04:2021-Insecure Design
    这是2021年的新类别,重点是与设计缺陷相关的风险。它需要更多地使用威胁建模、安全设计模式和原则以及参考架构。
  5. A05:2021-Security Misconfiguration
    90% 的应用程序被测试了某种形式的错误配置。随着更多向高度可配置软件的转变,看到这一类别上升并不奇怪。XML外部实体 (XXE) 的前一个类别现在是该类别的一部分。
  6. A06:2021-Vulnerable and Outdated Components
    以前被命名为使用具有已知漏洞的组件,是一个我们很难测试和评估风险的已知问题。。
  7. A07:2021-Identification and Authentication Failures
    以前是损坏的身份验证,现在包括与识别失败更相关的CWEs。规范地使用标准化框架有助于解决这个问题。
  8. A08:2021-Software and Data Integrity Failures
    这个问题侧重于在不验证完整性的情况下做出与软件更新、关键数据和CI/CD管道相关的假设。公共漏洞和暴露/公共漏洞评分系统 (CVE/CVSS) 数据映射到此类别中的10个CWEs的加权影响最高之一。
  9. A09:2021-Security Logging and Monitoring Failures
    之前的问题日志记录和监控不足,现在已扩展为包括更多类型的故障,测试它比较具有挑战性,并且在CVE/CVSS数据中没有很好地表示。但是,此类故障会直接影响可见性、事件警报和取证。
  10. A10:2021-Server-Side Request Forgery
    这个问题的出现比率相对较低,但测试覆盖率仍旧高于平均水平,开发和影响潜力评级高于平均水平。

上面只是列出这些风险的简要说明,由于英文原文非常拗口,很难精准的翻译。所以这对这些风险的描述和他们的详细解释请直接访问 OWASP Top 10 网站。

27.2 后端开发工程师的安全职责

软件系统的信息安全大致可以分为两个方面:

  1. 私密性:资料不被非法获取和利用,只有授权才可以利用。
  2. 可靠性:资料不丢失、不损坏、不被篡改。

与安全保护的工作主要分布在架构设计、代码实施和运维管理方面。其中后端开发工程师主要承担代码实施方面的的安全工作,同时 也应该参与架构设计相关的信息安全保护工作。

27.2.1 后端开发工程师应该做什么

下面时后端开发工程师需要承担的安全职责:

  1. 设计实施严谨的用户认证过程。
  2. 设计实施全面的授权及鉴权过程。
  3. 记录足够完整的访问和异常信息。
  4. 采用国密算法进行信息加密解密。
  5. 深刻理解个人隐私保护方面的法规、标准和技术措施。
  6. 了解电子政务和信息安全等级保护对软件设计的要求。
  7. 了解国家密码管理部门对商用密码的技术要求。
  8. 理解系统架构设计师和运维工程师做出的安全设计并提出自己的见解。

    27.2.2 后端开发工程师不必做什么

    以下内容不是后端开发工程师工作中需要考虑的:

  9. 操作系统及系统软件的安全管理。

  10. 网络路由、交换及各种安全设备的安全管理。
  11. HTTP协议以下层次协议的安全管理。
  12. 虑数据库审计、内容防篡改等透明安全机制。
  13. 对DDOS、SYN 等网络攻击的防御。

    27.3 与设计相关的后端安全防护

    27.3.1 使用 HTTPS

    不加密前端和后端 Web 应用程序之间的通信是有风险的。由于HTTP是一个不加密的明文传输协议。攻击者可以通过使用中间人攻击来窃取或更改你的前端和后端之间的通信,这种攻击形式可以监视两个系统之间的通信,然后窃取敏感数据或者实施中间人攻击。

苹果公司 2016 年在 WWDC 上宣称,公司希望官方应用商店中的所有 iOS App 都使用安全的 HTTPS 链接与服务器进行通信。Google Chrome 则在18年七月份已经将所有的 HTTP 网站标记为“不安全”。并且已经有越来越多的第三方服务开始推荐甚至是强制要求使用 HTTPS 连接方式。

HTTP 协议是客户端浏览器或其他程序与 Web 服务器之间的应用层通信协议,它是一种不加密的明文传输。而HTTPS 协议的安全基础是 SSL(Security Sockets Layer), SSL是具有防止窃听、篡改和冒充功能的加密通信协议。因此在 Web 应用系统中必须使用 HTTPS。

27.3.2 防止 SQL 注入

所谓 SQL 注入,就是是利用应用程序的漏洞,将恶意 的 SQL 命令注入到后台数据库引擎执行的。比如攻击者可能会通过在 Web 表单中输入SQL 语句片段作为查询内容,导致有漏洞的后端应用程序形成有恶意的查询语句,进而实施攻击或越权访问数据。

后端开发做 SQL 保护至少要坚持以下的原则:

  1. 永远不相信前端的安全防护措施。这个是首要的原则。
  2. 永远不要信任用户的输入。必须在后端对用户的输入内容进行校验和编码,可以通过正则表达式、限制长度、对单双引号进行转换等。
  3. 永远不要使用动态拼装 SQL。应该使用参数化的 SQL 进行数据查询存取(不要使用会增加迁移代价的存储过程)。
  4. 永远不要使用管理员权限的数据库连接。必须为每个应用使用单独的、权限有限的用户进行数据库连接。
  5. 永远不要把机密信息直接存放。应该使用对称或摘要密码算法加密处理用户密码及敏感信息。

    27.3.3 防御 CSRF 攻击

    CSRF(Cross-site request forgery)通常翻译为跨站请求伪造。

这种攻击方式可以简单理解为:攻击者盗用身份,以假冒名义发送恶意请求。显然,成功的 CSRF 攻击会造成个人隐私泄露甚至于财产的损失。

CSRF 攻击点源于Web系统的身份验证过程——Web 的身份验证机制虽然可以保证一个请求是来自某个用户的浏览器,但无法保证该请求是经过用户批准发送的。

服务器端防御 CSRF 攻击通常有如下的措施:

  1. 关键操作只接受 POST 请求。
  2. 检查标准头部确认请求是否同源: 检查 source origin 和 target origin,然后比较两个值是否匹配。
  3. 检测 HTTP 请求的 Referer 属性
    发往新页面 HTTP 请求的Referer 属性保存前一页面的地址。通常检查 Referer 的值可以判断这个请求是否喝法。不过由于服务器不是任何时候都接受到 Referer 的值,所以检查 Referer 的手段一般用于监控是否发生 CSRF 攻击而不用来抵御攻击。
  4. 登录过程要求动态验证码
    CSRF 攻击的过程往往是在用户不知情时被构造网络请求。使用动态验证码会要求用户必须参与互动,从而能够简单有效地防御 CSRF 攻击。当然,在发出每个请求时都要求输入验证码是不现实的,所以验证码一般只出现在特殊操作环节,比如用户注册、登录、修改密码重要信息、执行转账等要求高安全登记的动作等。
  5. 在请求中携带令牌(Token)
    使用令牌(Token)是防御 CSRF 攻击的主流作法。CSRF 攻击成功的条件在于攻击者能够准确地预测所有的参数从而构造出合法的请求,所以增加不可预测的内容能够有效防御 CSRF 攻击(因为攻击者无法伪造出合法的请求)。具体的作法是在请求中添加一个随机内容作为Token 参数,通常有如下几种方法

    • Synchronizer Tokens: 在表单里隐藏一个随机变化的 token,每当用户提交表单时,将这个 token 提交到后台进行验证,如果验证通过则可以继续执行操作。
    • Double Cookie Defense: 当向服务器发出请求时,生成一个随机值,将这个随机值既放在 cookie 中,也放在请求的参数中,服务器同时验证这两个值是否匹配;
    • Encrypted Token Pattern: 对 Token 进行加密
    • Custom Header: 使用自定义请求头部,这个方式依赖于同源策略。其中最适合的自定义头部便是: “X-Requested-With: XMLHttpRequest”

    在这个过程中应遵循以下的原则:

    1. Token 要足够随机,使攻击者无法准确预测
    2. Token 是一次性的,即每次请求成功后要更新 Token,增加预测难度
    3. Token 要主要保密性,敏感操作使用 POST,防止 Token 出现在 URL 中。
    4. 如果加密,那么应该是在客户端使用非对称密码算法中的公钥加密,只有服务器端可以用私钥解密。

最后值得注意的是,过滤用户输入的内容不能阻挡 CSRF 攻击,我们需要做的是过滤请求的来源,因为有些请求是合法,有些是非法的,所以 CSRF 防御主要是过滤那些非法伪造的请求来源。

27.3.4 防御 XSS 攻击

XSS(Cross Site Script) 通常翻译为跨站脚本攻击,这个缩写是为了防止与定义页面风格的 CSS(Cascading Style Sheets)混淆。

这种攻击方式的原理是攻击者向有 XSS 漏洞的网站中输入恶意的脚本 代码,当其它用户浏览该网站时候,该段 代码会自动执行,从而达到攻击的目的,如盗取用户的 Cookie,破坏页面结构,重定向到其它网站等。理论上,任何没有对输入内容进行处理的地方都会存在 XSS 漏洞,而漏洞的危险取决于攻击代码的威力,攻击代码也不局限于执行脚本。

XSS 主要有三种类型:

  • 存储型 XSS: 注入的脚本永久的存在于目标服务器上,每当受害者向服务器请求此数据时就会重新唤醒攻击脚本;
  • 反射型 XSS: 当用受害者被引诱点击一个恶意链接,提交一个伪造的表单,恶意代码便会和正常返回数据一起作为响应发送到受害者的浏览器,从而骗过了浏览器,使之误以为恶意脚本来自于可信的服务器,以至于让恶意脚本得以执行。
  • DOM 型 XSS: 有点类似于存储型 XSS,但存储型 XSS 是将恶意脚本作为数据存储在服务器中,每个调用数据的用户都会受到攻击。但 DOM 型 XSS 则是一个本地的行为,更多是本地更新 DOM 时导致了恶意脚本执行。

相比之下,存储型 XSS 的攻击影响力最大,清除的难度也最大。

防御 XSS 攻击最简单直接的方法就是过滤用户的输入,包括验证输入内容的格式、执行转义编码,以及设置HTTP Header: “X-XSS-Protection: 1”。

需要说明的是,如果允许用户输入 HTML 代码的时候,仅仅粗暴地去掉 Script 标签是没有用的,因为任何一个合法 HTML 标签都可以添加 onclick 一类的事件属性来执行 JavaScript 代码。更好的方法可能是,将用户的输入使用 HTML 解析库进行解析,获取其中的数据。然后根据用户原有的标签属性,重新构建 HTML 元素树。构建的过程中,所有的标签、属性都只从白名单中拿取。

27.3.5 不要泄露技术信息

如果服务器返回的提示或错误信息中出现服务器版本信息、程序出错泄露物理路径、程序查询出错返回SQL语句、给出过于详细的用户验证或其他操作的结果信息,有可能被攻击者利用做有针对性的攻击。所以后端给前端反馈的信息应该是友好且和技术细节无关的。比如不能告知用户登录失败是因为用户不存在还是密码错误,这就是一个非常重要的安全原则。

27.3.6 使用增强型的密码加密技术

密码加密算法的选择、密钥的保存与更新,这些都是影响密码加密效果的重要严肃。数据加密的常见的问题是密钥生成和储存不安全、不轮换密钥,和使用弱算法等。另外,使用密码加密技术也存在合规问题。所有的政务类应用软件或者面临信息安全等级保护评测的软件必须使用国密算法进行加密解密。

27.3.7 不使用过时的软件组件

一个 Web 应用程序由 多个保持其运行的软件组件组成。每个组件在 Web 应用程序的成功运行中都扮演着独特的角色。单个组件的漏洞暴露了应用程序中的其他组件。你需要优先考虑 Web 应用程序每个组件的安全性,因为过时或生命周期结束的软件很容易出现风险。网络攻击者部署高级工具来在线搜索过时的软件以进行攻击。确保你的 Web 应用程序的所有组件都更新到其最新版本,以减少它们受到攻击的脆弱性。

27.3.8 防止暴露敏感数据

为了增强你网站上的用户体验,你的 Web 应用程序可能会将用户生成的某些信息或数据存储在临时位置。对此类数据的访问应该仅限于相关用户。但是,如果存储信息的文件夹安全性不高,黑客可能会未经授权访问存储信息的文件夹并将数据用于他们的私利。

27.4 总结

软件系统的安全永远只是相对的,没有绝对的安全。安全性与易用性、与投入成本始终是成反比的。但对于软件系统的设计、建设和维护者来说,信息安全始终是要放在第一位考虑的事情。尤其对于政务系统来说,“安全问题”具有“一票否决”权的。

版权说明:本文由北京朗思云网科技股份有限公司原创,向互联网开放全部内容但保留所有权力。