引入:
前面我们分2篇文章分别探讨了来自外部的XSS攻击和来自内部的XSS攻击,现在我们来专门探讨如何防范来自内部的XSS攻击。
 
实践:
 
http://www.cnblogs.com/crazylqy/p/4146740.html 文章中可以看出,主要的攻击手段无外乎是发送了一段恶意脚本到受害者机器上去运行,所以我们的思路就是,如何让这段脚本失效。
 
因为脚本的组成部分是<script>和</script>,而这其中最主要的是大于号和小于号字符,所以我们只要在请求中,把
大于号字符,小于号字符处理下,让其没办法通过
Http发送到受害者机器上,当然就没办法在受害者机器上组成一段恶意脚本了。但是如果我们的内容中真的有大于号和小于号,并且作为内容的一部分而最终目
的并不是入侵怎么办?我们只要吧大于号,小于号进行全角化处理就可以了,因为只有half-width的大于号和小于号能组
成<script>,</script>,而full-width的大于号和小于号是不可以被对待
成<script>,</script>的。
 
读者可能又问,现在就算你不让我输入大于号和小于号,但是我可以以unicode字符的形式输入这些字符啊,比如大于号叫 >
小于号叫< 所以我只要在恶意脚本中所有用到大于小于的地方全部用这些替换,一样可以达到入侵的目的。
所以,我们必须对于这种&,#还有其他特殊字符也进行处理。
 
综上所述,我们大概明白怎么做了,我们只要做一个过滤器,然后把这些特殊字符都过滤掉就可以了。
 
web.xml中定义一个过滤器:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    <display-name>XSSDemo</display-name>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
    <filter>
        <filter-name>XSS Filter</filter-name>
        <filter-class>com.charles.study.XSSFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>XSS Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
</web-app>

然后我们定义一个 XSSHttpServletRequestWrapper,它是HttpServletRequest的封装器,其中会吧一些特殊字符全部处理掉,被处 理的特殊字符就是那些会造成script的字符,吧他们全部“全角化”,来避免植入恶意代码,这是通过覆写getParameter()和 getHeader()方法来实现的:

package com.charles.study;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
 * This is the HTTPServletRequestWrapper class ,which overrides the default implementation
 * of getParameter() and getHeader() method ,it will handle the characters that may cause XSS
 * @author charles.wang
 *
 */
public class XSSHttpServletRequestWrapper extends HttpServletRequestWrapper {
    public XSSHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
     /**
     * Override the original getParameter() method ,
     * so that it can filter all the parameter name and parameter value
     * then use replace the special character that may cause XSS attack
     */
    @Override
    public String getParameter(String name) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
        String value = super.getParameter(encodeXSS(name));
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
        //the following sentences will be replaced by logging sentence in actual project  
        System.out.println("The original value received from getParameter() is:"+value);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
        if (value != null) {
            value = encodeXSS(value);
        }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
        //the following sentences will be replaced by logging sentence in actual project  
        System.out.println("After handling XSS ,the actual value is:"+value);
        System.out.println();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
        return value;
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
    /**
     * Override the original getHeader() method ,
     * so that it can filter all the parameter name and parameter value
     * then use replace the special character that may cause XSS attack
     */
    @Override
    public String getHeader(String name) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
        String value = super.getHeader(encodeXSS(name));
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
        //the following sentences will be replaced by logging sentence in actual project  
        System.out.println("The original value received from getHeader() is:"+value);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
        if (value != null) {
            value = encodeXSS(value);
        }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
        //the following sentences will be replaced by logging sentence in actual project  
        System.out.println("After handling XSS ,the actual value is:"+value);
        System.out.println();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
        return value;
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
    /**
     * replace all the characters that may cause XSS attack from half-width character
     * to full-width character
     *
     * @param s
     * @return
     */
    private String encodeXSS(String s) {
        if (s == null || "".equals(s)) {
            return s;
        }
        StringBuilder sb = new StringBuilder(s.length() + 16);
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            switch (c) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
            //handle the '<' and '>' which can be used for constructing <script> and </script>
            case '>':
                sb.append('>');
                break;
            case '<':
                sb.append('<');
                break;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
            //since the html can support the characters using $#number format
            //so here also need to escape '#','&' and quote symbol
            case '\'':
                sb.append('‘');
                break;
            case '\"':
                sb.append('“');
                break;
            case '&':
                sb.append('&');
                break;
            case '\\':
                sb.append('\');
                break;
            case '#':
                sb.append('#');
                break;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
            //if not the special characters ,then output it directly  
            default:
                sb.append(c);
                break;
            }
        }
        return sb.toString();
    }
}

