引入:
前面我们分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. Hexo + Github Pages 搭建个人博客

    之前一直想搭建自己的博客,由于自己的懒惰拖到现在.好了,废话不多说!直接上干货! 安装Node.js 安装Git Github Pages配置 安装Hexo及主题设置 进阶篇-高级定制 其它实用功能 ...

  2. es6基础系列二:Number

    es6中关于Number类型的变化,主要有以下几点 Number.isInteger(新增,判断是否为整数) Number.EPSILON(新增,判断是否可忽略的误差) Number.MAX_SAFE ...

  3. 4 安装MPush

    cnblogs-DOC 1.服务器环境 2.安装Redis3.安装Zookeeper4.安装MPush5.安装Alloc服务6.完整测试7.常见问题 一.Linux安装Mpush [root@loca ...

  4. MySQL Online DDL的改进与应用

        本文简析Online DDL的实现原理与使用过程注意事项.       任何DDL操作,执行者都需要预先测试或者清晰了解这个操作会给数据库带来的影响是否是在业务期间数据库的可承受范围内,尤其是 ...

  5. appium+python做移动端自动化测试

      1 导言 1.1 编制目的 该文档为选用Appium作为移动设备原生(Native).混合(Hybrid).移动Web(Mobile Web)应用UI自动化测试的相关自动化测试人员.开发人员等提供 ...

  6. T-SQL几个简单的操作

    视图 咱们先来了解下视图到底是什么意思,顾名思义,用简单的视觉方式展现复杂的内容 有什么功能呢, 各位应该还记得咱们之前练习的那个小小的数据库superise,里面有这么四张表,分别是: studen ...

  7. UEditor使用------图片上传与springMVC集成 完整实例

    UEditor是一个很强大的在线编辑软件 ,首先讲一下 基本的配置使用 ,如果已经会的同学可以直接跳过此节 ,今天篇文章重点说图片上传; 一  富文本的初始化使用: 1 首先将UEditor从官网下载 ...

  8. CPP--借助神器VS理解内存存储

    之前也有想了解这些,第一个不是学底层的不知道从何理解,第二个上网搜概念,大牛们三言两语就结束了,举得例子也比较复杂,对于非C方向的可能有点吃力,所以一直没理解. 今天偶然发现原来还要内存窗口之说,就慢 ...

  9. 想成为Java高级工程师的看过来

    想成为Java高级工程师,有哪些要求呢? 1.Core Java,就是Java基础.JDK的类库,很多童鞋都会说,JDK我懂,但是懂还不足够,知其然还要知其所以然,JDK的源代码写的非常好,要经常查看 ...

  10. hadoop环境搭建之关于NAT模式静态IP的设置 ---VMware12+CentOs7

    很久没有更新了,主要是没有时间,今天挤出时间验证了一下,果然还是有些问题的,不过已经解决了,就发上来吧. PS:小豆腐看仔细了哦~ 关于hadoop环境搭建,从单机模式,到伪分布式,再到完全分布式,我 ...