XSS研究2-来自内部的XSS攻击的防范

引入:
前面我们分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"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <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;
    }
}

时间: 2024-11-09 02:11:10

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

XSS研究1-来自内部的XSS攻击

引入: 上文中我们的例子是研究了来自内部的XSS攻击,通过输送一段有害js代码到受害者的机器,让其在受害者的域上运行这段有害JS代码来得到入侵目的.现在我们来看下来自外部的XSS攻击. 实践: 下面还是按照惯例,我用白话文来解释下什么是来自外部的XSS攻击. 假设我是攻击者,A是受害者,我知道A有个习惯,他会经常去某个奢侈品消费网站登录,然后每次登录用他的积分买很多东西,我没钱,我想通过A的账号 密码登录同样的网站,然后用他的积分去买东西给我自己.显然因为A知道我是受害者,所以我直接问A要账号密

xss (Cross Site Scripting)跨站脚本攻击

XSS攻击:跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS. XSS攻击分成两类: 一类是来自内部的攻击,主要指的是利用程序自身的漏洞,构造跨站语句,如:dvbbs的showerror.asp存在的跨站漏洞. 另一类则是来自外部的攻击,主要指的自己构造XSS跨站漏洞网页或者寻找非目标机以外的有跨站漏洞的网页.如当我们要渗透一个站点,我们自己构造一个有跨站漏洞的网页,然后构

总结 XSS 与 CSRF 两种跨站攻击

在那个年代,大家一般用拼接字符串的方式来构造动态 SQL 语句创建应用,于是 SQL 注入成了很流行的攻击方式.在这个年代, 参数化查询 [1] 已经成了普遍用法,我们已经离 SQL 注入很远了.但是,历史同样悠久的 XSS 和 CSRF 却没有远离我们.由于之前已经对 XSS 很熟悉了,所以我对用户输入的数据一直非常小心.如果输入的时候没有经过 Tidy 之类的过滤,我一定会在模板输出时候全部转义.所以个人感觉,要避免 XSS 也是很容易的,重点是要“小心”.但最近又听说了另一种跨站攻击 CS

XSS与CSRF两种跨站攻击总结

在那个年代,大家一般用拼接字符串的方式来构造动态 SQL 语句创建应用,于是 SQL 注入成了很流行的攻击方式.在这个年代, 参数化查询 [1] 已经成了普遍用法,我们已经离 SQL 注入很远了.但是,历史同样悠久的 XSS 和 CSRF 却没有远离我们.由于之前已经对 XSS 很熟悉了,所以我对用户输入的数据一直非常小心.如果输入的时候没有经过 Tidy 之类的过滤,我一定会在模板输出时候全部转义.所以个人感觉,要避免 XSS 也是很容易的,重点是要“小心”.但最近又听说了另一种跨站攻击 CS

XSS攻击与防范

1.什么是XSS攻击 XSS攻击,跨站脚本攻击 跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets,CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS.恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的. xss攻击,就是给form表单的项目里边填写一些html.css.js等脚本代码,这些代码就会被收集到数据库里边,当对应的内容展示的时

DOM based XSS Prevention Cheat Sheet(DOM Based XSS防御检查单)

本文为翻译版本,原文请查看 https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet 介绍 谈到XSS攻击,有三种公认的形式,Stored. Reflected 和 DOM Based XSS. XSS Prevention Cheatsheet可以有效地解决 Stored. Reflected XSS攻击, 本检查单解决了 DOM Based XSS攻击,是 XSS Prevention Cheatsheet 的延

Atitit.&#160;Xss&#160;漏洞的原理and应用xss木马

Atitit. Xss 漏洞的原理and应用xss木马 1. XSS漏洞1 2. XSS的用途2 2.1. 盗取cookie2 2.2. 刷新流量 刷分3 2.3. DOS 窃取隐私”.“假冒身份”.“WEB蠕虫3 2.4. 广告植入 弹窗 .信息收集 .流量转发 甚至是路由劫持3 2.5. 钓鱼攻击,高级的钓鱼技巧.3 2.6. 删除目标文章.恶意篡改数据.嫁祸.3 2.7. 劫持用户Web行为,甚至进一步渗透内网.3 2.8. 爆发Web2.0蠕虫.3 2.9. 蠕虫式的DDoS攻击.3 2

XSS跨站脚本(pikachu)——反射型xss(get和post)

XSS漏洞是危害比较大的一个漏洞了,主要危害的是前端用户.XSS漏洞可以用来进行钓鱼攻击,前端JS挖矿,用户cookie获取.甚至可以结合浏览器自身的漏洞对用户主机进行远程控制. 这是我从B站学习视频上截取到的攻击过程的图片觉得比较生动形象.  我们需要了解XSS的三种基本类型 反射型XSS:<非持久化> 攻击者事先制作好攻击链接, 需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一次性,所见即所得,一般容易出现在搜索页面. 存储型XSS:<持久化>

Web攻防系列教程之跨站脚本攻击和防范技巧详解

Web攻防系列教程之跨站脚本攻击和防范技巧详解[XSS] 收藏:http://www.rising.com.cn/newsletter/news/2012-04-25/11387.html 来源:瑞星 2012-04-25 14:33:46 摘要:XSS跨站脚本攻击一直都被认为是客户端Web安全中最主流的攻击方式.因为Web环境的复杂性 以及XSS跨站脚本攻击的多变性,使得该类型攻击很难彻底解决.那么,XSS跨站脚本攻击具体攻击行为是什么,又该如何进行有效的防范呢?本文对此进行了 有针对性的具体