最后,我们来定义过滤器的实现,我们在doFilter()方法体中会吧所有的Http请求包装为我们自定义的包装器,这样所有当请求相关内容时候,我们包装器中就会对有可能引起XSS攻击的特殊字符处理,从而预防XSS 攻击。

package com.charles.study;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
 * XSSFilter that can be used to filter invalid character which may cause XSS attack
 * @author charles.wang
 *
 */
public class XSSFilter implements Filter {
                                                                                                                                                                                                                                                                                                                                                                                      
    @Override
    public void destroy() {
    }
    /**
     * now the doFilter will filter the request ,using the Wrapper class to wrap the request
     * and in the wrapper class, it will handle the XSS issue
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
         XSSHttpServletRequestWrapper xssRequest = new XSSHttpServletRequestWrapper(
                    (HttpServletRequest) request);
            chain.doFilter(xssRequest, response);
    }
    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }
}

我们基于上面的实现来做例子,我们回忆以前文章,假如在恶意页面的输入框中输 入<script>alert("Attack");</script>时候,在受害者页面会弹出一个alert对话框,也就是 说这个恶意js在受害者的自己域上执行了从而达到内部XSS攻击的目的。
 
那么现在呢?假如我们在页面中输入同样的脚本:

因为我们启用了XSS的过滤器,所以他们会自动吧这些大于小于转为全角,从而破坏其形成一段脚本,我们来看下服务器日志:

因为做了半角到全角的转换,所以最终页面不会弹出那个alert了,而且正确的显示了:


 
总结:
其实这种解决方案很common,其思路就是类似于海关检查,大家都知道爆炸物和有威胁的物品(恶意脚本)大多数都是硫磺,金属('<','>')等等,那么我只要在过海关的时候(用户提交输入内容框)对这些危险物品进行清查,该扣留的扣留,该销毁的销毁(我们的encodeXSS方法,吧这些< ,>全部全角化)) ,这样就算这个人通过了检查,他因为没有了硫磺和金属物品,所以他没办法制作有威胁的炸弹了(到我们例子就是我们把特殊字符全部全角化了之后,它就不再能形成一个脚本了),于是达到防止内部XSS攻击的结果。


还可以换成HTML转义字符

package cn.richinfo.answerclub.filter;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 *
 * @author liyuan
 *
 */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    HttpServletRequest orgRequest = null;

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

/**
     * 覆盖getParameter方法,将参数名和参数值都做xss过滤。<br/>
     * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br/>
     * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
     */
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(xssEncode(name));
        if (value != null) {
            value = xssEncode(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;
        }

s = s.replaceAll("&", "&amp;");
        s = s.replaceAll("\"", "&quot;");
        s = s.replaceAll("<", "&lt;");
        s = s.replaceAll(">", "&gt;");
        s = s.replaceAll("%3C", "&lt;");
        s = s.replaceAll("%3E", "&gt;");
        
        s = s.replaceAll("%27", "");
        s = s.replaceAll("%22", "");
        s = s.replaceAll("%3E", "");
        s = s.replaceAll("%3C", "");
        s = s.replaceAll("%3D", "");
        s = s.replaceAll("%2F", "");
        s = regexReplace("^>", "", s);

s = regexReplace("<([^>]*?)(?=<|$)", "&lt;$1", s);
        s = regexReplace("(^|>)([^<]*?)(?=>)", "$1$2&gt;<", s);

//s = s.replaceAll("\\|", "");
        s = s.replaceAll("alert", "");
        s = s.replaceAll("STYLE=", "");
        s = s.replaceAll("<iframe", "");
        s = s.replaceAll("<script", "");
        s = s.replaceAll("<IMG", "");
        return s;
    }

private static String regexReplace(String regex_pattern,
            String replacement, String s) {
        Pattern p = Pattern.compile(regex_pattern);
        Matcher m = p.matcher(s);
        return m.replaceAll(replacement);
    }

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

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

return req;
    }
}

