XSS漏洞的原理与测试解决方案笔记

漏洞原理:
XSS又叫CSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意的特殊目的。
业务影响:
通过XSS攻击可以攻击到网站管理员后台和平行的用户
安全关注点:
跨站可以导致用户的认证信息被盗,被钓鱼,被挂马等
解决方案:
对输出变量中的危险符号<   >";'(   ) 等进行转义处理词转义处理或者过滤。
工具测试方案:

打开WVS,点击左上角的New Scan


在弹出窗口中输入要扫描的网址



点击 Next,出现窗口中选择XSS,测试模版



扫描结果如下图,红色感叹号即为扫到的XSS漏洞




展开能看到更多详情,右侧为漏洞详情和payload,可用来做手工验证
  手工测试方案:

还是拿上面的例子来说,首先对我们的输入用burpsuite进行抓包,如下图



可以清楚的看到http请求的内容,在空白处点击右键,选择Send to Repeater



然后点开repeater标签



点击Go,即可看到服务器返回的数据



在右侧搜索我们输入的字符串,可以看到右侧有输出



我们把输入的部分改成 <script>alert(1)</script>,点击Go看回显,payload原封不动的输出了,这里有一个需要注意的,服务器返回的数据中,下图中标出来的头部必须是html才可以触发,否则就算服务器返回了输入的payload,浏览器也不会执行,下图这个状态就说明存在XSS漏洞



上面说的是反射型XSS漏洞,还有一种漏洞是存储型XSS漏洞,相较反射型XSS漏洞危害更大,但是此类漏洞很难用工具自动检测,更多的是手工测试。反射XSS需要受害者去点击链接,才能够触发,而存储型XSS,往往更加稳定的存在,任何人只要访问了存在Payload的页面,即可触发。

案例:某论坛,有人发了一篇帖子,所有的人都能看帖子,注册用户可以回帖,回帖功能存在存储型XSS,这时有个用户发了一个恶意的回复内容,服务端将内容存入数据库,有人访问页面的时候就在页面上显示回复内容,但这个内容是用户输入的恶意内容,服务端如果未作过滤就显示在页面上,那么谁访问该页面,谁就中招(触发攻击)。

然后我们看具体的代码示例

1在web.xml配置

   <filter>
        <filter-name>XssFilter</filter-name>
        <filter-class>com.jd.noah.cms.web.util.XssFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>XssFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

2写一个filter

package com.jd.noah.cms.web.util;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Set;

/**
 * xss攻击的预防过滤器
 * Created by jiangkunkun on 2016/12/26
 */
public class XssFilter implements Filter {
    FilterConfig filterConfig = null;
    /**
     * 需要匹配替换的正则表达式
     */
    private String regEx;
    /**
     * 过滤器排除url集合
     */
    private Set<String> excluded;

    /**
     * 过滤器初始化方法
     * @param filterConfig
     * @throws ServletException
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
        if (filterConfig.getInitParameter("regEx") != null) {
            regEx = filterConfig.getInitParameter("regEx");
        }
        if (filterConfig.getInitParameter("excluded") != null) {
            String excludedStr = filterConfig.getInitParameter("excluded");
            if (excludedStr.contains(",")) {
                String[] arr = excludedStr.split(",");
                for (String s : arr) {
                    excluded.add(s.trim());
                }
            } else {
                excluded.add(excludedStr);
            }
        }
    }
    //
    public void destroy() {
        this.filterConfig = null;
    }
    //
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest inRequest = (HttpServletRequest) request;
        String uri = inRequest.getRequestURI();
        if (simpleMatch(excluded, uri)) {
            chain.doFilter(request, response);
            return;
        }
        chain.doFilter(new XssHttpServletRequestWrapper(
                inRequest,this.regEx), response);
    }

    private static boolean simpleMatch(Set<String> patterns, String str) {
        if (patterns == null || patterns.isEmpty() || str == null) {
            return false;
        }
        for (String pattern : patterns) {
            if (simpleMatch(pattern, str)) {
                return true;
            }
        }
        return false;
    }

    /**
     * URL通配符匹配
     * @param pattern
     * @param str
     * @return
     */
    private static boolean simpleMatch(String pattern, String str) {
        if (pattern == null || str == null) {
            return false;
        }
        int firstIndex = pattern.indexOf('*');
        if (firstIndex == -1) {
            return pattern.equals(str);
        }
        if (firstIndex == 0) {
            if (pattern.length() == 1) {
                return true;
            }
            int nextIndex = pattern.indexOf('*', firstIndex + 1);
            if (nextIndex == -1) {
                return str.endsWith(pattern.substring(1));
            }
            String part = pattern.substring(1, nextIndex);
            int partIndex = str.indexOf(part);
            while (partIndex != -1) {
                if (simpleMatch(pattern.substring(nextIndex), str.substring(partIndex + part.length()))) {
                    return true;
                }
                partIndex = str.indexOf(part, partIndex + 1);
            }
            return false;
        }
        return (str.length() >= firstIndex &&
                pattern.substring(0, firstIndex).equals(str.substring(0, firstIndex)) &&
                simpleMatch(pattern.substring(firstIndex), str.substring(firstIndex)));
    }
}

3HttpServletRequestWrapper类

package com.jd.noah.cms.web.util;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 用户请求包装类
 *  Created by jiangkunkun on 2016/12/26
 */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    /**
     * 需要匹配替换的正则表达式
     */
    private String regEx;

    public XssHttpServletRequestWrapper(HttpServletRequest servletRequest,String regEx) {
        super(servletRequest);
        this.regEx = regEx;
    }

    @Override
    public String[] getParameterValues(String parameter) {
        String[] values = super.getParameterValues(parameter);
        if (values == null) {
            return null;
        }
        int count = values.length;
        String[] encodedValues = new String[count];
        for (int i = 0; i < count; i++) {
            encodedValues[i] = cleanXSS(values[i]);
        }
        return encodedValues;
    }

    @Override
    public String getParameter(String parameter) {
        String value = super.getParameter(parameter);
        if (value == null) {
            return null;
        }
        return cleanXSS(value);
    }

    //
    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        if (value == null)
            return null;
        return cleanXSS(value);
    }

    /**
     * 清除替换XSS代码
     * @param value
     * @return
     */
    private String cleanXSS(String value) {
        value = value.replaceAll("<", "<").replaceAll(">", ">");
         value = value.replaceAll("\\(", "(").replaceAll("\\)", ")");
        value = value.replaceAll("'", "'");
        value = value.replaceAll("eval\\((.*)\\)", "");
        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
        value = value.replaceAll("script", "").trim();
/*        String regEx="[`~!@#$%^&*()+=|{}':;',//[//].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?\"]";
        if(this.regEx != null){
            regEx = this.regEx;
        }
        Pattern p   =   Pattern.compile(regEx);
        Matcher dataMatcher   =   p.matcher(value);
        value = dataMatcher.replaceAll("").trim() ;*/
        return value;
    }


}

  • 4
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值