{"id":1298,"date":"2024-07-09T13:33:13","date_gmt":"2024-07-09T05:33:13","guid":{"rendered":"https:\/\/blog.nonot.cn\/?p=1298"},"modified":"2024-07-09T13:33:13","modified_gmt":"2024-07-09T05:33:13","slug":"xss%e8%bf%87%e6%bb%a4java%e8%bf%87%e6%bb%a4%e5%99%a8filter-%e9%98%b2%e6%ad%a2%e5%b8%b8%e8%a7%81sql%e6%b3%a8%e5%85%a5","status":"publish","type":"post","link":"https:\/\/blog.nonot.cn\/index.php\/2024\/07\/09\/xss%e8%bf%87%e6%bb%a4java%e8%bf%87%e6%bb%a4%e5%99%a8filter-%e9%98%b2%e6%ad%a2%e5%b8%b8%e8%a7%81sql%e6%b3%a8%e5%85%a5\/","title":{"rendered":"XSS\u8fc7\u6ee4JAVA\u8fc7\u6ee4\u5668filter \u9632\u6b62\u5e38\u89c1SQL\u6ce8\u5165"},"content":{"rendered":"<p>Java\u9879\u76ee\u4e2dXSS\u8fc7\u6ee4\u5668\u7684\u4f7f\u7528\u65b9\u6cd5\u3002<\/p>\n<p>\u7b80\u5355\u4ecb\u7ecd\uff1a<\/p>\n<p>XSS : \u8de8\u7ad9\u811a\u672c\u653b\u51fb(Cross Site Scripting)\uff0c\u4e3a\u4e0d\u548c\u5c42\u53e0\u6837\u5f0f\u8868(Cascading Style Sheets, CSS)\u7684\u7f29\u5199\u6df7\u6dc6\uff0c\u6545\u5c06\u8de8\u7ad9\u811a\u672c\u653b\u51fb\u7f29\u5199\u4e3aXSS\u3002\u6076\u610f\u653b\u51fb\u8005\u5f80Web\u9875\u9762\u91cc\u63d2\u5165\u6076\u610fhtml\u4ee3\u7801\uff0c\u5f53\u7528\u6237\u6d4f\u89c8\u8be5\u9875\u4e4b\u65f6\uff0c\u5d4c\u5165\u5176\u4e2dWeb\u91cc\u9762\u7684html\u4ee3\u7801\u4f1a\u88ab\u6267\u884c\uff0c\u4ece\u800c\u8fbe\u5230\u6076\u610f\u653b\u51fb\u7528\u6237\u7684\u7279\u6b8a\u76ee\u7684\u3002<\/p>\n<p>sql\u6ce8\u5165<br \/>\n\u6240\u8c13SQL\u6ce8\u5165\uff0c\u5c31\u662f\u901a\u8fc7\u628aSQL\u547d\u4ee4\u63d2\u5165\u5230Web\u8868\u5355\u63d0\u4ea4\u6216\u8f93\u5165\u57df\u540d\u6216\u9875\u9762\u8bf7\u6c42\u7684\u67e5\u8be2\u5b57\u7b26\u4e32\uff0c\u6700\u7ec8\u8fbe\u5230\u6b3a\u9a97\u670d\u52a1\u5668\u6267\u884c\u6076\u610f\u7684SQL\u547d\u4ee4\u3002\u5177\u4f53\u6765\u8bf4\uff0c\u5b83\u662f\u5229\u7528\u73b0\u6709\u5e94\u7528\u7a0b\u5e8f\uff0c\u5c06\uff08\u6076\u610f\uff09\u7684SQL\u547d\u4ee4\u6ce8\u5165\u5230\u540e\u53f0\u6570\u636e\u5e93\u5f15\u64ce\u6267\u884c\u7684\u80fd\u529b\uff0c\u5b83\u53ef\u4ee5\u901a\u8fc7\u5728Web\u8868\u5355\u4e2d\u8f93\u5165\uff08\u6076\u610f\uff09SQL\u8bed\u53e5\u5f97\u5230\u4e00\u4e2a\u5b58\u5728\u5b89\u5168\u6f0f\u6d1e\u7684\u7f51\u7ad9\u4e0a\u7684\u6570\u636e\u5e93\uff0c\u800c\u4e0d\u662f\u6309\u7167\u8bbe\u8ba1\u8005\u610f\u56fe\u53bb\u6267\u884cSQL\u8bed\u53e5\u3002<\/p>\n<p>\u5b9e\u73b0\u65b9\u5f0f\uff0c\u5171\u4e09\u6b65\uff1a<\/p>\n<p><strong>\u7b2c\u4e00\u6b65<\/strong>\uff1a\u914d\u7f6eweb.xml<\/p>\n<div class=\"cnblogs_code\">\n<pre>&lt;filter&gt;\r\n    &lt;filter-name&gt;xssFilter&lt;\/filter-name&gt;\r\n    &lt;filter-class&gt;com.***.xss.XssFilter&lt;\/filter-class&gt;\r\n  &lt;\/filter&gt;\r\n  &lt;filter-mapping&gt;\r\n    &lt;filter-name&gt;xssFilter&lt;\/filter-name&gt;\r\n    &lt;url-pattern&gt;\/*&lt;\/url-pattern&gt;\r\n  &lt;\/filter-mapping&gt;<\/pre>\n<div class=\"cnblogs_code_toolbar\"><\/div>\n<\/div>\n<p>&nbsp;<\/p>\n<p><strong>\u7b2c\u4e8c\u6b65<\/strong>\uff1a\u8fc7\u6ee4\u5de5\u5177\u7c7b<\/p>\n<p>1.XSSFilter.java<\/p>\n<div class=\"cnblogs_code\">\n<p>package com.***.xss;<\/p>\n<p>import javax.servlet.*;<br \/>\nimport javax.servlet.http.HttpServletRequest;<br \/>\nimport java.io.IOException;<\/p>\n<p>\/**<br \/>\n* xss\u8fc7\u6ee4<br \/>\n* @author xlf<br \/>\n* @email xlfbe696@gmail.com<br \/>\n* @date 2017\u5e744\u670819\u65e5 \u4e0a\u534810:41:42<br \/>\n*\/<br \/>\npublic class XssFilter implements Filter {<\/p>\n<p>@Override<br \/>\npublic void init(FilterConfig config) throws ServletException {<br \/>\n}<\/p>\n<p>public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)<br \/>\nthrows IOException, ServletException {<\/p>\n<p>XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(<br \/>\n(HttpServletRequest) request);<br \/>\nchain.doFilter(xssRequest, response);<br \/>\n}<\/p>\n<p>@Override<br \/>\npublic void destroy() {<br \/>\n}<\/p>\n<p>}<\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<p>2.XssHttpServletRequestWrapper<\/p>\n<div class=\"cnblogs_code\">\n<p>package com.***.xss;<\/p>\n<p>import org.apache.commons.lang.StringEscapeUtils;<br \/>\nimport org.apache.commons.lang.StringUtils;<\/p>\n<p>import javax.servlet.http.HttpServletRequest;<br \/>\nimport javax.servlet.http.HttpServletRequestWrapper;<br \/>\nimport java.util.LinkedHashMap;<br \/>\nimport java.util.Map;<\/p>\n<p>public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {<\/p>\n<p>\/\/ \u6ca1\u88ab\u5305\u88c5\u8fc7\u7684HttpServletRequest\uff08\u7279\u6b8a\u573a\u666f\uff0c\u9700\u6c42\u81ea\u5df1\u8fc7\u6ee4\uff09<br \/>\nHttpServletRequest orgRequest;<br \/>\n\/\/ html\u8fc7\u6ee4<br \/>\nprivate final static HTMLFilter htmlFilter = new HTMLFilter();<\/p>\n<p>public XssHttpServletRequestWrapper(HttpServletRequest request) {<br \/>\nsuper(request);<br \/>\norgRequest = request;<br \/>\n}<\/p>\n<p>@Override<br \/>\npublic String getParameter(String name) {<br \/>\nString value = super.getParameter(xssEncode(name));<br \/>\nif (StringUtils.isNotBlank(value)) {<br \/>\nvalue =xssEncode(value);<br \/>\n}<\/p>\n<p>\/\/SQL\u6ce8\u5165\u68c0\u67e5<br \/>\n\/\/ value = SQLFilter.sqlInject(value);<br \/>\nvalue = SQLFilter.sqlInject(value);<\/p>\n<p>return StringEscapeUtils.unescapeHtml(value);<br \/>\n}<\/p>\n<p>@Override<br \/>\npublic String[] getParameterValues(String name) {<br \/>\nString[] parameters = super.getParameterValues(name);<br \/>\nif (parameters == null || parameters.length == 0) {<br \/>\nreturn null;<br \/>\n}<\/p>\n<p>for (int i = 0; i &lt; parameters.length; i++) {<br \/>\nparameters[i] = xssEncode(parameters[i]);<br \/>\n\/\/SQL\u6ce8\u5165\u68c0\u67e5<br \/>\n\/\/ parameters[i] = SQLFilter.sqlInject(parameters[i]);<br \/>\nparameters[i] = SQLFilter.sqlInject(parameters[i]);<br \/>\nparameters[i] = StringEscapeUtils.unescapeHtml(parameters[i]);<br \/>\n}<br \/>\nreturn parameters;<br \/>\n}<\/p>\n<p>@Override<br \/>\npublic Map&lt;String, String[]&gt; getParameterMap() {<br \/>\nMap&lt;String, String[]&gt; map = new LinkedHashMap&lt;&gt;();<br \/>\nMap&lt;String, String[]&gt; parameters = super.getParameterMap();<br \/>\nfor (String key : parameters.keySet()) {<br \/>\nString[] values = parameters.get(key);<br \/>\nfor (int i = 0; i &lt; values.length; i++) {<br \/>\nvalues[i] = xssEncode(values[i]);<br \/>\n\/\/SQL\u6ce8\u5165\u68c0\u67e5<br \/>\n\/\/ values[i] = SQLFilter.sqlInject(values[i]);<br \/>\nvalues[i] = SQLFilter.sqlInject(values[i]);<br \/>\nvalues[i] = StringEscapeUtils.unescapeHtml(values[i]);<br \/>\n}<br \/>\nmap.put(key, values);<br \/>\n}<br \/>\nreturn map;<br \/>\n}<\/p>\n<p>@Override<br \/>\npublic String getHeader(String name) {<br \/>\nString value = super.getHeader(xssEncode(name));<br \/>\nif (StringUtils.isNotBlank(value)) {<br \/>\nvalue = xssEncode(value);<br \/>\n}<\/p>\n<p>\/\/SQL\u6ce8\u5165\u68c0\u67e5<br \/>\n\/\/ value = SQLFilter.sqlInject(value);<br \/>\nvalue = SQLFilter.sqlInject(value);<br \/>\nreturn StringEscapeUtils.unescapeHtml(value);<br \/>\n}<\/p>\n<p>private String xssEncode(String input) {<br \/>\nreturn htmlFilter.filter(input);<br \/>\n}<\/p>\n<p>\/**<br \/>\n* \u83b7\u53d6\u6700\u539f\u59cb\u7684request<br \/>\n*\/<br \/>\npublic HttpServletRequest getOrgRequest() {<br \/>\nreturn orgRequest;<br \/>\n}<\/p>\n<p>\/**<br \/>\n* \u83b7\u53d6\u6700\u539f\u59cb\u7684request<br \/>\n*\/<br \/>\npublic static HttpServletRequest getOrgRequest(HttpServletRequest request) {<br \/>\nif (request instanceof XssHttpServletRequestWrapper) {<br \/>\nreturn ((XssHttpServletRequestWrapper) request).getOrgRequest();<br \/>\n}<\/p>\n<p>return request;<br \/>\n}<\/p>\n<p>}<\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<p>3.HTMLFilter<\/p>\n<div class=\"cnblogs_code\">\n<p>package com.***.xss;<\/p>\n<p>import java.util.ArrayList;<br \/>\nimport java.util.Collections;<br \/>\nimport java.util.HashMap;<br \/>\nimport java.util.List;<br \/>\nimport java.util.Map;<br \/>\nimport java.util.concurrent.ConcurrentHashMap;<br \/>\nimport java.util.concurrent.ConcurrentMap;<br \/>\nimport java.util.logging.Logger;<br \/>\nimport java.util.regex.Matcher;<br \/>\nimport java.util.regex.Pattern;<br \/>\n\/**<br \/>\n*<br \/>\n* HTML filtering utility for protecting against XSS (Cross Site Scripting).<br \/>\n*<br \/>\n* This code is licensed LGPLv3<br \/>\n*<br \/>\n* This code is a Java port of the original work in PHP by Cal Hendersen.<br \/>\n* http:\/\/code.iamcal.com\/php\/lib_filter\/<br \/>\n*<br \/>\n* The trickiest part of the translation was handling the differences in regex handling<br \/>\n* between PHP and Java. These resources were helpful in the process:<br \/>\n*<br \/>\n* http:\/\/java.sun.com\/j2se\/1.4.2\/docs\/api\/java\/util\/regex\/Pattern.html<br \/>\n* http:\/\/us2.php.net\/manual\/en\/reference.pcre.pattern.modifiers.php<br \/>\n* http:\/\/www.regular-expressions.info\/modifiers.html<br \/>\n*<br \/>\n* A note on naming conventions: instance variables are prefixed with a &#8220;v&#8221;; global<br \/>\n* constants are in all caps.<br \/>\n*<br \/>\n* Sample use:<br \/>\n* String input = &#8230;<br \/>\n* String clean = new HTMLFilter().filter( input );<br \/>\n*<br \/>\n* The class is not thread safe. Create a new instance if in doubt.<br \/>\n*<br \/>\n* If you find bugs or have suggestions on improvement (especially regarding<br \/>\n* performance), please contact us. The latest version of this<br \/>\n* source, and our contact details, can be found at http:\/\/xss-html-filter.sf.net<br \/>\n*<br \/>\n* @author Joseph O&#8217;Connell<br \/>\n* @author Cal Hendersen<br \/>\n* @author Michael Semb Wever<br \/>\n*\/<br \/>\npublic class HTMLFilter {<\/p>\n<p>\/** regex flag union representing \/si modifiers in php **\/<br \/>\nprivate static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;<br \/>\nprivate static final Pattern P_COMMENTS = Pattern.compile(&#8220;&lt;!&#8211;(.*?)&#8211;&gt;&#8221;, Pattern.DOTALL);<br \/>\nprivate static final Pattern P_COMMENT = Pattern.compile(&#8220;^!&#8211;(.*)&#8211;$&#8221;, REGEX_FLAGS_SI);<br \/>\nprivate static final Pattern P_TAGS = Pattern.compile(&#8220;&lt;(.*?)&gt;&#8221;, Pattern.DOTALL);<br \/>\nprivate static final Pattern P_END_TAG = Pattern.compile(&#8220;^\/([a-z0-9]+)&#8221;, REGEX_FLAGS_SI);<br \/>\nprivate static final Pattern P_START_TAG = Pattern.compile(&#8220;^([a-z0-9]+)(.*?)(\/?)$&#8221;, REGEX_FLAGS_SI);<br \/>\nprivate static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile(&#8220;([a-z0-9]+)=([\\&#8221;&#8216;])(.*?)\\\\2&#8221;, REGEX_FLAGS_SI);<br \/>\nprivate static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile(&#8220;([a-z0-9]+)(=)([^\\&#8221;\\\\s&#8217;]+)&#8221;, REGEX_FLAGS_SI);<br \/>\nprivate static final Pattern P_PROTOCOL = Pattern.compile(&#8220;^([^:]+):&#8221;, REGEX_FLAGS_SI);<br \/>\nprivate static final Pattern P_ENTITY = Pattern.compile(&#8220;&amp;#(\\\\d+);?&#8221;);<br \/>\nprivate static final Pattern P_ENTITY_UNICODE = Pattern.compile(&#8220;&amp;#x([0-9a-f]+);?&#8221;);<br \/>\nprivate static final Pattern P_ENCODE = Pattern.compile(&#8220;%([0-9a-f]{2});?&#8221;);<br \/>\nprivate static final Pattern P_VALID_ENTITIES = Pattern.compile(&#8220;&amp;([^&amp;;]*)(?=(;|&amp;|$))&#8221;);<br \/>\nprivate static final Pattern P_VALID_QUOTES = Pattern.compile(&#8220;(&gt;|^)([^&lt;]+?)(&lt;|$)&#8221;, Pattern.DOTALL);<br \/>\nprivate static final Pattern P_END_ARROW = Pattern.compile(&#8220;^&gt;&#8221;);<br \/>\nprivate static final Pattern P_BODY_TO_END = Pattern.compile(&#8220;&lt;([^&gt;]*?)(?=&lt;|$)&#8221;);<br \/>\nprivate static final Pattern P_XML_CONTENT = Pattern.compile(&#8220;(^|&gt;)([^&lt;]*?)(?=&gt;)&#8221;);<br \/>\nprivate static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile(&#8220;&lt;([^&gt;]*?)(?=&lt;|$)&#8221;);<br \/>\nprivate static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile(&#8220;(^|&gt;)([^&lt;]*?)(?=&gt;)&#8221;);<br \/>\nprivate static final Pattern P_AMP = Pattern.compile(&#8220;&amp;&#8221;);<br \/>\nprivate static final Pattern P_QUOTE = Pattern.compile(&#8220;\\&#8221;&#8221;);<br \/>\nprivate static final Pattern P_LEFT_ARROW = Pattern.compile(&#8220;&lt;&#8220;);<br \/>\nprivate static final Pattern P_RIGHT_ARROW = Pattern.compile(&#8220;&gt;&#8221;);<br \/>\nprivate static final Pattern P_BOTH_ARROWS = Pattern.compile(&#8220;&lt;&gt;&#8221;);<br \/>\nprivate static final Pattern P_DOUBLE_QUOT = Pattern.compile(&#8220;&#8221;&#8221;);<\/p>\n<p>\/\/ @xxx could grow large&#8230; maybe use sesat&#8217;s ReferenceMap<br \/>\nprivate static final ConcurrentMap&lt;String,Pattern&gt; P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap&lt;String, Pattern&gt;();<br \/>\nprivate static final ConcurrentMap&lt;String,Pattern&gt; P_REMOVE_SELF_BLANKS = new ConcurrentHashMap&lt;String, Pattern&gt;();<\/p>\n<p>\/** set of allowed html elements, along with allowed attributes for each element **\/<br \/>\nprivate final Map&lt;String, List&lt;String&gt;&gt; vAllowed;<br \/>\n\/** counts of open tags for each (allowable) html element **\/<br \/>\nprivate final Map&lt;String, Integer&gt; vTagCounts = new HashMap&lt;String, Integer&gt;();<\/p>\n<p>\/** html elements which must always be self-closing (e.g. &#8220;&lt;img \/&gt;&#8221;) **\/<br \/>\nprivate final String[] vSelfClosingTags;<br \/>\n\/** html elements which must always have separate opening and closing tags (e.g. &#8220;&lt;b&gt;&lt;\/b&gt;&#8221;) **\/<br \/>\nprivate final String[] vNeedClosingTags;<br \/>\n\/** set of disallowed html elements **\/<br \/>\nprivate final String[] vDisallowed;<br \/>\n\/** attributes which should be checked for valid protocols **\/<br \/>\nprivate final String[] vProtocolAtts;<br \/>\n\/** allowed protocols **\/<br \/>\nprivate final String[] vAllowedProtocols;<br \/>\n\/** tags which should be removed if they contain no content (e.g. &#8220;&lt;b&gt;&lt;\/b&gt;&#8221; or &#8220;&lt;b \/&gt;&#8221;) **\/<br \/>\nprivate final String[] vRemoveBlanks;<br \/>\n\/** entities allowed within html markup **\/<br \/>\nprivate final String[] vAllowedEntities;<br \/>\n\/** flag determining whether comments are allowed in input String. *\/<br \/>\nprivate final boolean stripComment;<br \/>\nprivate final boolean encodeQuotes;<br \/>\nprivate boolean vDebug = false;<br \/>\n\/**<br \/>\n* flag determining whether to try to make tags when presented with &#8220;unbalanced&#8221;<br \/>\n* angle brackets (e.g. &#8220;&lt;b text &lt;\/b&gt;&#8221; becomes &#8220;&lt;b&gt; text &lt;\/b&gt;&#8221;). If set to false,<br \/>\n* unbalanced angle brackets will be html escaped.<br \/>\n*\/<br \/>\nprivate final boolean alwaysMakeTags;<\/p>\n<p>\/** Default constructor.<br \/>\n*<br \/>\n*\/<br \/>\npublic HTMLFilter() {<br \/>\nvAllowed = new HashMap&lt;&gt;();<\/p>\n<p>final ArrayList&lt;String&gt; a_atts = new ArrayList&lt;String&gt;();<br \/>\na_atts.add(&#8220;href&#8221;);<br \/>\na_atts.add(&#8220;target&#8221;);<br \/>\nvAllowed.put(&#8220;a&#8221;, a_atts);<\/p>\n<p>final ArrayList&lt;String&gt; img_atts = new ArrayList&lt;String&gt;();<br \/>\nimg_atts.add(&#8220;src&#8221;);<br \/>\nimg_atts.add(&#8220;width&#8221;);<br \/>\nimg_atts.add(&#8220;height&#8221;);<br \/>\nimg_atts.add(&#8220;alt&#8221;);<br \/>\nvAllowed.put(&#8220;img&#8221;, img_atts);<\/p>\n<p>final ArrayList&lt;String&gt; no_atts = new ArrayList&lt;String&gt;();<br \/>\nvAllowed.put(&#8220;b&#8221;, no_atts);<br \/>\nvAllowed.put(&#8220;strong&#8221;, no_atts);<br \/>\nvAllowed.put(&#8220;i&#8221;, no_atts);<br \/>\nvAllowed.put(&#8220;em&#8221;, no_atts);<\/p>\n<p>vSelfClosingTags = new String[]{&#8220;img&#8221;};<br \/>\nvNeedClosingTags = new String[]{&#8220;a&#8221;, &#8220;b&#8221;, &#8220;strong&#8221;, &#8220;i&#8221;, &#8220;em&#8221;};<br \/>\nvDisallowed = new String[]{};<br \/>\nvAllowedProtocols = new String[]{&#8220;http&#8221;, &#8220;mailto&#8221;, &#8220;https&#8221;}; \/\/ no ftp.<br \/>\nvProtocolAtts = new String[]{&#8220;src&#8221;, &#8220;href&#8221;};<br \/>\nvRemoveBlanks = new String[]{&#8220;a&#8221;, &#8220;b&#8221;, &#8220;strong&#8221;, &#8220;i&#8221;, &#8220;em&#8221;};<br \/>\nvAllowedEntities = new String[]{&#8220;amp&#8221;, &#8220;gt&#8221;, &#8220;lt&#8221;, &#8220;quot&#8221;};<br \/>\nstripComment = true;<br \/>\nencodeQuotes = true;<br \/>\nalwaysMakeTags = true;<br \/>\n}<\/p>\n<p>\/** Set debug flag to true. Otherwise use default settings. See the default constructor.<br \/>\n*<br \/>\n* @param debug turn debug on with a true argument<br \/>\n*\/<br \/>\npublic HTMLFilter(final boolean debug) {<br \/>\nthis();<br \/>\nvDebug = debug;<\/p>\n<p>}<\/p>\n<p>\/** Map-parameter configurable constructor.<br \/>\n*<br \/>\n* @param conf map containing configuration. keys match field names.<br \/>\n*\/<br \/>\npublic HTMLFilter(final Map&lt;String,Object&gt; conf) {<\/p>\n<p>assert conf.containsKey(&#8220;vAllowed&#8221;) : &#8220;configuration requires vAllowed&#8221;;<br \/>\nassert conf.containsKey(&#8220;vSelfClosingTags&#8221;) : &#8220;configuration requires vSelfClosingTags&#8221;;<br \/>\nassert conf.containsKey(&#8220;vNeedClosingTags&#8221;) : &#8220;configuration requires vNeedClosingTags&#8221;;<br \/>\nassert conf.containsKey(&#8220;vDisallowed&#8221;) : &#8220;configuration requires vDisallowed&#8221;;<br \/>\nassert conf.containsKey(&#8220;vAllowedProtocols&#8221;) : &#8220;configuration requires vAllowedProtocols&#8221;;<br \/>\nassert conf.containsKey(&#8220;vProtocolAtts&#8221;) : &#8220;configuration requires vProtocolAtts&#8221;;<br \/>\nassert conf.containsKey(&#8220;vRemoveBlanks&#8221;) : &#8220;configuration requires vRemoveBlanks&#8221;;<br \/>\nassert conf.containsKey(&#8220;vAllowedEntities&#8221;) : &#8220;configuration requires vAllowedEntities&#8221;;<\/p>\n<p>vAllowed = Collections.unmodifiableMap((HashMap&lt;String, List&lt;String&gt;&gt;) conf.get(&#8220;vAllowed&#8221;));<br \/>\nvSelfClosingTags = (String[]) conf.get(&#8220;vSelfClosingTags&#8221;);<br \/>\nvNeedClosingTags = (String[]) conf.get(&#8220;vNeedClosingTags&#8221;);<br \/>\nvDisallowed = (String[]) conf.get(&#8220;vDisallowed&#8221;);<br \/>\nvAllowedProtocols = (String[]) conf.get(&#8220;vAllowedProtocols&#8221;);<br \/>\nvProtocolAtts = (String[]) conf.get(&#8220;vProtocolAtts&#8221;);<br \/>\nvRemoveBlanks = (String[]) conf.get(&#8220;vRemoveBlanks&#8221;);<br \/>\nvAllowedEntities = (String[]) conf.get(&#8220;vAllowedEntities&#8221;);<br \/>\nstripComment = conf.containsKey(&#8220;stripComment&#8221;) ? (Boolean) conf.get(&#8220;stripComment&#8221;) : true;<br \/>\nencodeQuotes = conf.containsKey(&#8220;encodeQuotes&#8221;) ? (Boolean) conf.get(&#8220;encodeQuotes&#8221;) : true;<br \/>\nalwaysMakeTags = conf.containsKey(&#8220;alwaysMakeTags&#8221;) ? (Boolean) conf.get(&#8220;alwaysMakeTags&#8221;) : true;<br \/>\n}<\/p>\n<p>private void reset() {<br \/>\nvTagCounts.clear();<br \/>\n}<\/p>\n<p>private void debug(final String msg) {<br \/>\nif (vDebug) {<br \/>\nLogger.getAnonymousLogger().info(msg);<br \/>\n}<br \/>\n}<\/p>\n<p>\/\/&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br \/>\n\/\/ my versions of some PHP library functions<br \/>\npublic static String chr(final int decimal) {<br \/>\nreturn String.valueOf((char) decimal);<br \/>\n}<\/p>\n<p>public static String htmlSpecialChars(final String s) {<br \/>\nString result = s;<br \/>\nresult = regexReplace(P_AMP, &#8220;&amp;&#8221;, result);<br \/>\nresult = regexReplace(P_QUOTE, &#8220;&#8221;&#8221;, result);<br \/>\nresult = regexReplace(P_LEFT_ARROW, &#8220;&lt;&#8220;, result);<br \/>\nresult = regexReplace(P_RIGHT_ARROW, &#8220;&gt;&#8221;, result);<br \/>\nreturn result;<br \/>\n}<\/p>\n<p>\/\/&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br \/>\n\/**<br \/>\n* given a user submitted input String, filter out any invalid or restricted<br \/>\n* html.<br \/>\n*<br \/>\n* @param input text (i.e. submitted by a user) than may contain html<br \/>\n* @return &#8220;clean&#8221; version of input, with only valid, whitelisted html elements allowed<br \/>\n*\/<br \/>\npublic String filter(final String input) {<br \/>\nreset();<br \/>\nString s = input;<\/p>\n<p>debug(&#8220;************************************************&#8221;);<br \/>\ndebug(&#8221; INPUT: &#8221; + input);<\/p>\n<p>s = escapeComments(s);<br \/>\ndebug(&#8221; escapeComments: &#8221; + s);<\/p>\n<p>s = balanceHTML(s);<br \/>\ndebug(&#8221; balanceHTML: &#8221; + s);<\/p>\n<p>s = checkTags(s);<br \/>\ndebug(&#8221; checkTags: &#8221; + s);<\/p>\n<p>s = processRemoveBlanks(s);<br \/>\ndebug(&#8220;processRemoveBlanks: &#8221; + s);<\/p>\n<p>s = validateEntities(s);<br \/>\ndebug(&#8221; validateEntites: &#8221; + s);<\/p>\n<p>debug(&#8220;************************************************\\n\\n&#8221;);<br \/>\nreturn s;<br \/>\n}<\/p>\n<p>public boolean isAlwaysMakeTags(){<br \/>\nreturn alwaysMakeTags;<br \/>\n}<\/p>\n<p>public boolean isStripComments(){<br \/>\nreturn stripComment;<br \/>\n}<\/p>\n<p>private String escapeComments(final String s) {<br \/>\nfinal Matcher m = P_COMMENTS.matcher(s);<br \/>\nfinal StringBuffer buf = new StringBuffer();<br \/>\nif (m.find()) {<br \/>\nfinal String match = m.group(1); \/\/(.*?)<br \/>\nm.appendReplacement(buf, Matcher.quoteReplacement(&#8220;&lt;!&#8211;&#8221; + htmlSpecialChars(match) + &#8220;&#8211;&gt;&#8221;));<br \/>\n}<br \/>\nm.appendTail(buf);<\/p>\n<p>return buf.toString();<br \/>\n}<\/p>\n<p>private String balanceHTML(String s) {<br \/>\nif (alwaysMakeTags) {<br \/>\n\/\/<br \/>\n\/\/ try and form html<br \/>\n\/\/<br \/>\ns = regexReplace(P_END_ARROW, &#8220;&#8221;, s);<br \/>\ns = regexReplace(P_BODY_TO_END, &#8220;&lt;$1&gt;&#8221;, s);<br \/>\ns = regexReplace(P_XML_CONTENT, &#8220;$1&lt;$2&#8221;, s);<\/p>\n<p>} else {<br \/>\n\/\/<br \/>\n\/\/ escape stray brackets<br \/>\n\/\/<br \/>\ns = regexReplace(P_STRAY_LEFT_ARROW, &#8220;&lt;$1&#8221;, s);<br \/>\ns = regexReplace(P_STRAY_RIGHT_ARROW, &#8220;$1$2&gt;&lt;&#8220;, s);<\/p>\n<p>\/\/<br \/>\n\/\/ the last regexp causes &#8216;&lt;&gt;&#8217; entities to appear<br \/>\n\/\/ (we need to do a lookahead assertion so that the last bracket can<br \/>\n\/\/ be used in the next pass of the regexp)<br \/>\n\/\/<br \/>\ns = regexReplace(P_BOTH_ARROWS, &#8220;&#8221;, s);<br \/>\n}<\/p>\n<p>return s;<br \/>\n}<\/p>\n<p>private String checkTags(String s) {<br \/>\nMatcher m = P_TAGS.matcher(s);<\/p>\n<p>final StringBuffer buf = new StringBuffer();<br \/>\nwhile (m.find()) {<br \/>\nString replaceStr = m.group(1);<br \/>\nreplaceStr = processTag(replaceStr);<br \/>\nm.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));<br \/>\n}<br \/>\nm.appendTail(buf);<\/p>\n<p>s = buf.toString();<\/p>\n<p>\/\/ these get tallied in processTag<br \/>\n\/\/ (remember to reset before subsequent calls to filter method)<br \/>\nfor (String key : vTagCounts.keySet()) {<br \/>\nfor (int ii = 0; ii &lt; vTagCounts.get(key); ii++) {<br \/>\ns += &#8220;&lt;\/&#8221; + key + &#8220;&gt;&#8221;;<br \/>\n}<br \/>\n}<\/p>\n<p>return s;<br \/>\n}<\/p>\n<p>private String processRemoveBlanks(final String s) {<br \/>\nString result = s;<br \/>\nfor (String tag : vRemoveBlanks) {<br \/>\nif(!P_REMOVE_PAIR_BLANKS.containsKey(tag)){<br \/>\nP_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile(&#8220;&lt;&#8221; + tag + &#8220;(\\\\s[^&gt;]*)?&gt;&lt;\/&#8221; + tag + &#8220;&gt;&#8221;));<br \/>\n}<br \/>\nresult = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), &#8220;&#8221;, result);<br \/>\nif(!P_REMOVE_SELF_BLANKS.containsKey(tag)){<br \/>\nP_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile(&#8220;&lt;&#8221; + tag + &#8220;(\\\\s[^&gt;]*)?\/&gt;&#8221;));<br \/>\n}<br \/>\nresult = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), &#8220;&#8221;, result);<br \/>\n}<\/p>\n<p>return result;<br \/>\n}<\/p>\n<p>private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) {<br \/>\nMatcher m = regex_pattern.matcher(s);<br \/>\nreturn m.replaceAll(replacement);<br \/>\n}<\/p>\n<p>private String processTag(final String s) {<br \/>\n\/\/ ending tags<br \/>\nMatcher m = P_END_TAG.matcher(s);<br \/>\nif (m.find()) {<br \/>\nfinal String name = m.group(1).toLowerCase();<br \/>\nif (allowed(name)) {<br \/>\nif (!inArray(name, vSelfClosingTags)) {<br \/>\nif (vTagCounts.containsKey(name)) {<br \/>\nvTagCounts.put(name, vTagCounts.get(name) &#8211; 1);<br \/>\nreturn &#8220;&lt;\/&#8221; + name + &#8220;&gt;&#8221;;<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>\/\/ starting tags<br \/>\nm = P_START_TAG.matcher(s);<br \/>\nif (m.find()) {<br \/>\nfinal String name = m.group(1).toLowerCase();<br \/>\nfinal String body = m.group(2);<br \/>\nString ending = m.group(3);<\/p>\n<p>\/\/debug( &#8220;in a starting tag, name='&#8221; + name + &#8220;&#8216;; body='&#8221; + body + &#8220;&#8216;; ending='&#8221; + ending + &#8220;&#8216;&#8221; );<br \/>\nif (allowed(name)) {<br \/>\nString params = &#8220;&#8221;;<\/p>\n<p>final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);<br \/>\nfinal Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);<br \/>\nfinal List&lt;String&gt; paramNames = new ArrayList&lt;String&gt;();<br \/>\nfinal List&lt;String&gt; paramValues = new ArrayList&lt;String&gt;();<br \/>\nwhile (m2.find()) {<br \/>\nparamNames.add(m2.group(1)); \/\/([a-z0-9]+)<br \/>\nparamValues.add(m2.group(3)); \/\/(.*?)<br \/>\n}<br \/>\nwhile (m3.find()) {<br \/>\nparamNames.add(m3.group(1)); \/\/([a-z0-9]+)<br \/>\nparamValues.add(m3.group(3)); \/\/([^\\&#8221;\\\\s&#8217;]+)<br \/>\n}<\/p>\n<p>String paramName, paramValue;<br \/>\nfor (int ii = 0; ii &lt; paramNames.size(); ii++) {<br \/>\nparamName = paramNames.get(ii).toLowerCase();<br \/>\nparamValue = paramValues.get(ii);<\/p>\n<p>\/\/ debug( &#8220;paramName='&#8221; + paramName + &#8220;&#8216;&#8221; );<br \/>\n\/\/ debug( &#8220;paramValue='&#8221; + paramValue + &#8220;&#8216;&#8221; );<br \/>\n\/\/ debug( &#8220;allowed? &#8221; + vAllowed.get( name ).contains( paramName ) );<\/p>\n<p>if (allowedAttribute(name, paramName)) {<br \/>\nif (inArray(paramName, vProtocolAtts)) {<br \/>\nparamValue = processParamProtocol(paramValue);<br \/>\n}<br \/>\nparams += &#8221; &#8221; + paramName + &#8220;=\\&#8221;&#8221; + paramValue + &#8220;\\&#8221;&#8221;;<br \/>\n}<br \/>\n}<\/p>\n<p>if (inArray(name, vSelfClosingTags)) {<br \/>\nending = &#8221; \/&#8221;;<br \/>\n}<\/p>\n<p>if (inArray(name, vNeedClosingTags)) {<br \/>\nending = &#8220;&#8221;;<br \/>\n}<\/p>\n<p>if (ending == null || ending.length() &lt; 1) {<br \/>\nif (vTagCounts.containsKey(name)) {<br \/>\nvTagCounts.put(name, vTagCounts.get(name) + 1);<br \/>\n} else {<br \/>\nvTagCounts.put(name, 1);<br \/>\n}<br \/>\n} else {<br \/>\nending = &#8221; \/&#8221;;<br \/>\n}<br \/>\nreturn &#8220;&lt;&#8221; + name + params + ending + &#8220;&gt;&#8221;;<br \/>\n} else {<br \/>\nreturn &#8220;&#8221;;<br \/>\n}<br \/>\n}<\/p>\n<p>\/\/ comments<br \/>\nm = P_COMMENT.matcher(s);<br \/>\nif (!stripComment &amp;&amp; m.find()) {<br \/>\nreturn &#8220;&lt;&#8221; + m.group() + &#8220;&gt;&#8221;;<br \/>\n}<\/p>\n<p>return &#8220;&#8221;;<br \/>\n}<\/p>\n<p>private String processParamProtocol(String s) {<br \/>\ns = decodeEntities(s);<br \/>\nfinal Matcher m = P_PROTOCOL.matcher(s);<br \/>\nif (m.find()) {<br \/>\nfinal String protocol = m.group(1);<br \/>\nif (!inArray(protocol, vAllowedProtocols)) {<br \/>\n\/\/ bad protocol, turn into local anchor link instead<br \/>\ns = &#8220;#&#8221; + s.substring(protocol.length() + 1, s.length());<br \/>\nif (s.startsWith(&#8220;#\/\/&#8221;)) {<br \/>\ns = &#8220;#&#8221; + s.substring(3, s.length());<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>return s;<br \/>\n}<\/p>\n<p>private String decodeEntities(String s) {<br \/>\nStringBuffer buf = new StringBuffer();<\/p>\n<p>Matcher m = P_ENTITY.matcher(s);<br \/>\nwhile (m.find()) {<br \/>\nfinal String match = m.group(1);<br \/>\nfinal int decimal = Integer.decode(match).intValue();<br \/>\nm.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));<br \/>\n}<br \/>\nm.appendTail(buf);<br \/>\ns = buf.toString();<\/p>\n<p>buf = new StringBuffer();<br \/>\nm = P_ENTITY_UNICODE.matcher(s);<br \/>\nwhile (m.find()) {<br \/>\nfinal String match = m.group(1);<br \/>\nfinal int decimal = Integer.valueOf(match, 16).intValue();<br \/>\nm.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));<br \/>\n}<br \/>\nm.appendTail(buf);<br \/>\ns = buf.toString();<\/p>\n<p>buf = new StringBuffer();<br \/>\nm = P_ENCODE.matcher(s);<br \/>\nwhile (m.find()) {<br \/>\nfinal String match = m.group(1);<br \/>\nfinal int decimal = Integer.valueOf(match, 16).intValue();<br \/>\nm.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));<br \/>\n}<br \/>\nm.appendTail(buf);<br \/>\ns = buf.toString();<\/p>\n<p>s = validateEntities(s);<br \/>\nreturn s;<br \/>\n}<\/p>\n<p>private String validateEntities(final String s) {<br \/>\nStringBuffer buf = new StringBuffer();<\/p>\n<p>\/\/ validate entities throughout the string<br \/>\nMatcher m = P_VALID_ENTITIES.matcher(s);<br \/>\nwhile (m.find()) {<br \/>\nfinal String one = m.group(1); \/\/([^&amp;;]*)<br \/>\nfinal String two = m.group(2); \/\/(?=(;|&amp;|$))<br \/>\nm.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));<br \/>\n}<br \/>\nm.appendTail(buf);<\/p>\n<p>return encodeQuotes(buf.toString());<br \/>\n}<\/p>\n<p>private String encodeQuotes(final String s){<br \/>\nif(encodeQuotes){<br \/>\nStringBuffer buf = new StringBuffer();<br \/>\nMatcher m = P_VALID_QUOTES.matcher(s);<br \/>\nwhile (m.find()) {<br \/>\nfinal String one = m.group(1); \/\/(&gt;|^)<br \/>\nfinal String two = m.group(2); \/\/([^&lt;]+?)<br \/>\nfinal String three = m.group(3); \/\/(&lt;|$)<br \/>\nm.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, &#8220;&#8221;&#8221;, two) + three));<br \/>\n}<br \/>\nm.appendTail(buf);<br \/>\nreturn buf.toString();<br \/>\n}else{<br \/>\nreturn s;<br \/>\n}<br \/>\n}<\/p>\n<p>private String checkEntity(final String preamble, final String term) {<\/p>\n<p>return &#8220;;&#8221;.equals(term) &amp;&amp; isValidEntity(preamble)<br \/>\n? &#8216;&amp;&#8217; + preamble<br \/>\n: &#8220;&amp;&#8221; + preamble;<br \/>\n}<\/p>\n<p>private boolean isValidEntity(final String entity) {<br \/>\nreturn inArray(entity, vAllowedEntities);<br \/>\n}<\/p>\n<p>private static boolean inArray(final String s, final String[] array) {<br \/>\nfor (String item : array) {<br \/>\nif (item != null &amp;&amp; item.equals(s)) {<br \/>\nreturn true;<br \/>\n}<br \/>\n}<br \/>\nreturn false;<br \/>\n}<\/p>\n<p>private boolean allowed(final String name) {<br \/>\nreturn (vAllowed.isEmpty() || vAllowed.containsKey(name)) &amp;&amp; !inArray(name, vDisallowed);<br \/>\n}<\/p>\n<p>private boolean allowedAttribute(final String name, final String paramName) {<br \/>\nreturn allowed(name) &amp;&amp; (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));<br \/>\n}<br \/>\n}<\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<p>4.SQLFilter<\/p>\n<div class=\"cnblogs_code\">\n<div id=\"cnblogs_code_open_fedb124b-8ded-46a8-a20b-96e8906b478d\" class=\"cnblogs_code_hide\">\n<pre>package com.***.xss;\r\n\r\nimport org.apache.commons.lang.StringUtils;\r\n\r\nimport com.wfcm.utils.RRException;\r\n\r\n\/**\r\n * sql\u8fc7\u6ee4\r\n * \r\n * @author xlf\r\n * @email xlfbe696@gmail.com\r\n * @date 2017\u5e744\u670819\u65e5 \u4e0a\u534810:41:25\r\n *\/\r\npublic class SQLFilter {\r\n\r\n    \/**\r\n     * SQL\u6ce8\u5165\u8fc7\u6ee4\r\n     * \r\n     * @param str\r\n     *            \u5f85\u9a8c\u8bc1\u7684\u5b57\u7b26\u4e32\r\n     *\/\r\n    public static String sqlInject(String str) {\r\n        if (StringUtils.isBlank(str)) {\r\n            return null;\r\n        }\r\n        \/\/ \u53bb\u6389'|\"|;|\\\u5b57\u7b26\r\n        str = StringUtils.replace(str, \"'\", \"\");\r\n        str = StringUtils.replace(str, \"\\\"\", \"\");\r\n        str = StringUtils.replace(str, \";\", \"\");\r\n        str = StringUtils.replace(str, \"\\\\\", \"\");\r\n\r\n        \/\/ \u8f6c\u6362\u6210\u5c0f\u5199\r\n        str = str.toLowerCase();\r\n\r\n        \/\/ \u975e\u6cd5\u5b57\u7b26\r\n        String[] keywords = { \"master\", \"truncate\", \"insert\", \"select\", \"delete\", \"update\", \"declare\", \"alert\",\r\n                \"create\", \"drop\" };\r\n        \/\/ \u5224\u65ad\u662f\u5426\u5305\u542b\u975e\u6cd5\u5b57\u7b26\r\n        for (String keyword : keywords) {\r\n            if (str.equals(keyword)) {\r\n                throw new RRException(\"\u5305\u542b\u975e\u6cd5\u5b57\u7b26\", 1);\r\n            }\r\n        }\r\n\r\n        return str;\r\n    }\r\n}<\/pre>\n<\/div>\n<\/div>\n<p>&nbsp;<\/p>\n<p><b>THE END\uff01<\/b><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Java\u9879\u76ee\u4e2dXSS\u8fc7\u6ee4\u5668\u7684\u4f7f\u7528\u65b9\u6cd5\u3002 \u7b80\u5355\u4ecb\u7ecd\uff1a XSS &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-1298","post","type-post","status-publish","format-standard","hentry","category-java"],"_links":{"self":[{"href":"https:\/\/blog.nonot.cn\/index.php\/wp-json\/wp\/v2\/posts\/1298","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.nonot.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.nonot.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.nonot.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.nonot.cn\/index.php\/wp-json\/wp\/v2\/comments?post=1298"}],"version-history":[{"count":1,"href":"https:\/\/blog.nonot.cn\/index.php\/wp-json\/wp\/v2\/posts\/1298\/revisions"}],"predecessor-version":[{"id":1317,"href":"https:\/\/blog.nonot.cn\/index.php\/wp-json\/wp\/v2\/posts\/1298\/revisions\/1317"}],"wp:attachment":[{"href":"https:\/\/blog.nonot.cn\/index.php\/wp-json\/wp\/v2\/media?parent=1298"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.nonot.cn\/index.php\/wp-json\/wp\/v2\/categories?post=1298"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.nonot.cn\/index.php\/wp-json\/wp\/v2\/tags?post=1298"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}