Web 开发的安全之旅 | 青训营笔记

110 阅读6分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 12 天

攻击篇

跨站脚本攻击 Cross-Site Scripting(XSS)

这是最常见的一种攻击方式,在页面中,攻击者通过注入恶意脚本,当用户访问页面时,恶意脚本就会被执行,从而完成攻击,使用户的隐私被泄露。

XSS主要利用了:

  • 开发者盲目信任用户的提交内容
  • 开发者直接把用户提交的字符串转化成了DOM

XSS攻击的一些特点

  • 通常难以从UI上感知(暗地执行脚本)
  • 切勿用户信息(cookie/token)
  • 绘制UI,诱骗用户点击/填写表单

XSS攻击按性质分类

  • Stored XSS 存储型XSS攻击

    • 恶意脚本被存在数据库中
    • 访问页面 + 读数据 = 被攻击
    • 危害最大,对全部用户可见
  • Reflected XSS 反射型XSS攻击

    • 不涉及数据库
    • 从URL上攻击
  • DOM-based XSS 基于DOM的XSS攻击

    • 不需要服务器的参与
    • 恶意攻击的发起和执行全在浏览器完成
  • Mutation-based XSS 基于变种的XSS攻击

    • 利用了浏览器渲染DOM的特性(独特优化)
    • 不同浏览器会有区别(按浏览器进行攻击)

跨站伪造请求 Cross-site request forgery

跨站伪造请求有如下几个特点:

  • 在用户不知情的前提下
  • 利用用户权限 (如cookie)
  • 构造指定HTTP请求,窃取或修改用户敏感信息

假设用户点击了一封陌生邮件中的网站链接,进入了一个恶意的页面,攻击者在其中构造了一个HTTP请求,向银行发起转账请求,而这个请求是在另一个域名,当银行系统接收到这个请求,发现请求中包含用户的cookie,且cookie验证通过,就会认为这是一个合法的用户请求,于是执行这个转账接口,用户就丢失了一笔财产。

跨站伪造请求最常见的是GET请求,通过伪造链接或背景图片,只要用户点击链接或图片被加载,就能够发起GET请求。

Injection 注入

假设一个HTTP请求中带有恶意注入的SQL参数,然后这条请求到达了服务器端,服务端从参数中读取到了SQL语句,进而执行SQL代码,从而达到获取其他数据、修改数据甚至删除数据的目的。

注入其实并不局限于SQL注入,还有诸如:

  • CLI

  • OS Command

  • Server-Side Request Forgery(SSRF) 服务端伪造请求

Denial of Service(DoS) 服务拒绝

通过某种方式(构造特定请求),导致服务器资源被显著消耗,来不及响应更多请求,导致请求挤压,进而引发雪崩效应。

  • ReDos:利用正则表达式,通过构造容易发生回溯行为的字符串,导致服务器响应时间大大延长,响应用户请求的次数大大下降。
  • DDoS:短时间内,来自大量僵尸设备的请求流量,服务器不能及时完成全部请求导致请求堆积,进而雪崩效应,无法响应新请求。

基于传输层的攻击方式

中间人攻击

客户端与服务端双方都认为自己在与对方通信,但事实上在二者之间存在一个中间人,于是中间人便能够完成窃取信息、修改请求或返回值等操作。

中间人攻击发生的原因:

  • 数据明文传输
  • 当传输的信息被篡改时,浏览器和服务器都不知道
  • 服务器和浏览器都没有对对方的身份进行任何验证

防御篇

防御XSS攻击

  • 永远不要信任用户的提交内容
  • 不要将用户提交的内容直接转换成DOM

也有一些现成的工具可以帮助我们防御XSS攻击:

  • 前端

    • 主流的前端框架都默认防御XSS
    • google-closure-library
  • 服务端 (Node)

    • DOMPurify

但是,如果有一些需求必须要动态生成DOM,那么将String转换成DOM的时候必须对String进行转译;如果用户上传了svg图片,由于svg格式规范中允许插入script标签,所以必须对整个svg文件进行扫描;尽量不要做让用户自定义跳转的链接,在必要时要做好过滤,因为允许自定义跳转链接就意味着允许传递js代码。

此外,如果允许用户自定义样式,也有可能导致XSS攻击,当用户选中某个选项时发送了GET请求,就容易暴露选项中包含的信息,所以对于自定义样式中能够设置图片属性或URL属性的位置,开发者需要特别留意。

内容安全策略 Content Security Policy(CSP)

线简单回顾一下SOP(Same-Origin Policy)即同源策略,这是存在于浏览器中的一个规定,源要确保两个URL上的协议、域名、端口都保持一致。

那么CSP能够允许开发者来定义:

  • 哪些源(域名)被认为是安全的
  • 来自安全源的脚本可以执行,否则直接报错
  • 拒绝执行 eval + inline script

CSRF的防御

  • 在服务端对origin和referer进行校验
  • 通过设置token来判断请求是否来自于合法来源
  • 通过在iframe中设置button的方式,用户对button的点击可以被传递到iframe中,从而可以导致同源攻击。对于这种攻击方式,可以设置X-Frame-Options响应头来规避这种攻击方式。
  • 不要为了方便而将GET实现成GET+POST
  • 避免用户信息被携带 Same Site Cookie

防御注入攻击

  • 找到项目中查询SQL的地方
  • 使用 prepared statement

其他注入攻击的防御

  • 最小权限原则

    • 所有的命令都不要使用sudo来执行或给予root权限
  • 建立白名单+过滤,只允许指定的命令被执行

  • 对URL类型参数进行协议、域名、IP等协议进行限制

    • 以免内网资源被访问
  • ReDoS

    • 减少允许用户使用正则表达式请求
    • 增加校验, 对代码做扫描 +正则性能测试
  • L-DoS

    • 限流: 限制流量的异常波动,对于异常IP封锁。
    • 并不是非黑即白: 有时候需要请求量超过阈值才能检测出L-DoS
    • 分析代码的性能瓶颈:同步调用、串行逻辑、CPU密集操作
  • DDoS

    • 过滤:负载均衡、API网关

    • 抗量:CDN、快速扩容、 非核心服务降级

推荐读物