diff --git a/zcommon/src/main/java/org/zkoss/html/HTMLs.java b/zcommon/src/main/java/org/zkoss/html/HTMLs.java index eb7dc70156..0031642d32 100644 --- a/zcommon/src/main/java/org/zkoss/html/HTMLs.java +++ b/zcommon/src/main/java/org/zkoss/html/HTMLs.java @@ -211,117 +211,4 @@ public static final boolean isOrphanTag(String tagname) { for (int j = orphans.length; --j >= 0;) _orphans.add(orphans[j]); } - - // Since 7.0.2 - // The following implementation for encoding JavaScript is referred from - // https://code.google.com/p/owasp-esapi-java/ - // which is licensed under New BSD License - http://opensource.org/licenses/BSD-3-Clause - private static char[] IMMUNE_JAVASCRIPT = { ',', '.', '_' }; - private static final String[] hex = new String[256]; - - private static boolean containsCharacter(char c, char[] array) { - for (char ch : array) { - if (c == ch) - return true; - } - return false; - } - - static { - for (char c = 0; c < 0xFF; c++) { - if (c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5A || c >= 0x61 - && c <= 0x7A) { - hex[c] = null; - } else { - hex[c] = toHex(c).intern(); - } - } - } - - private static String toHex(char c) { - return Integer.toHexString(c); - } - - private static String getHexForNonAlphanumeric(char c) { - if (c < 0xFF) - return hex[c]; - return toHex(c); - } - - /** - * Encodes the JavaScript content for XSS vulnerabilities, the implementation is referred from owasp-esapi-java - *

- * Returns backslash encoded numeric format. Does not use backslash - * character escapes such as, \" or \' as these may cause parsing problems. - * For example, if a javascript attribute, such as onmouseover, contains a - * \" that will close the entire attribute and allow an attacker to inject - * another script attribute. - * - * @since 7.0.2 - * @deprecated as of release 10.1.0, replaced by {@link org.owasp.encoder.Encode#forJavaScript(String)} - */ - public static String encodeJavaScript(String input) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < input.length(); i++) { - char c = input.charAt(i); - sb.append(encodeCharacter(IMMUNE_JAVASCRIPT, c)); - } - return sb.toString(); - } - - /** - * Encodes the JavaScript content for XSS vulnerabilities, the implementation is referred from owasp-esapi-java - *

