前端安全之防范XSS

时间: 2020-05-01阅读: 90标签: 安全
由于前段时间业务有接触到富文本编辑器,且编辑器由用户直接使用,所以不可避免需要对其涉及到的XSS防护有所了解,因此对XSS防护做一个实战小结。



前言

XSS大部分前端coder都不会陌生,全称:跨站脚本漏洞(Cross Site Scripting,简写作XSS)是Web应用程序在将数据输出或者展示到网页的时候存在问题,导致攻击者可以将对网站的正常功能造成影响甚至窃取或篡改用户个人信息,其诱发的主要原因是没有针对用户输入来源的数据以及不可信数据源的过滤。本文将针对XSS进行简单的归类总结,并且提供相关的实战处理手段。


一、XSS 类型划分

对于常见的XSS攻击方式,大部分人再熟悉不过了,这里再帮大家复习一下。

1、反射性XSS:常见情况是攻击者通过构造一个恶意链接的形式,诱导用户传播和打开,由于链接内所携带的参数会回显于页面中或作为页面的处理数据源,最终造成XSS攻击。

2、存储型XSS:与前者不同,存储型XSS是持久化的XSS攻击方式,通过用户输入个人信息或者发表文章的方式将恶意代码存储于服务器端,当其他用户再次访问页面时触发,造成XSS攻击。

3、DOM based型XSS:同样也是利用对数据源不可靠,缺乏过滤,由于开发过程中,不可避免部分数据需要回填到DOM中,例如href、src、>二、XSS防范手段

针对XSS的防范,需要开发者养成意识,针对用户输入源的数据进行过滤,针对页面不可信任的数据源也要做好过滤,类似于响应头中的字段、url中的参数、refer等字段都是不可信的,并且结合其他手段和方法,让页面更加安全可控。

1、Htmlencode转义特殊字符

大部分的论坛或者博客平台,注册账号都会允许用户填写个人信息,包括昵称、邮箱和个性签名等,此类文本信息属于非富文本类型,最常见的方法就是对尖括号标签转义成实体字符存储,由于是非富文本信息,并且以标签内容的形式展示,如果不使用框架渲染,直接原生JS通过docoment.getElementById('xxx').innerText = 'your name'展示回页面中即可。

常见的处理方式如下:

