引入:
前面我们分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. js正则表达式匹配字符串与优化过程

    前言 有时候需要实现对js源文件中的url字符串做拦截预处理,或者前端js语法高亮,或者需要对动态加载的关键源码做混淆保护,在某些步骤实现之前,有一个步骤是需要提炼出所有的合法字符串. 目标:检测源文 ...

  2. 读书笔记 effective c++ Item 44 将与模板参数无关的代码抽离出来

    1. 使用模板可能导致代码膨胀 使用模板是节省时间和避免代码重用的很好的方法.你不需要手动输入20个相同的类名,每个类有15个成员函数,相反,你只需要输入一个类模板,然后让编译器来为你实例化20个特定 ...

  3. Java Level 2 学习的八大名著

    Java Level 2 学习的八大名著 前段时间有几天难得的假期,于是把自己认为Java技术栈中的精华总结了一下,但是一直没有时间写下来,今天终于得空希望本文可以对大家有所启发.通过多个实际项目的沉 ...

  4. Eclipse中Maven插件部分常用功能命令介绍

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6689010.html Eclipse中安装Maven插件之后,就能很方便的管理Maven项 ...

  5. 监听器的小示例:利用HttpSessionListener和HttpServletContextListener实现定时销毁HttpSession

    1.创建MyServletContextListener实现HttpServletContextListener接口 @Override public void contextDestroyed(Se ...

  6. C#变量、常量、枚举、预处理器指令知多少

    一.变量 C#共有其中变量类型有:静态变量.实类变量.数组元素.数值参数.引用参数.输出参数和局部变量 先定义一个简单的类来说明,如下: public class VariableDefine { p ...

  7. vue获取dom元素内容

    通过ref来获取dom元素 在vue官网上对ref的解释 ref 被用来给元素或子组件注册引用信息.引用信息将会注册在父组件的 $refs 对象上.如果在普通的 DOM 元素上使用,引用指向的就是 D ...

  8. 基于MATLAB的数字基带信号的各种码型的产生

    单极性非归零码 单极性非归零码使用电平1来表示二元信息中的“1”,用电平0来表示二元信息中的“0”,电平在整个码元的时间里不变单极性非归零码的优点是实现简单,但由于含有直流分量,对在带限信道中的传输不 ...

  9. [原创] JavaScript实现简单的颜色类标签云

    效果预览: 源码分享: <!DOCTYPE html><html><head lang="en"> <meta charset=" ...

  10. Android系统--输入系统(七)Reader_Dispatcher线程启动分析

    Android系统--输入系统(七)Reader_Dispatcher线程启动分析 1. Reader/Dispatcher的引入 对于输入系统来说,将会创建两个线程: Reader线程(读取事件) ...