- * Returns backslash encoded numeric format. Does not use backslash - * character escapes such as, \" or \' as these may cause parsing problems. - * For example, if a javascript attribute, such as onmouseover, contains a - * \" that will close the entire attribute and allow an attacker to inject - * another script attribute. - * - * @since 7.0.2 - * @deprecated as of release 10.1.0, replaced by {@link org.owasp.encoder.Encode#forJavaScript(String)} - */ - public static String encodeCharacter(char[] immune, Character c) { - - // check for immune characters - if (containsCharacter(c, immune)) { - return "" + c; - } - - // check for alphanumeric characters - String hex = getHexForNonAlphanumeric(c); - if (hex == null) { - return "" + c; - } - - // Do not use these shortcuts as they can be used to break out of a - // context - // if ( ch == 0x00 ) return "\\0"; - // if ( ch == 0x08 ) return "\\b"; - // if ( ch == 0x09 ) return "\\t"; - // if ( ch == 0x0a ) return "\\n"; - // if ( ch == 0x0b ) return "\\v"; - // if ( ch == 0x0c ) return "\\f"; - // if ( ch == 0x0d ) return "\\r"; - // if ( ch == 0x22 ) return "\\\""; - // if ( ch == 0x27 ) return "\\'"; - // if ( ch == 0x5c ) return "\\\\"; - - // encode up to 256 with \\xHH - String temp = Integer.toHexString(c); - if (c < 256) { - String pad = "00".substring(temp.length()); - return "\\x" + pad + temp.toUpperCase(); - } - - // otherwise encode with \\uHHHH - String pad = "0000".substring(temp.length()); - return "\\u" + pad + temp.toUpperCase(); - } } diff --git a/zcommon/src/main/java/org/zkoss/lang/Strings.java b/zcommon/src/main/java/org/zkoss/lang/Strings.java index b0311d0dcb..61b07142da 100644 --- a/zcommon/src/main/java/org/zkoss/lang/Strings.java +++ b/zcommon/src/main/java/org/zkoss/lang/Strings.java @@ -17,7 +17,8 @@ package org.zkoss.lang; import java.io.UnsupportedEncodingException; -import java.util.Arrays; + +import org.owasp.encoder.Encode; import org.zkoss.mesg.MCommon; import org.zkoss.util.IllegalSyntaxException; @@ -28,10 +29,6 @@ * @author tomyeh */ public class Strings { - /** Used with {@link #escape} to escape a string in - * JavaScript. It assumes the string will be enclosed with a single quote. - */ - public static final String ESCAPE_JAVASCRIPT = "'\n\r\t\f\\/!"; public static final String EMPTY = ""; /** * Returns true if the string is null or empty. @@ -274,7 +271,7 @@ public static final int nextWhitespace(CharSequence src, int from) { * * @param src the string to process. If null, null is returned. * @param specials a string of characters that shall be escaped/quoted - * To escape a string in JavaScript code snippet, you can use {@link #ESCAPE_JAVASCRIPT}. + * To escape a string in JavaScript code snippet, you can use {@link Encode#forJavaScript(String)}. * @see #unescape */ public static final String escape(String src, String specials) { @@ -284,10 +281,7 @@ public static final String escape(String src, String specials) { int k = 0; for (char c : chars) { - if (shallEncodeUnicode(c, specials)) { // Check if it should be Unicode encoded - String encoded = encodeUnicode(c); - sb.append('\\').append(encoded); // Append encoded form with a backslash - } else if (specials.indexOf(c) >= 0) { // Check if char is a special character to escape + if (specials.indexOf(c) >= 0) { // Check if char is a special character to escape char escaped = escapeSpecial(src, c, k, specials); if (escaped != (char) 0) { sb.append('\\').append(escaped); // Append escaped character with a backslash @@ -310,144 +304,9 @@ private static char escapeSpecial(CharSequence src, case '\t': return 't'; case '\r': return 'r'; case '\f': return 'f'; - case '/': - String key; - //escape - if (ESCAPE_JAVASCRIPT.equals(specials) // handle it specially - && (k <= 0 || src.charAt(k - 1) != '<' - || k + 8 > src.length() || !("script>" - .equalsIgnoreCase((key = src.subSequence(k + 1, - k + 8).toString())) || "script " - .equalsIgnoreCase(key)))) { - return (char) 0; // don't escape - } - break; - case '!': - //escape For more information about the XSS diff --git a/zktest/src/test/java/org/zkoss/zktest/zats/test2/B70_ZK_1750Test.java b/zktest/src/test/java/org/zkoss/zktest/zats/test2/B70_ZK_1750Test.java index 73d637eeab..16fa5f5208 100644 --- a/zktest/src/test/java/org/zkoss/zktest/zats/test2/B70_ZK_1750Test.java +++ b/zktest/src/test/java/org/zkoss/zktest/zats/test2/B70_ZK_1750Test.java @@ -1,9 +1,9 @@ /* B70_ZK_1750Test.java Purpose: - + Description: - + History: Wed Mar 27 14:19:15 CST 2019, Created by rudyhuang @@ -35,9 +35,9 @@ public void test() throws Exception { String script = runonce.html(); if (!script.contains("zkmx(")) continue; - assertThat(script, containsString(",cu:'\\x2F")); - assertThat(script, containsString(",uu:'\\x2F")); - assertThat(script, containsString(",ru:'\\x2F")); + assertThat(script, containsString(",cu:'\\x27")); + assertThat(script, containsString(",uu:'\\x27")); + assertThat(script, containsString(",ru:'\\x27")); } } } diff --git a/zul/src/main/java/org/zkoss/zul/SimpleConstraint.java b/zul/src/main/java/org/zkoss/zul/SimpleConstraint.java index 2ef31a5dcb..3be5077148 100644 --- a/zul/src/main/java/org/zkoss/zul/SimpleConstraint.java +++ b/zul/src/main/java/org/zkoss/zul/SimpleConstraint.java @@ -1,9 +1,9 @@ /* SimpleConstraint.java Purpose: - + Description: - + History: Tue Jun 28 13:58:11 2005, Created by tomyeh @@ -21,8 +21,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.owasp.encoder.Encode; + import org.zkoss.lang.Classes; -import org.zkoss.lang.Strings; import org.zkoss.util.Dates; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.UiException; @@ -34,7 +35,7 @@ * *