const htmlEncode = function (handleString){
    return handleString
    .replace(/&/g,"&")
    .replace(/</g,"&lt;")
    .replace(/>/g,"&gt;")
    .replace(/ /g,"&nbsp;")
    .replace(/\'/g,"&#39;")
    .replace(/\"/g,"&quot;");
}

2、引入XSS库针对用户输入源过滤,设置标签白名单

前面说明了在非富文本的情况下较为快捷方便的处理方法,然而在大部分论坛中发帖发文章都是富文本编辑的形式,即最后回显于页面中的是一段HTML内容,不能单纯以文本形式处理。

大部分的富文本编辑器原理,都是提供一个具备contenteditable属性的dom元素,让用户对一段富文本进行编辑,其本质是对一段html进行处理,新增或删除样式等,最后通过回传富文本框中html的方式提供给开发者,意味着我们要允许用户填充一段html于我们的页面中。而获取到的html字符串我们不能直接进行简单的标签替换,否则会导致原有的样式丢失,最终展示在页面中的也不再是一篇排版精致的文章,因此我们要另寻他路。

首先需要明确的是,无论是这份来自于富文本编辑器的html,还是来自于最终用户发起请求所获取到的html,都是不可信的,意味着在前端进行过滤是没有任何实际意义和价值的,因为攻击者可以轻易的伪造请求绕过限制,所以我们需要在我们的服务器端针对这段html进行过滤处理。针对html的标签白名单过滤,不同的语言有不同的库实现,这里主要介绍nodejs中常用的标签过滤库,nodejs中常用的库主要是xss和xss-filter,下面以xss库的使用为例:

import * as xss from 'xss';
function handleXss(content: Content) {
  // 设置HTML过滤器的白名单
  const options = {
    whiteList: {
      p: ['class', 'style'],
      em: ['class', 'style'],
      strong: ['class', 'style'],
      br: ['class', 'style'],
      u: ['class', 'style'],
      s: ['class', 'style'],
      blockquote: ['class', 'style'],
      li: ['class', 'style'],
      ol: ['class', 'style'],
      ul: ['class', 'style'],
      h1: ['class', 'style'],
      h2: ['class', 'style'],
      h3: ['class', 'style'],
      h4: ['class', 'style'],
      h5: ['class', 'style'],
      h6: ['class', 'style'],
      span: ['class', 'style'],
      div: ['class', 'style'],
      img: ['src', 'class', 'style', 'width'],
    },
  }; 
  // 自定义规则
  const myxss = new xss.FilterXSS(options);
  // 直接调用 myxss.process() 即可
  content.content = myxss.process(content.content);
  return content;
}

通过限定白名单,仅允许常见的文本展示标签以及图片img标签进入白名单,这部分会再过滤后被保留,并且标签内的class和style属性也会被保留;其他属性和诸如script、iframe等标签都会被直接过滤掉。 

这里为何要严格限定标签的以及属性的原因,例如一个a标签可以通过href属性注入一段类似这样的js代码:

<a href\="javascript:alert('xss')"\>click me</a\>

更有甚者会对注入的字符进行大小写字符转换,或转义成等效字符,或插入空格或tab,但脚本仍然能正常运行,造成攻击。

<p onclick="alert('xss')">this is a text</p>
<img src="xxx.com/test.jpg" onerror="alert('xss')"/>

其次,普通的标签可以直接通过绑定onclick的方式攻击,即便是img、video等资源加载标签,也可以通过onload、onerror等事件注入脚本,可见针对标签内属性的过滤也是不可或缺的。

然而本以为这样已足够,但是即使是只开放了class和style属性开放了,也是不安全的,关键在于style属性,如果任由用户自定义的话,可以通过style属性实现:点击劫持(将元素铺满整个界面)、加载外域图片、脚本注入甚至可以给文章设置一些花里胡哨的动画:

<div style="position:absolute;top:0;left:0;width:2000px;height:2000px;z-index:9999;">
点击劫持的元素,阻止页面其他操作</div>

<div style="background:url(javacript:alert('xss'))">
借助style标签注入脚本,大部分xss过滤库会帮我们过滤这部分脚本</div>

<div style="background:url(//xxx.com/H图.jpg)">
偷偷加载其他网站的小H图,绕过过滤和审核</div>

可见style属性也不容忽视,因此我们需要在option参数中额外为style属性设置白名单,确保style属性安全可控:

...
   css: {
      whiteList: {
        color: true,
        'background-color': true,
      },
    },
...

其次为了确保不加载非本域名下的图片资源,我们也可以再这一层做一些针对img标签的过滤:

    ...
    stripIgnoreTag: true,
    onTagAttr: (tag:string, name:string, value:string, isWhiteAttr:boolean) => {
      // 判断img下的src属性 如果非本域名下 返回空
      if (isWhiteAttr && tag === 'img' && name === 'src' && !checkLegal(value)) 
      {
        return '#';
      }
    },
    ...

3、cookie设置HttpOnly,配合token或验证码防范

针对信息源的过滤,针对不可信数据源的过滤,已经能达到初步的效果,但这远远不够,毕竟没有绝对的安全。

由于大部分攻击者会想要获取到用户的cookie去做别的坏事,所以我们需要在http的响应头set-cookie时设置httpOnly,让浏览器知道不能通过document.cookie的方式获取到cookie内容。

app.get('/', (req, res) => {
    if(req.cookies.isVisit) {
        console.log(req.cookies)
        res.send('欢迎再次光临')
    } else {
        res.cookie('isVisit', 1, {maxAge: 3600 * 1000, httpOnly: true}) 
        res.send('欢迎初次光临')
    }
})

虽然避免了攻击者直接获取到cookie,但是攻击者仍然可以页面内发起别的请求,直接篡改用户的信息,因此需要我们配合token或者验证码的形式,防止攻击者直接通过脚本的方式篡改用户个人信息。而这个token类似于CSRF中我们所需要的token,不过如果攻击者仔细研究了代码,并且知道的token在页面中的来源,也是可以直接获取到token的,因此,相比之下验证码安全性更高。

4、设置CSP安全策略

除了针对数据源的严格过滤以外,CSP安全策略的限制也是主要的XSS防范手段之一,通过在页面中设置允许加载的资源的来源,来严格限制页面可加载的脚本以及图片等资源,防止外部的脚本攻击后注入其他脚本以及内容。

CSP,内容安全策略,是一种基于内容的声明式网络应用程序机制,对缓解内容注入漏洞的危害非常有效。通过一系列指令告诉客户端(如浏览器)被保护资源(如页面)内只允许加载和执行指令集中限定的内容,类似白名单机制,不满足限定条件的资源和内容将被客户端阻断或不被执行。可以通过两种方式设置CSP,一种是meta标签,一种是HTTP响应头Content-Security-Policy:

指令及其说明:
default-src 定义资源默认加载策略
connect-src 定义Ajax、 WebSocket等加载策略
font-src 定义Font 加载策略
frame- src 定义Frame加载策略
img-src 定义图片加载策略
media- src 定义<audio>、 <video> 等引用资源加载策略
object-src 定义 <applet>、 <embed>、 <object> 等引用资源加载策略
script-src 定义JS加载策略
style- src 定义CSS加载策略

对应的指令value可以设置为:(图片引自:https://www.jianshu.com/p/4bad03d89c04

相信聪明的你看了这个规则一看就懂了,接下来,以meta标签设置CSP为例,我们可以如下设置,以此来限制对白名单外资源加载:

<meta http-equiv="Content-Security-Policy" content=
    "script-src 'self' *.qq.com *.cdn-go.cn; 
    img-src 'self' *.cdn-go.cn *.gtimg.cn data:;
    style-src 'unsafe-inline' *.cdn-go.cn; 
    media-src 'none'; 
    child-src *.qq.com">

5、其他HTTP安全响应头设置

除了CSP这个最常用最强势的限制规则外,还有其他的HTTP安全响应头,如果心情好的话,可以统统整上(滑稽):

1)、X-Frame-Options:X-Frame-Options HTTP 响应头是用来给浏览器指示允许一个页面可否在 <frame>, <iframe>或者 <object> 中展现的标记。网站可以使用此功能,来确保自己网站的内容没有被嵌到别人的网站中去,也从而避免了点击劫持 (clickjacking) 的攻击。
X-Frame-Options 有三个值:

DENY
表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。
SAMEORIGIN
表示该页面可以在相同域名页面的 frame 中展示。
ALLOW-FROM uri
表示该页面可以在指定来源的 frame 中展示。

2)、X-Content-Type-Options:X-Content-Type-Options 响应首部相当于一个提示标志,被服务器用来提示客户端一定要遵循在 Content-Type 首部中对 MIME 类型 的设定,而不能对其进行修改。这就禁用了客户端的 MIME 类型嗅探行为,(类型嗅探指的是浏览器在加载资源时,自动嗅探资源类型过程中,导致执行了注入脚本),换句话说,也就是意味着网站管理员确定自己的设置没有问题。

3)、X-XSS-Protection:当检测到跨站脚本攻击 (XSS)时,浏览器将停止加载页面。