XSS研究2-来自内部的XSS攻击的防范的更多相关文章

  1. XSS研究1-来自外部的XSS攻击

    引入: 上文中我们的例子是研究了来自内部的XSS攻击,通过输送一段有害js代码到受害者的机器,让其在受害者的域上运行这段有害JS代码来得到入侵目的.现在我们来看下来自外部的XSS攻击. 实践: 下面还 ...

  2. 来自内部的XSS攻击的防范

    来自内部的XSS攻击的防范 引入:前面我们分2篇文章分别探讨了来自外部的XSS攻击和来自内部的XSS攻击,现在我们来专门探讨如何防范来自内部的XSS攻击. 实践:其实从 http://www.2cto ...

  3. XSS与CSRF两种跨站攻击比较

    XSS:跨站脚本(Cross-site scripting) CSRF:跨站请求伪造(Cross-site request forgery) 在那个年代,大家一般用拼接字符串的方式来构造动态SQL 语 ...

  4. 总结 XSS 与 CSRF 两种跨站攻击

    前言 在那个年代,大家一般用拼接字符串的方式来构造动态 SQL 语句创建应用,于是 SQL 注入成了很流行的攻击方式.在这个年代, 参数化查询 [1] 已经成了普遍用法,我们已经离 SQL 注入很远了 ...

  5. 总结XSS与CSRF两种跨站攻击

    XSS:跨站脚本(Cross-site scripting),实际应是"CSS",但由于和层叠样式表CSS名称冲突,故改为"XSS" CSRF:跨站请求伪造(C ...

  6. XSS 与 CSRF 两种跨站攻击

    在前几年,大家一般用拼接字符串的方式来构造动态 SQL 语句创建应用,于是 SQL 注入成了很流行的攻击方式, 但是现在参数化查询 已经成了普遍用法,我们已经离 SQL 注入很远了.但是历史同样悠久的 ...

  7. XSS与CSRF两种跨站攻击总结

    在那个年代,大家一般用拼接字符串的方式来构造动态 SQL 语句创建应用,于是 SQL 注入成了很流行的攻击方式.在这个年代, 参数化查询 [1] 已经成了普遍用法,我们已经离 SQL 注入很远了.但是 ...

  8. XSS攻击及防范

    1.什么是XSS攻击 跨站脚本攻击(Cross Site Scripting),攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到 ...

  9. 二十五:XSS跨站值原理分类及攻击手法

    HTML DOM树 XSS跨站产生原理,危害,特点 本质,产生层面,函数类,漏洞操作对应层,危害影响,浏览器内核版本 XSS是什么? XSS全称跨站脚本(Cross Site Scripting),为 ...

随机推荐

  1. 4.Linux的文件搜索命令

    1.文件搜索命令  which 语法:which [命令名称] 范例:$which ls  列出ls命令所在目录 [chanshuyi@localhost ~]$ which ls alias ls= ...

  2. C#基础语法(一)

    一.基础语法 1.C#区分大小写,所以myVar和MyVar是两个不同的变量. 2.每个C#可执行文件(如控制台应用程序,Windows应用程序和Windows服务)都必须有一个入口点----Main ...

  3. 浩哥解析MyBatis源码(八)——Type类型模块之TypeAliasRegistry(类型别名注册器)

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6705769.html 1.回顾 前面几篇讲了数据源模块,这和之前的事务模块都是enviro ...

  4. 轻量级操作系统FreeRTOS的内存管理机制(一)

    本文由嵌入式企鹅圈原创团队成员朱衡德(Hunter_Zhu)供稿. 近几年来,FreeRTOS在嵌入式操作系统排行榜中一直位居前列,作为开源的嵌入式操作系统之一,它支持许多不同架构的处理器以及多种编译 ...

  5. 通过virtualbox最小化安装centos 6.3后无法上网解决办法

    通过virtualbox最小化安装centos 6.3后无法上网解决办法 1.设置virtualbox的网络连接方式,如下图使用桥接方式,桥接的网卡为宿主正在上网的网卡,现在我是通过无线来上网的,所以 ...

  6. pixi.js

    添加基本文件(库文件) 渲染库 pixi.js pixi.lib.js是pixi.js的子集,依赖class.js,cat.js,event_emiter.js文件 pixi.scroller.js ...

  7. Oracle空间查询 ORA-28595

    可使用数据库管理系统 (DBMS) 的结构化查询语言 (SQL).数据类型和表格式来处理地理数据库或安装了 ST_Geometry 类型的数据库中所存储的信息. 例如,在ArcMap中我们使用&quo ...

  8. 使用Eclipse Memory Analyzer Tool(MAT)分析线上故障(一) - 视图&功能篇

    Eclipse Memory Analyzer Tool(MAT)相关文章目录: 使用Eclipse Memory Analyzer Tool(MAT)分析线上故障(一) - 视图&功能篇 使 ...

  9. JS模式---发布、订阅模式

    发布订阅模式又叫观察者模式,它定义一种一对多的依赖关系, 当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. document.body.addEventListener('click', ...

  10. Windows7系统的封装

    系统装到虚拟机优化完成以后,可以装上自己想要装的软件,也可以不装做个纯净版的.今天用ES封装,首先打开一般我们只点这四项就够了,如下图 写上自己想写的,也可以不写系统默认,直接点“下一步”关闭设备管理 ...