Depending on the component (such as {@link Intbox} and {@link Datebox}, * you could combine the flags, such as {@link #NO_POSITIVE} + {@link #NO_ZERO} - * to accept only negative number. + * to accept only negative number. * * @author tomyeh */ @@ -72,46 +73,46 @@ public class SimpleConstraint implements Constraint, ClientConstraint, java.io.S /** Today is not allowed. (Only date part is compared) */ public static final int NO_TODAY = NO_ZERO; - /** The Error-box position. + /** The Error-box position. */ public static final int BEFORE_START = 0x1000; - /** The Error-box position. + /** The Error-box position. */ public static final int BEFORE_END = 0x2000; - /** The Error-box position. + /** The Error-box position. */ public static final int END_BEFORE = 0x3000; - /** The Error-box position. + /** The Error-box position. */ public static final int END_AFTER = 0x4000; - /** The Error-box position. + /** The Error-box position. */ public static final int AFTER_END = 0x5000; - /** The Error-box position. + /** The Error-box position. */ public static final int AFTER_START = 0x6000; - /** The Error-box position. + /** The Error-box position. */ public static final int START_AFTER = 0x7000; - /** The Error-box position. + /** The Error-box position. */ public static final int START_BEFORE = 0x8000; - /** The Error-box position. + /** The Error-box position. */ public static final int OVERLAP = 0x9000; - /** The Error-box position. + /** The Error-box position. */ public static final int OVERLAP_END = 0xa000; - /** The Error-box position. + /** The Error-box position. */ public static final int OVERLAP_BEFORE = 0xb000; - /** The Error-box position. + /** The Error-box position. */ public static final int OVERLAP_AFTER = 0xc000; - /** The Error-box position. + /** The Error-box position. */ public static final int AT_POINTER = 0xd000; - /** The Error-box position. + /** The Error-box position. */ public static final int AFTER_POINTER = 0xe000; @@ -464,7 +465,7 @@ private int getMessageForDateDenied() { //ClientConstraint// public String getClientConstraint() { if (_raw != null) - return '\'' + Strings.escape(_raw, Strings.ESCAPE_JAVASCRIPT) + '\''; + return '\'' + Encode.forJavaScript(_raw) + '\''; final StringBuffer sb = new StringBuffer("new zul.inp.SimpleConstraint("); if (_flags != 0 || _regex != null || _errmsg != null) { @@ -473,13 +474,13 @@ public String getClientConstraint() { sb.append(','); if (_regex != null) { sb.append('\''); - Strings.escape(sb, _regex.pattern(), Strings.ESCAPE_JAVASCRIPT); + sb.append(Encode.forJavaScript(_regex.pattern())); sb.append('\''); } else sb.append("null"); if (_errmsg != null) { sb.append(",'"); - Strings.escape(sb, _errmsg, Strings.ESCAPE_JAVASCRIPT); + sb.append(Encode.forJavaScript(_errmsg)); sb.append('\''); } } diff --git a/zul/src/main/java/org/zkoss/zul/impl/Utils.java b/zul/src/main/java/org/zkoss/zul/impl/Utils.java index b03deb41e1..a05ee29629 100644 --- a/zul/src/main/java/org/zkoss/zul/impl/Utils.java +++ b/zul/src/main/java/org/zkoss/zul/impl/Utils.java @@ -316,7 +316,7 @@ public static final String outLocaleJavaScript() { private static void addLocaleJS(StringBuffer sb, String name, int mesgCode) { sb.append('\n').append(name).append(":'"); - Strings.escape(sb, Messages.get(mesgCode), Strings.ESCAPE_JAVASCRIPT); + sb.append(Encode.forJavaScript(Messages.get(mesgCode))); sb.append("',"); }