然而这个响应头由于只有IE、谷歌等少部分浏览器支持,且不同浏览器的实现不一致,存在错误过滤行为,甚至可能导致带额外的漏洞,所以在实际情况中较少使用。(为避免错误过滤,部分门户网站会将其值设置为0)

X-XSS-Protection: 0
X-XSS-Protection: 1
X-XSS-Protection: 1; mode=block
X-XSS-Protection: 1; report=<reporting-uri>
0禁止XSS过滤。
1启用XSS过滤(通常浏览器是默认的)。 如果检测到跨站脚本攻击,浏览器将清除页面(删除不安全的部分)。
1;mode=block启用XSS过滤。 如果检测到攻击,浏览器将不会清除页面,而是阻止页面加载。
1; report=<reporting-URI> (Chromium only)启用XSS过滤。 如果检测到跨站脚本攻击,浏览器将清除页面并使用CSP report-uri指令的功能发送违规报告。

以推特网站为例,其设置的响应头如下:
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 0


三、总结

本文主要总结归纳了实践过程中针对XSS漏洞的防护措施,首先针对用户输入源和不可信数据源需要我们做好必要的过滤和校验,其次,通过CSP安全策略和其他HTTP响应头的设置等进一步确保安全性。

只有综合多种手段和方法才能确保自己的网站更加安全,如果不安全,那么就删git仓库跑路。

