WEB安全实战(五)XSS 攻击的另外一种解决方案(推荐)

说到 XSS 攻击,前边已经有两篇文章在讲这个事了,这次又拿出来说,主要是针对最近工作中的一些新的问题。那么之前是怎么解决这个问题的呢?为什么又要换解决方案?下面就详细的跟大家分享一下。

旧方案

公司的测试团队发现这个问题之后,就要求尽快的解决,在网上查了很多相关的资料,也翻阅了基本安全方面的书,基于 XSS 的攻击原理,自己写了一个 Filter,并在该 Filter 中加入了对各种请求的处理代码。首先是拦截浏览器发出的请求,然后对拦截到的请求进行过滤,获取参数列表,参数值列表(包括表单提交),然后对这些参数值进行危险字符的过滤处理,处理的过程中分为两种情况。

其中一种是把危险字符进行转换,保留原来的语意,在适当的时候进行还原,当然,这种情况下危险字符还是存在的,只不过是换了一种相对安全的形式。这种情况的好处是,保证了请求的原始性,但是对数据库或文件系统产生一些不必要的垃圾信息。为什么这么说呢,因为普通的用户在正常的操作下是不会包含这些非法字符的,只有在非法入侵的情况下才会出现这种情况,而对于危险字符的转换就是一种间接的保护措施。

对于第二种情况,不是对危险字符进行转换,而是把请求中的危险字符进行过滤,使得请求纯净化,把非法的字符过滤掉,这样以来,进入数据库或文件系统的就仅仅是合法的语句。这种情况也会有他的利弊。比如,在过滤的过程中,可能把用户的某些正常请求参数值也给清理掉,这样就不能保证请求的原始性。但系统的安全性方面却大大的提高了。为了避免用户的请求失真,我们能做的就是尽量的避开用户可以输入的特殊字符,在注册、登录、或者其他的请求中,规定用户可以使用的特殊字符,对那些不提倡使用的字符进行过滤和处理。

问题

在旧的的方案提交给测试团队之后,很大一部分的 XSS 攻击问题已经不存在了,但又出现了另外一个问题,在登录的过程中,偶尔会把验证码给过滤掉,还有一些不定的 URL 会时不时的漏掉,虽然在 web.xml 配置了全局的请求,但还是会出现这样的问题。测试团队给出的报告中显示,还有少量的 XSS 攻击存在,让我尽快解决。

针对这个问题,我又研究了问题所在区域的源代码,并结合自己写的 XSSFilter,发现了2点问题。

其一,是后台的验证逻辑并不完整,对于提交过来的请求,并没有进行相应的处理。

其二,是 XSSFilter 写的有问题,正如我上面讲到的情况一,只是把危险字符进行转换,并没有从根本上解决问题。

俗话说,久病成良医。那么,总想着一件事,问题解决起来也总会是事半功倍的。

新方案

对于出现的问题,我这里有两点需要说,其一就是针对后台的验证逻辑,这个没有必要再详细说了,无非就行完善验证逻辑,针对可能出现的情况进行抽象,抽出通用的验证逻辑,对于个别的验证就单独处理,不过还是要考虑代码的复用性。

其二,是关于 XSS 攻击全局处理的。我这里给出两种解决方案,详述如下。

方案一

如果你遇到的情况,对与用户的输入、输出有明确的限制,而且对于特殊字符也有明确的规定,那么你可以自己写一个 XSSFilter,使用上面提到的情况二,对不建议输入的特殊字符进行过滤和清理,包括 SQL 注入的一些敏感信息,都是要过滤掉的。基本的 Filter 网上都有,你要做的就是针对自己的业务,再加入对危险字符的处理即可。

方案二

想到一句老话,站在巨人的肩膀上。第二种方案,就是站在巨人的肩膀上。推荐一款开源插件,xssProject,具体作者不详。GoogleCode 中提供相应了的源代码。想研究的可以自己去找一下。下面着重讲一下,如何在项目中集成 xssProject,并使之为我们服务。

首先,项目中需要引入 xssProtect-0.1.jar、antlr-3.0.1.jar、antlr-runtime-3.0.1.jar 等3个 jar 包。

然后,封装 request,代码如下。

