XSS、CSRF、点击劫持的防御

作者: EdmundChen | 来源:发表于2018-05-08 15:32 被阅读13次

    xss解决方案

    XSS的本质还是一种“HTML注入”,用户的数据被当成了HTML代码一部分来执行,从而混淆了原本的语义,产生了新的语义。

    一、HttpOnly

    游览器将禁止页面的javascript访问带有HttpOnly属性的cookie

    HttpOnly并非为了对抗XSS——HttpOnly解决的是XSS后的Cookie劫持攻击。

    如果该Cookie设置了HttpOnly,则这种攻击会失败,因为JavaScript读取不到Cookie的值。
    一个Cookie的使用过程如下。

    • Step1:浏览器向服务器发起请求,这时候没有Cookie。
    • Step2:服务器返回时发送Set-Cookie头,向客户端浏览器写入Cookie。
    • Step3:在该Cookie到期前,浏览器访问该域下的所有页面,都将发送该Cookie。

    二、输入检查

    常见的Web漏洞如XSS、SQL Injection等,都要求攻击者构造一些特殊字符,这些特殊字符可能是正常用户不会用到的,所以输入检查就有存在的必要了。
    在XSS的防御上,输入检查一般是检查用户输入的数据中是否包含一些特殊字符,如<>'"等。如果发现存在特殊字符,则将这些字符过滤或者编码。比较智能的“输入检查”,可能还会匹配XSS的特征。比如查找用户数据中是否包含了<script>javascript等敏感字符。
    这种输入检查的方式,可以称为XSS Filter。互联网上有很多开源的XSS Filter的实现。

    三、输出检查

    一般来说,除了富文本的输出外,在变量输出到HTML页面时,可以使用编码或转义的方式来防御XSS攻击。

    安全的编码函数

    编码分为很多种,

    1、HTML代码的编码方式是HtmlEncode。对抗XSS,在HtmlEncode中要求至少转换以下字符:
    & --> &amp;
    < --> &lt;
    > --> &gt;
    " --> &quot;
    ' --> &#x27;
    / --> &#x2F;  
    
    • 包含反斜线是因为它可能会闭合一些HTML entity
    • 所有在标签中输出的变量,如果未做任何处理,都能导致直接产生XSS
    2、JavaScript的编码方式可以使用JavascriptEncode。

    方法使用“\”对特殊字符进行转义。在对抗XSS时,还要求输出的变量必须在引号内部,

    • <script>标签中输出在<script>标签中输出时
    • 在事件中输出
    <a href="#" onclick="funcA('$var')">test</a>
    
    3、在CSS中输出在CSS和style、style attribute中形成XSS 使用encodeForCSS()
    • 尽可能禁止用户可控制的变量在“<style>标签”、“HTML标签的style属性” “CSS文件” 输出
    • 将除了字母、数字外的所有字符都编码成十六进制形式”\uHH“。
    4、在地址中输出: 在URL的path(路径)或者search(参数)中输出,使用URLEncode

    方法使用“\”对特殊字符进行转义。在对抗XSS时,还要求输出的变量必须在引号内部,

    • URLEncode会将字符转换为“%HH”形式,比如空格就是“%20”,“<”符号是“%3c”
    <a href="http://www.evil.com/?test=" onclick=alert(1)"" >test</a>
    

    四、处理富文本

    如何区分安全的“富文本”和有攻击性的XSS呢?在处理富文本时,还是要回到“输入检查”的思路上来。“输入检查”的主要问题是,在检查时还不知道变量的输出语境。但用户提交的“富文本”数据,其语义是完整的HTML代码,在输出时也不会拼凑到某个标签的属性中。因此可以特殊情况特殊处理。

    列出了所有在HTML中可能执行脚本的地方。而一个优秀的“XSS Filter”,也应该能够找出HTML代码中所有可能执行脚本的地方。

    HTML是一种结构化的语言,比较好分析。通过htmlparser可以解析出HTML代码的标签、标签属性和事件。

    在过滤富文本时,“事件”应该被严格禁止,因为“富文本”的展示需求里不应该包括“事件”这种动态效果。而一些危险的标签,比如<iframe>、<script>、<base>、<form>等,也是应该严格禁止的。

    在标签的选择上,应该使用白名单,避免使用黑名单。比如,只允许<a>、<img>、<div>等比较“安全”的标签存在。“白名单原则”不仅仅用于标签的选择,同样应该用于属性与事件的选择。

    如果一定要允许用户自定义样式,则只能像过滤“富文本”一样过滤“CSS”。这需要一个CSSParser对样式进行智能分析,检查其中是否包含危险代码。有一些比较成熟的开源项目,实现了对富文本的XSS检查。

    CSRF的防御

    概述: CSRF攻击的过程,往往是在用户不知情的情况下构造了网络请求。

    防御方法

    一、验证码

    验证码强制用户必须与应用进行交互,才能完成最终请求。因此在通常情况下,验证码能够很好地遏制CSRF攻击。但是验证码并非万能。很多时候,出于用户体验考虑,网站不能给所有的操作都加上验证码。因此,验证码只能作为防御CSRF的一种辅助手段,而不能作为最主要的解决方案。

    二、Referer Check

    Referer Check在互联网中最常见的应用就是“防止图片盗链”。同理,Referer Check也可以被用于检查请求是否来自合法的“源”。

    Referer Check的缺陷在于,服务器并非什么时候都能取到Referer。很多用户出于隐私保护的考虑,限制了Referer的发送。在某些情况下,浏览器也不会发送Referer,比如从HTTPS跳转到HTTP,出于安全的考虑,浏览器也不会发送Ref-erer。

    三、Anti CSRF Token

    现在业界针对CSRF的防御,一致的做法是使用一个Token。

    点击劫持

    点击劫持是一种视觉上的欺骗手段。攻击者使用一个透明的、不可见的iframe,覆盖在一个网页上,然后诱使用户在该网页上进行操作,此时用户将在不知情的情况下点击透明的iframe页面。通过调整iframe页面的位置,可以诱使用户恰好点击在iframe页面的一些功能性按钮上。

    防御方法

    一、frame busting

    通常可以写一段JavaScript代码,以禁止iframe的嵌套。这种方法叫frame busting。
    但是frame busting也存在一些缺陷。由于它是用JavaScript写的,控制能力并不是特别强,因此有许多方法可以绕过它。

    二、HTTP头 X-Frame-Options

    它有三个可选的值:

    • DENY: 浏览器会拒绝当前页面加载任何frame页面;
    • SAMEORIGIN:则frame页面的地址只能为同源域名下的页面
    • ALLOW-FROM origin:可以定义允许frame加载的页面地址。

    参考《白帽子讲web安全》

    相关文章

      网友评论

        本文标题:XSS、CSRF、点击劫持的防御

        本文链接:https://www.haomeiwen.com/subject/jcqwrftx.html