zoukankan      html  css  js  c++  java
  • XSS分析及预防

    XSS(Cross Site Scripting),又称跨站脚本,XSS的重点不在于跨站点,而是在于脚本的执行。在WEB前端应用日益发展的今天,XSS漏洞尤其容易被开发人员忽视,最终可能造成对个人信息的泄漏。如今,仍然没有统一的方式来检测XSS漏洞,但是对于前端开发人员而言,仍是可以在某些细微处避免的,因此本文会结合笔者的学习和经验总结解决和避免的一些方案,并简要从webkit内核分析浏览器内核对于XSS避免所做的努力,了解底层基础设施对预防XSS所做的贡献。

    XSS的种类和特点

    此处不详细讲解XSS的一些细节

    XSS的目标是让其他站点的js文件运行在目标站点的上,这主要发生在页面渲染阶段。在该阶段发生了某些非预期的脚本行为,该脚本可能来自用户的输入,也可能来自域外的其他js文件,不一而足。XSS的发生起源来自于用户输入,因此XSS根据用户输入数据以何种形式、何时触发XSS、是否有后端服务器的参与划分为三种类型,分别是反射型XSS、持久型XSS和DOM XSS。

    反射型XSS

    反射型XSS,顾名思义在于“反射”这个一来一回的过程。反射型XSS的触发有后端的参与,而之所以触发XSS是因为后端解析用户在前端输入的带有XSS性质的脚本或者脚本的data URI编码,后端解析用户输入处理后返回给前端,由浏览器解析这段XSS脚本,触发XSS漏洞。因此如果要避免反射性XSS,则必须需要后端的协调,在后端解析前端的数据时首先做相关的字串检测和转义处理;同时前端同样也许针对用户的数据做excape转义,保证数据源的可靠性。

    e.x.
    localhost/test.php

    <?php echo $_GET['name'] ?>
    

    如果通过 localhost/test.php?name=alert(document.cookie) 访问页面,那么经过后端服务器的处理,就会造成反射性XSS的发生。

    同理,通过传入data uri编码的字符串也会导致XSS,如 localhost/test.php?name=data:text/html;charset=utf-8;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5jb29raWUpPC9zY3JpcHQ+ 会导致同样的问题。该段编码的字串解码后是“alert(document.cookie)”。

    持久型XSS

    持久型XSS仍然需要服务端的参与,它与反射型XSS的区别在于XSS代码是否持久化(硬盘,数据库)。反射型XSS过程中后端服务器仅仅将XSS代码保存在内存中,并未持久化,因此每次触发反射性XSS都需要由用户输入相关的XSS代码;而持久型XSS则仅仅首次输入相关的XSS代码,保存在数据库中,当下次从数据库中获取该数据时在前端未加字串检测和excape转码时,会造成XSS,而且由于该漏洞的隐蔽性和持久型的特点,在多人开发的大型应用和跨应用间的数据获取时造成的大范围的XSS漏洞,危害尤其大。这就需要开发人员培养良好的WEB前端安全意识,不仅仅不能相信用户的输入,也不能完全相信保存在数据库中的数据(即后端开发人员忽视的数据安全检测)。针对持久型XSS没有好的解决方式,只能由开发人员保证。当然规则是由开发者制定,如果忽略用户体验的话,可以制定一套严谨的输入规则,对相关关键词和输入类型(如data URI检测,禁止输入)的检测和禁止,尽可能规避用户发现XSS漏洞的可能性,从源头处理。

    DOM XSS

    DOM XSS完全在前端浏览器触发,无需服务端的参与,因此这是前端开发工程师的“地盘”,理应获得我们的关注。

    e.x.
    localhost/test.html

    <script>
    eval('alert(location.hash.slice("1"))');
    </script>
    

    如果访问localhost/test.html#document.cookie ,那么就会触发最简单的危害非常大的DOM XSS。它完全没有服务端的参与,仅仅由用户的输入和不安全的脚本执行造成,当然在本例中仅仅是最简单的情况,如果用户输入字符串‘’或者text/html格式的data URI,则更难检测,也危害更大,黑客操作起来更为容易。

    因此预防DOM XSS,需要前端开发人员警惕用户所有的输入数据,做到数据的excape转义,同时尽可能少的直接输出HTML的内容;不用eval、new Function、setTimeout等较为hack的方式解析外站数据和执行js脚本;禁止内联事件处理函数;如果在考虑安全性的前提下需要获取外站脚本的执行结果,可以采用前端沙盒(建立空的iframe执行脚本,该iframe无法操作当前文档对象模型)、worker线程的方式完成,保证DOM的安全。

    XSS预防

    XSS漏洞难以检测,但是为了WEB安全仍需要尽力避免,在本节将会针对三种类型XSS漏洞提出对应解决方法,并从其他角度提供更具启发性的意见。

    针对反射型XSS,在对应的小节中也提到过,需要服务端和前端共同预防,针对用户输入的数据做解析和转义,对于前端开发而言,则是善于使用escape,针对data URI内容做正则判断,禁止用户输入非显示信息,如MIME类型为“text/html,text/plain”类型的内容。
    对于存储型XSS,处理方式仍然类同于反射性XSS。
    对于DOM XSS,则需要慎之又慎。由于造成XSS的原因在于用户的输入,因此在前端,需要特别注意以下的用户输入源:


    document.URL,
    location.hash,
    location.research,
    document.referrer(此处应尤为注意,referrer属性虽然可用于避免CSRF,但可触发XSS攻击),
    XHR返回值(跨域返回值),
    form表单及各种input框

    针对以上输入源,需要做相对于的检测和转义。在以上输入源中获取数据后,可能会有各种DOM操作或纯粹的js计算,这些操作则是真正触发XSS的罪魁祸首:


    1,直接输出HTML内容
    document.body.innerHTML = ...
    document.body.outterHTML = ...
    document.write()
    2,HTML标签内联脚本

    <img src='abc' onerror=alert('error')>
    3,直接执行脚本
    eval
    new Function(){}
    setTimeout()
    window.execScript()
    4,打开新页面触发XSS(包括反射型XSS和持久型XSS)
    window.open()
    location.href = ...
    location.hash = ...

    在操作DOM时,需要尤其注意上述操作,针对可能造成的XSS需要进行字串转义。当然,有些操作是完全可以避免的:对于innerHTML的拼接操作,需要摒弃jQuery式的链式操作而使用前端模版如artTemplate,也可选择使用由后端渲染好的可靠的数据,这样既保证性能也确保安全;对于HTML标签内嵌js,则需要完全避免,这是一种容错率很低的实现;直接执行脚本和解析数据,则需避免eval和new Funciton等操作,改为JSON.parse、iframe沙盒和webWorker执行;而针对打开新页面触发的XSS则需要开发人员自行把控。

    另外的尝试

    上文提到的仅仅是对应的XSS避免方案,但是如果将目光放置在全局,站在浏览器的角度上,则会变的更为柳暗花明。现阶段,大多数浏览器都支持多种安全策略,如沙盒机制,跨域机制,跨文档消息和CSP。在这里,我们关注CSP(Content Security Policy),又称内容安全协议,CSP通过服务端响应的HTTP头部来制定网页相关资源的加载域,这些资源限定于js文件、css文件、image、iframe、字体和其他对象(如object、applet)。

    CSP通过HTTP头部由服务端制定,头部类型由于历史原因总共由三种,这三种仅仅是兼容性的差别,针对chrome浏览器,我们仅需关注Content-Security-Policy头部。CSP头部的定义规则如下:
    Content-Security-Policy: 名 值; 名 值; 名 值;

    具体的指令名如下图:
    CSP derective
    指令值的规范如下图:
    CSP value

    因此,如果我们要避免XSS攻击,可以限定脚本的来源域,如:
    Content-Security-Policy: default-src 'self' ajax.googleapis.com;
    这样,非本域和ajax.googleapis.com域下的其他脚本不会被加载,避免了XSS。

    在这里需要强调一点的是,默认CSP会禁止script代码块的执行;禁止内联事件处理函数;禁止内联样式;禁止eval和new Function。对于内联script代码块和内联样式,可通过CSP的header设置,如Content-Security-Policy: default-src 'self'; script-src 'unsafe-inline';。

    CSP有一个指令需要注意,即report-uri,它会将错误信息主动发送至改cgi(sevlet),用于管理员的统一管控。report-uri属性将会在下文中涉及到。

    webkit中的XSS组件

    XSS攻击主要发生在页面的渲染时,当浏览器的渲染引擎获取到该页面并开始解析时,是可以在该阶段进行安全校验的,具体的时间节点则是在词法分析后针对每个token做过滤。

    在webkit中,由HTMLDocumentParser解析得到token后,使用XSSAuditor进行过滤,具体则是在filterToken中执行,不仅仅是针对token的名称,其属性也是监测重点。在webkit中采用黑名单机制,针对“,,,”做重点排查,当发现相关隐患时,生成相关信息XSSInfo,由XSSAuditorDelegate类发送给对应的cgi,该cgi的地址正是CSP中的指令值report-uri,当然也可以手动制定该值。

    默认,XSSAuditor是启用的,但是XSSAuditor在发现XSS行为时却有多种,这些行为可以配置,这就涉及到HTTP头部X-XSS-Protection。该头部并不是W3C和IETF的规范,而是非标准实现,通过对该头部的赋值来定制XSSAuditor的相关行为。

    默认情况,XSSAuditor处于重写模式(js代码处在非执行状态),即X-XSS-Protection:1;如果要禁用XSSAuditor,可以X-XSS-Protection:0;当设置为X-XSS-Protection:1;mode=block,则会在XSSAuditor作用时禁止网页显示,呈现给用户的则是空白页;若设置为X-XSS-Protection:1;report=... ,则会将相关统计信息发送给CSP中定义的report-uri。XSSAuditor无法完全避免XSS,但毕竟在浏览器层面提供了一层检查机制,从HTML tag上保证其可靠性。

    总结

    XSS漏洞难以发现,但是作为开发人员需要于细节处避免制造XSS漏洞,而对于CSP规范和webkit的XSSAuditor机制的使用,我们不应抱着依靠它们的想法来解决XSS,毕竟不是所有的页面都可以容忍CSP的严格,XSSAuditor机制也仅仅针对chrome而言,并且存在多种bypass绕过检查,如通过各种HTML实体编码、url编码和js编码。因此,我们仍需以人为本,规范开发习惯,提高WEB前端安全意识。

    参考文章:
    1 浏览器安全策略说之内容安全策略CSP
    2 UNDERSTANDING XSS AUDITOR
    3 webkit技术内幕

  • 相关阅读:
    2021,6,10 xjzx 模拟考试
    平衡树(二)——Treap
    AtCoder Beginner Contest 204 A-E简要题解
    POJ 2311 Cutting Game 题解
    Codeforces 990G GCD Counting 题解
    NOI2021 SDPTT D2T1 我已经完全理解了 DFS 序线段树 题解
    第三届山东省青少年创意编程与智能设计大赛总结
    Luogu P6042 「ACOI2020」学园祭 题解
    联合省选2021 游记
    Codeforces 1498E Two Houses 题解 —— 如何用结论吊打标算
  • 原文地址:https://www.cnblogs.com/accordion/p/5446174.html
Copyright © 2011-2022 走看看