<span style="font-family:Comic Sans MS;">public class NewXssHttpServletRequestWrapper extends HttpServletRequestWrapper {

	HttpServletRequest orgRequest = null;

	public NewXssHttpServletRequestWrapper(HttpServletRequest request) {
		super(request);
        orgRequest = request;
	}

    /**
     * 覆盖getParameter方法,将参数名和参数值都做xss过滤。<br/>
     * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br/>
     * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
     */
    @Override
    public String getParameter(String name)
    {
    	System.out.println("NewXssFilter处理前的 Value = " + super.getParameterValues(name));

        String value = super.getParameter(xssEncode(name));
        if (value != null)
        {
            value = xssEncode(value);
        }

        System.out.println("NewXssFilter处理后的 Value = " + value);

        return value;
    }

    /**
     * 覆盖getHeader方法,将参数名和参数值都做xss过滤。<br/>
     * 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br/> getHeaderNames 也可能需要覆盖
     */
    @Override
    public String getHeader(String name)
    {

        String value = super.getHeader(xssEncode(name));
        if (value != null)
        {
            value = xssEncode(value);
        }
        return value;
    }

    /**
     * 将容易引起xss漏洞的半角字符直接替换成全角字符
     *
     * @param s
     * @return
     */
    private static String xssEncode(String s)
    {
        if (s == null || s.isEmpty())
        {
            return s;
        }

        StringReader reader = new StringReader( s );
        StringWriter writer = new StringWriter();
        try {
            HTMLParser.process( reader, writer, new XSSFilter(), true );

            return writer.toString();
        }
        catch (NullPointerException e) {
            return s;
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }

        return null;

    }

    /**
     * 获取最原始的request
     *
     * @return
     */
    public HttpServletRequest getOrgRequest()
    {
        return orgRequest;
    }

    /**
     * 获取最原始的request的静态方法
     *
     * @return
     */
    public static HttpServletRequest getOrgRequest(HttpServletRequest req)
    {
        if (req instanceof NewXssHttpServletRequestWrapper)
        {
            return ((NewXssHttpServletRequestWrapper) req).getOrgRequest();
        }

        return req;
    }

}</span>

再然后,创建过滤器 NewXssFilter 。

<span style="font-family:Comic Sans MS;">public class NewXssFilter implements Filter {

	FilterConfig filterConfig = null;

	@Override
	public void destroy() {
		this.filterConfig = null;
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		String path = ((HttpServletRequest) request).getContextPath();
		String basePath = request.getScheme() + "://" + request.getServerName()
				+ ":" + request.getServerPort() + path + "/";

		// HTTP 头设置 Referer过滤
		String referer = ((HttpServletRequest) request).getHeader("Referer"); // REFRESH
		if (referer != null && referer.indexOf(basePath) < 0) {
			((HttpServletRequest) request).getRequestDispatcher(
					((HttpServletRequest) request).getRequestURI()).forward(
					((HttpServletRequest) request), response);
			System.out.println("referer不为空,referer >>>>>>>>>>>>>> " + referer);
		}
		NewXssHttpServletRequestWrapper xssRequest = new NewXssHttpServletRequestWrapper((HttpServletRequest) request);
		chain.doFilter(xssRequest, response);
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		this.filterConfig = filterConfig;
	}

}</span>

最后,在 web.xml 中配置过滤器 。

<span style="font-family:Comic Sans MS;"><filter>
	<filter-name>XssSqlFilter</filter-name>
	<filter-class>com.***.web.common.NewXssFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>XssSqlFilter</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>REQUEST</dispatcher>
</filter-mapping></span>

结束语

以上这些就是全部的内容了,针对 XSS 攻击的解决方案,写出来跟大家分享,个人建议使用 xssProject 来解决这一问题。毕竟 xssProject 已经提供了很完善的过滤、处理方案,你可以通过研究他的代码来进行扩展,如果需要的话。最后附上 xssProject 所需的三个 jar 包。

xssProject 下载

时间: 2024-10-09 05:58:20

WEB安全实战(五)XSS 攻击的另外一种解决方案(推荐)的相关文章

使用 PHP 构建的 Web 应用如何避免 XSS 攻击

本文首先简单介绍开发测试人员如何对 Web 应用进行 XSS 漏洞测试,如何借助工具绕过客户端 JavaScript 校验输入恶意数据:然后针对使用 PHP 语言构建的 Web 站点,从在输出端对动态内容进行编码.以及在服务器端对输入进行检测两方面介绍如何避免恶意的 XSS 攻击. 使用 PHP 构建的 Web 应用如何避免 XSS 攻击 Web 2.0 的发展为网络用户的互动提供了更多机会.用户通过在论坛发表评论,或是在博客发表留言都可能有意或无意输入一些破坏性的内容,从而造成网页不能正常显示

Web 安全漏洞之 XSS 攻击

