Web 开发的安全问题

62 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情

xss 攻击

概念

xss 攻击指的是跨站脚本攻击,是一种代码注入攻击。攻击者通过在网站注入恶意脚本,使其在用户的浏览器上运行,从而盗取用户的信息,如 cookie 等。

本质

由于网站没有对恶意代码进行过滤,使其与正常的代码混合在一起了,但浏览器没有能力区分这些恶意代码,只能无条件执行。

特点

  • 通常难以从UI上感知(暗地执行脚本)
  • 窃取用户的敏感信息(cookie/token)
  • 绘制UI(比如弹窗),诱骗用户点击/填写表单

分类

xss 攻击可以分为反射型、存储型、DOM 型:

  • 反射型指的是攻击者诱导用户访问带有恶意代码的 url ,服务端接收数据后处理,将带有恶意代码的数据发送回浏览器,浏览器解析这段带有 xss 代码的数据后会将其当做脚本执行,以此完成 xss 攻击。
  • 存储型指的是恶意脚本会存储在服务器上,当浏览器请求数据时,这段恶意脚本会从服务器传回并执行。
  • DOM 型指的是攻击者修改网页的 DOM 节点而形成的 xss 攻击。

反射型 XSS 攻击

攻击步骤

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码执行攻击。

防御

对url的查询参数进行转义后再输出到页面(encodeURIComponent(url))。

DOM 型 XSS 攻击

攻击步骤

  1. 攻击者构造恶意代码。
  2. 浏览器执行恶意代码,将其插入 DOM 节点中并执行;
  3. 恶意代码执行攻击。

防御

  • 对于 url ,使用 encodeURIComponent 对输入内容进行转义
  • 对于非 url ,可使用如下函数编码:
    function encodeHtml(str) {
        return str.replace(/"/g, '"')
                .replace(/'/g, ''')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;');
    }
    

范畴:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞。

存储型 XSS 攻击

攻击步骤

  1. 攻击者将恶意代码提交到目标网站的数据库中;
  2. 所有用户在打开目标网站时,网站服务端将恶意代码从数据库中取出,拼接在 HTML 中返回给浏览器;
  3. 浏览器接收到响应后解析执行,同时也执行了恶意代码;
  4. 恶意代码发动攻击。

防御

  • 转义
    1. 前端数据传递给服务器之前,先转义/过滤(防范不了抓包修改数据的情况)
    2. 服务器接收到数据,在存储到数据库之前,进行转义/过滤
    3. 前端接收到服务器传递过来的数据,在展示到页面前,先进行转义/过滤
  • 限制
    1. 在服务端使用 HTTP 的 Content-Security-Policy 头部来指定策略:Content-Security-Policy: default-src 'self';或者在前端设置 meta 标签:<meta http-equiv="Content-Security-Policy" content="form-action 'self';">

    参考:Content-Security-Policy

    1. 限制输入内容的长度
    2. 限制输入的内容
  • 其他
    1. HTTP-only Cookie: 禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也无法窃取此Cookie。
    2. 验证码:防止脚本冒充用户提交危险操作。

使用场景:常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。

反射型 xss 与存储型 xss 的区别

  • 反射型作用范围小,仅局限于单体攻击对象;而存储型则是作用于操作到数据库的所有用户。
  • 反射型的恶意代码存在 url 里,而存储型的恶意代码存储在数据库里。

DOM xss 与前两种 xss 的区别

DOM 型 xss 攻击中,取出和执行恶意代码都由浏览器完成,属于前端 JavaScript 自身的安全漏洞;而其他两种 xss 攻击都是属于服务端的安全漏洞。

CSRF 攻击

概念

CSRF 攻击指的是跨站请求伪造攻击,攻击者诱导用户进入一个第三方网站,然后该网站向被攻击网站发送跨站请求,如果用户在被攻击网站中保存了登录状态,攻击者就可以利用这个登录状态绕过后台的用户验证,伪装成用户执行操作。

攻击步骤

  1. 受害者登录A站点,并保留了登录凭证(Cookie)。
  2. 攻击者诱导受害者访问了站点B。
  3. 站点B向站点A发送了一个请求,浏览器会默认携带站点A的Cookie信息。
  4. 站点A接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是无辜的受害者发送的请求。
  5. 站点A以受害者的名义执行了站点B的请求。
  6. 攻击完成,攻击者在受害者不知情的情况下,冒充受害者完成了攻击。

特点

  1. 攻击通常在第三方网站发起
  2. 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;并不会去获取cookie信息(cookie有同源策略)
  3. 跨站请求可以用各种方式:图片URL、超链接、CORS、Form提交等等(来源不明的链接,不要点击)

常见的 CSRF 攻击有三种

  • GET 类型的 csrf 攻击:比如在网站中的一个 img 标签里构建一个请求,在用户打开这个网页时就会自动提交。
  • POST 类型的 csrf 攻击:比如构建一个表单,然后隐藏它,在用户进入页面时,就会自动提交这个表单。
  • 链接类型的 csrf 攻击:比如在 a 标签的 href 属性里构建一个请求,然后诱导用户去点击。

防御措施

  • 添加验证码
    • 体验不好
  • 检测 Referer 判断请求的来源
    • 不安全,Referer 可以被更改
  • 使用加密 Token
    • 服务端给用户生成一个token,加密后传递给用户
    • 用户在提交请求时,需要携带这个token
    • 服务端验证token是否正确
  • Cookie 添加 Samesite 属性
    • 部署简单,并能有效防御CSRF攻击,但是存在兼容性问题。

为了更好的防御 CSRF 攻击,我们可以组合使用以上防御手段。