antixss.java

来自「cwbbs 云网论坛源码」· Java 代码 · 共 265 行

JAVA
265
字号
package cn.js.fan.security;import java.util.regex.Matcher;import java.util.regex.Pattern;import org.apache.oro.text.regex.PatternCompiler;import org.apache.oro.text.regex.PatternMatcher;import org.apache.oro.text.regex.Perl5Compiler;import org.apache.oro.text.regex.Perl5Matcher;import org.apache.oro.text.regex.Perl5Substitution;import org.apache.oro.text.regex.Util;public class AntiXSS {    static final Pattern SCRIPT_TAG_PATTERN = Pattern.compile(            "<script[^>]*>.*</script[^>]*>", Pattern.CASE_INSENSITIVE);    static final Pattern IFRAME_TAG_PATTERN = Pattern.compile(            "<iframe[^>]*>.*</iframe[^>]*>", Pattern.CASE_INSENSITIVE);    static final PatternCompiler pc = new Perl5Compiler();    static final PatternMatcher matcher = new Perl5Matcher();        public static String antiXSS(String content) {        String old = content;        String ret = _antiXSS(content);        while (!ret.equals(old)) {            old = ret;            ret = _antiXSS(ret);        }        return ret;    }    private static String _antiXSS(String content) {        try {            return stripAllowScriptAccess(stripProtocol(stripCssExpression(                    stripAsciiAndHex(stripEvent(stripScriptTag(content))))));        } catch (Exception e) {            e.printStackTrace();            return null;        }    }    private static String stripScriptTag(String content) {        Matcher m = SCRIPT_TAG_PATTERN.matcher(content);        content = m.replaceAll("");        m = IFRAME_TAG_PATTERN.matcher(content);        content = m.replaceAll("");        return content;    }    private static String stripEvent(String content) throws Exception {                                String[] events = {"onmouseover", "onmouseout", "onmousedown",                          "onmouseup", "onmousemove", "ondblclick",                          "onkeypress", "onkeydown", "onkeyup", "ondragstart",                          "onerrorupdate", "onhelp", "onreadystatechange",                          "onrowenter",                          "onrowexit", "onselectstart", "onunload",                          "onbeforeunload", "onblur", "onerror", "onfocus",                          "onresize",                          "onscroll", "oncontextmenu",};         for (String event : events) {            org.apache.oro.text.regex.Pattern p = pc.compile("(<[^>]*)("                    + event + ")([^>]*>)",                    Perl5Compiler.CASE_INSENSITIVE_MASK);            if (null != p) {                content = Util.substitute(matcher, p, new Perl5Substitution(                        "$1" + event.substring(2) + "$3"), content,                                          Util.SUBSTITUTE_ALL);            }        }                String patternStr = "(<[^>]*?)onload=([\"|'](.+?)[\"|'])";        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(                patternStr,                Pattern.DOTALL | Pattern.CASE_INSENSITIVE);        java.util.regex.Matcher mat = pattern.matcher(content);        StringBuffer sb = new StringBuffer();        boolean result = mat.find();        boolean isFind = false;        while (result) {            String tagStr = mat.group(0);            boolean isValid = true;            if (!tagStr.substring(1, 4).equalsIgnoreCase("img")) {                isValid = false;            }            else {                                String onloadStr = mat.group(3).toLowerCase();                if (onloadStr.indexOf("location")!=-1 || onloadStr.indexOf("open")!=-1) {                    isValid = false;                }            }            if (!isValid) {                String str = "$1load=$2";                mat.appendReplacement(sb, str);                mat.appendTail(sb);                isFind = true;            }            result = mat.find();        }        if (isFind) {            content = sb.toString();        }                        patternStr = "(<[^>]*)onclick=(\"(.*?)\".*?>)";        pattern = java.util.regex.Pattern.compile(                patternStr,                Pattern.DOTALL | Pattern.CASE_INSENSITIVE);        mat = pattern.matcher(content);        sb = new StringBuffer();        result = mat.find();        isFind = false;        while (result) {            String imgTag = mat.group(0);            if (!imgTag.substring(1, 4).equalsIgnoreCase("img")) {                String str = "$1click=$2";                mat.appendReplacement(sb, str);                isFind = true;            }            else {                                boolean isValid = true;                String imgOnClick = mat.group(3).toLowerCase();                if (imgOnClick.indexOf("location")!=-1) {                    isValid = false;                }                if (isValid) {                                        if (imgOnClick.indexOf("open") != -1) {                        boolean isSrcEqualsOpenParam = false;                                                String patString =                                "<img.*?src.*?=\\s*?([^> ]+)\\s*.*?>";                        java.util.regex.Pattern pat = java.util.regex.Pattern.                                compile(patString,                                        Pattern.DOTALL |                                        Pattern.CASE_INSENSITIVE);                        Matcher m = pat.matcher(imgTag);                        if (m.find()) {                            String imgUrl = m.group(1).replaceAll("\"|'", "");                            System.out.println("imgUrl=" + imgUrl);                                                        patString =                                    "(<img.*?open\\s*?\\()([^> ]+)(\\)\\s*.*?>)";                            pat = java.util.regex.Pattern.                                  compile(patString,                                          Pattern.DOTALL |                                          Pattern.CASE_INSENSITIVE);                            m = pat.matcher(imgTag);                            if (m.find()) {                                String param = m.group(2).replaceAll("\"|'", "");                                                                if (imgUrl.indexOf(param)!=-1) {                                    isSrcEqualsOpenParam = true;                                }                            }                        }                        if (!isSrcEqualsOpenParam) {                            isValid = false;                        }                    }                }                if (!isValid) {                    String str = "$1click=$2";                    mat.appendReplacement(sb, str);                    mat.appendTail(sb);                    isFind = true;                }            }            result = mat.find();        }        if (isFind) {            content = sb.toString();        }        return content;    }    private static String stripAsciiAndHex(String content) throws Exception {                org.apache.oro.text.regex.Pattern p = pc.compile(                "(<[^>]*)(&#|\\\\00)([^>]*>)",                Perl5Compiler.CASE_INSENSITIVE_MASK);        if (null != p)            content = Util                      .substitute(matcher, p, new Perl5Substitution("$1$3"),                                  content, Util.SUBSTITUTE_ALL);        return content;    }    private static String stripCssExpression(String content) throws Exception {        org.apache.oro.text.regex.Pattern p = pc.compile(                "(<[^>]*style=.*)/\\*.*\\*/([^>]*>)",                Perl5Compiler.CASE_INSENSITIVE_MASK);        if (null != p)            content = Util                      .substitute(matcher, p, new Perl5Substitution("$1$2"),                                  content, Util.SUBSTITUTE_ALL);        p = pc            .compile(                    "(<[^>]*style=[^>]+)(expression|javascript|vbscript|-moz-binding)([^>]*>)",                    Perl5Compiler.CASE_INSENSITIVE_MASK);        if (null != p)            content = Util                      .substitute(matcher, p, new Perl5Substitution("$1$3"),                                  content, Util.SUBSTITUTE_ALL);        p = pc.compile("(<style[^>]*>.*)/\\*.*\\*/(.*</style[^>]*>)",                       Perl5Compiler.CASE_INSENSITIVE_MASK);        if (null != p)            content = Util                      .substitute(matcher, p, new Perl5Substitution("$1$2"),                                  content, Util.SUBSTITUTE_ALL);        p = pc            .compile(                    "(<style[^>]*>[^>]+)(expression|javascript|vbscript|-moz-binding)(.*</style[^>]*>)",                    Perl5Compiler.CASE_INSENSITIVE_MASK);        if (null != p)            content = Util                      .substitute(matcher, p, new Perl5Substitution("$1$3"),                                  content, Util.SUBSTITUTE_ALL);        return content;    }    private static String stripProtocol(String content) throws Exception {        String[] protocols = {"javascript", "vbscript", "livescript",                             "ms-its", "mhtml", "data", "firefoxurl", "mocha"};        for (String protocol : protocols) {            org.apache.oro.text.regex.Pattern p = pc.compile("(<[^>]*)"                    + protocol + ":([^>]*>)",                    Perl5Compiler.CASE_INSENSITIVE_MASK);            if (null != p)                content = Util.substitute(matcher, p, new Perl5Substitution(                        "$1/$2"), content, Util.SUBSTITUTE_ALL);        }        return content;    }    private static String stripAllowScriptAccess(String content) throws            Exception {        org.apache.oro.text.regex.Pattern p = pc.compile(                "(<[^>]*)AllowScriptAccess([^>]*>)",                Perl5Compiler.CASE_INSENSITIVE_MASK);        if (null != p)            content = Util.substitute(matcher, p, new Perl5Substitution(                    "$1Allow_Script_Access$2"), content, Util.SUBSTITUTE_ALL);        return content;    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?