什么是 XSS 攻击 XSS(Cross-Site Scripting)又称跨站脚本,XSS的重点不在于跨站点,而是在于脚本的执行.XSS是一种经常出现在 Web 应用程序中的计算机安全漏洞,是由于 Web 应用程序对用户的输入过滤不足而产生的. 常见的 XSS 攻击有三种:反射型.DOM-based 型.存储型. 其中反射型.DOM-based 型可以归类为非持久型 XSS 攻击,存储型归类为持久型 XSS 攻击. 1.反射型 反射型 XSS 一般是攻击者通过特定手法(如电子邮件),诱使用户去

如何让Asp.net Web Api全局预防Xss攻击

一.概述 二.什么是XSS 三.预防方法 四.在WebApi中如何实现 在实现之前,需要了解ASP.NET WEB API的pipeline机制. 如上,可以采用多种方式进行参数的过滤 1.重写DelegatingHandler的SendAsync方法进行过滤,结合AntiXss类库实现 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Htt

Web开发之分页算法,N(N&gt;=3)种解决方案

在Web开发中,分页是最常用的一个功能了.但是,想简单.灵活.方便地解决分页这个问题,还是需要动点脑筋的. 今天,简要梳理下,过去6年中,亲自遇到的分页问题和解决办法. 1. 定义问题 原由:在页面中需要展示若干数据,但不可能一次展示所有的,想通过每次只展示若干条.分页数,pageNo,是为了标记,当前访问的内容在哪里. 后端需要做的:后端需要分页查询数据,把数据返回给前端 前端需要做的:根据后端的数据,构造"1.2.3"等分页面板,并且要响应事件,比如点击"2",

web安全之XSS攻击原理及防范

阅读目录 一:什么是XSS攻击? 二:反射型XSS 三:存储型XSS 四:DOM-based型XSS 五:SQL注入 六:XSS如何防范? 1. cookie安全策略 2. X-XSS-Protection设置 3. XSS防御HTML编码 4. XSS 防御HTML Attribute编码 5. XSS防御之javascript编码 6. XSS 防御之 URL 编码 7. XSS 防御之 CSS 编码 8. 开启CSP网页安全政策防止XSS攻击 回到顶部 一:什么是XSS攻击? XSS 即(

xss攻击入门

xss表示Cross Site Scripting(跨站脚本攻击),它与SQL注入攻击类似,SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的,而在xss攻击中,通过插入恶意脚本,实现对用户游览器的控制. xss攻击可以分成两种类型: 非持久型攻击 持久型攻击 下面我们通过具体例子,了解两种类型xss攻击. 1.非持久型xss攻击 顾名思义,非持久型xss攻击是一次性的,仅对当次的页面访问产生影响.非持久型xss攻击要求用户访问一个被攻击者篡改后的链接,用户访问该链接时

xss攻击入门【转载】

xss攻击入门 xss表示Cross Site Scripting(跨站脚本攻击),它与SQL注入攻击类似,SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的,而在xss攻击中,通过插入恶意脚本,实现对用户游览器的控制. xss攻击可以分成两种类型: 非持久型攻击 持久型攻击 下面我们通过具体例子,了解两种类型xss攻击. 1.非持久型xss攻击 顾名思义,非持久型xss攻击是一次性的,仅对当次的页面访问产生影响.非持久型xss攻击要求用户访问一个被攻击者篡改后的链接,

手写SpringBoot项目XSS攻击过滤器实现

一.先来个简介 什么是XSS? 百度百科的解释: XSS又叫CSS  (Cross Site Script) ,跨站脚本攻击.它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的. 它与SQL注入攻击类似,SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的,而在xss攻击中,通过插入恶意脚本,实现对用户游览器的控制,获取用户的一些信息. 二.XSS分类 xss攻击可以分成两种类型:

WEB安全实战(五)XSS 攻击的第二种解决方式(推荐)

序 说到 XSS 攻击,前边已经有两篇文章在讲这个事了,这次又拿出来说,主要是针对近期工作中的一些新的问题.那么之前是怎么解决问题的呢?为什么又要换解决方式?以下就具体的跟大家分享一下. 旧方案 公司的測试团队发现这个问题之后,就要求尽快的解决,在网上查了非常多相关的资料,也翻阅了基本安全方面的书,基于 XSS 的攻击原理,自己写了一个 Filter,并在该 Filter 中增加了对各种请求的处理代码.首先是拦截浏览器发出的请求,然后对拦截到的请求进行过滤,获取參数列表,參数值列表(包含表单提交