来自:https://segmentfault.com/a/1190000022678120

站长推荐

1.阿里云: 本站目前使用的是阿里云主机,安全/可靠/稳定。点击领取2000元代金券、了解最新阿里云产品的各种优惠活动点击进入

2.腾讯云: 提供云服务器、云数据库、云存储、视频与CDN、域名等服务。腾讯云各类产品的最新活动,优惠券领取点击进入

3.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/9064

前端开发人员的10个安全建议

Web安全是前端开发人员经常忽略的主题。当我们评估网站的质量时,我们通常会查看性能,SEO友好性和可访问性等指标,而网站抵御恶意攻击的能力却常常被忽略。即使敏感的用户数据存储在服务器端

前端安全之xss攻击

XSS 攻击指通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的代码。危害有什么?跳转到广告页面,页面注入广告等等。导致公司域名被其他平台拉黑,从而使业务受损。

浅谈前端安全

将Web安全问题按照发生的区域来分类,发生在浏览器、Web页面中的安全问题就是前端安全问题。同源:URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示他们同源。

十大开源Web应用安全测试工具

Web应用安全测试可对Web应用程序执行功能测试,找到尽可能多的安全问题,大大降低黑客入侵几率。在研究并推荐一些优秀的开源Web应用安全测试工具之前,让我们首先了解一下安全测试的定义、功用和价值。

web安全方案

完善的内容安全策略(CSP)是前端应用程序安全的基石。CSP是浏览器中引入的一种标准,用于检测和缓解某些类型的代码注入攻击,包括跨站点脚本(XSS)和点击劫持。

常见Web安全问题攻防解析

XSS (Cross Site Script),跨站脚本攻击,因缩写和 CSS (Cascading Style Sheets) 重叠,所以叫 XSS。XSS 的原理是恶意攻击者往 Web 页面里插入恶意可执行网页脚本代码,当用户浏览该页之时,嵌入其中 Web 里面的脚本代码会被执行

HTTPS为什么是安全的?

超文本传输协议HTTP被用于在web浏览器和网站服务器之间传递信息,但以明文方式发送内容,被攻击者截取就可以直接读取内容信息,不适合传输敏感信息。为解决这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS

前端用v-html影响安全性

你的站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击。请只对可信内容使用 HTML 插值,绝不要对用户提供的内容插值。使用 <pre> 标签替换掉 <div> 标签。

14个Linux系统安全小妙招

对于互联网IT从业人员来说,越来越多的工作会逐渐转移到Linux系统之上,这一点,无论是开发、运维、测试都应该是深有体会。曾有技术调查网站W3Techs于2018年11月就发布一个调查报告,报告显示Linux在网站服务器的系统中使用率高达37.2%

网站被劫持的方式都有哪些?

网络安全日益严峻,站长朋友们多多少少都遇到过被黑被劫持的经历,对于老老实实做人,认认真真做站的朋友来说,好不容易做出了一点成绩,一劫持就又回到解放前了,本期我们一起来探讨常见的网站被黑被劫持的手段有哪些

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!

文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全运营推广