diff --git a/core/src/main/cfml/context/admin/server.request.cfm b/core/src/main/cfml/context/admin/server.request.cfm index 015b589386..deb4420410 100755 --- a/core/src/main/cfml/context/admin/server.request.cfm +++ b/core/src/main/cfml/context/admin/server.request.cfm @@ -270,6 +270,18 @@ Error Output ---> #appSettings.scriptProtect# + + + + + +
Regex-Filter + +
+ +
+
+
this.scriptprotect="#appSettings.scriptProtect#"; diff --git a/core/src/main/java/lucee/runtime/config/ConfigImpl.java b/core/src/main/java/lucee/runtime/config/ConfigImpl.java index 091b74d7cf..7aee4b93c8 100755 --- a/core/src/main/java/lucee/runtime/config/ConfigImpl.java +++ b/core/src/main/java/lucee/runtime/config/ConfigImpl.java @@ -37,6 +37,7 @@ import java.util.Map.Entry; import java.util.TimeZone; import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Pattern; import org.osgi.framework.BundleException; import org.osgi.framework.Version; @@ -306,6 +307,7 @@ public abstract class ConfigImpl extends ConfigBase implements ConfigPro { private ApplicationListener applicationListener; private int scriptProtect = ApplicationContext.SCRIPT_PROTECT_ALL; + private ArrayList scriptProtectRegexList = new ArrayList<>(); private ProxyData proxy = null; @@ -2322,6 +2324,18 @@ protected void setScriptProtect(int scriptProtect) { this.scriptProtect = scriptProtect; } + public ArrayList getScriptProtectRegexList() { + return scriptProtectRegexList; + } + + public void setScriptProtectRegexList(ArrayList scriptProtectRegexList) { + this.scriptProtectRegexList = scriptProtectRegexList; + } + + public void addScriptProtectRegex(Pattern scriptProtectRegex) { + this.scriptProtectRegexList.add(scriptProtectRegex); + } + /** * @return the proxyPassword */ diff --git a/core/src/main/java/lucee/runtime/config/SingleContextConfigWeb.java b/core/src/main/java/lucee/runtime/config/SingleContextConfigWeb.java index d92740e0db..c0799e0aa5 100644 --- a/core/src/main/java/lucee/runtime/config/SingleContextConfigWeb.java +++ b/core/src/main/java/lucee/runtime/config/SingleContextConfigWeb.java @@ -4,14 +4,9 @@ import java.io.PrintWriter; import java.net.URL; import java.nio.charset.Charset; -import java.util.Collection; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.TimeZone; +import java.util.regex.Pattern; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; @@ -609,7 +604,12 @@ public int getScriptProtect() { return cs.getScriptProtect(); } - @Override + @Override + public ArrayList getScriptProtectRegexList() { + return cs.getScriptProtectRegexList(); + } + + @Override public ProxyData getProxyData() { return cs.getProxyData(); } diff --git a/core/src/main/java/lucee/runtime/config/XMLConfigWebFactory.java b/core/src/main/java/lucee/runtime/config/XMLConfigWebFactory.java index cba9dadffe..7ca8bb328a 100755 --- a/core/src/main/java/lucee/runtime/config/XMLConfigWebFactory.java +++ b/core/src/main/java/lucee/runtime/config/XMLConfigWebFactory.java @@ -48,6 +48,7 @@ import java.util.Set; import java.util.TimeZone; import java.util.UUID; +import java.util.regex.Pattern; import javax.servlet.ServletConfig; @@ -167,6 +168,7 @@ import lucee.runtime.regex.RegexFactory; import lucee.runtime.search.DummySearchEngine; import lucee.runtime.search.SearchEngine; +import lucee.runtime.security.ScriptProtect; import lucee.runtime.security.SecurityManager; import lucee.runtime.security.SecurityManagerImpl; import lucee.runtime.spooler.SpoolerEngineImpl; @@ -461,6 +463,8 @@ synchronized static void load(ConfigServerImpl cs, ConfigImpl config, Document d if (LOG) LogUtil.logGlobal(ThreadLocalPageContext.getConfig(cs == null ? config : cs), Log.LEVEL_INFO, XMLConfigWebFactory.class.getName(), "loaded orm"); _loadCacheHandler(cs, config, doc, log); if (LOG) LogUtil.logGlobal(ThreadLocalPageContext.getConfig(cs == null ? config : cs), Log.LEVEL_INFO, XMLConfigWebFactory.class.getName(), "loaded cache handlers"); + _loadScriptProtect(cs, config, doc, log); + if (LOG) LogUtil.logGlobal(ThreadLocalPageContext.getConfig(cs == null ? config : cs), Log.LEVEL_INFO, XMLConfigWebFactory.class.getName(), "loaded scriptprotect regex"); _loadCharset(cs, config, doc, log); if (LOG) LogUtil.logGlobal(ThreadLocalPageContext.getConfig(cs == null ? config : cs), Log.LEVEL_INFO, XMLConfigWebFactory.class.getName(), "loaded charset"); _loadApplication(cs, config, doc, mode, log); @@ -720,6 +724,29 @@ private static void _loadCacheHandler(ConfigServerImpl configServer, ConfigImpl } } + private static void _loadScriptProtect(ConfigServerImpl configServer, ConfigImpl config, Document doc, Log log) { + try { + config.setScriptProtectRegexList(new ArrayList<>()); + Element root = doc == null ? null : getChildByName(doc.getDocumentElement(), "scriptprotect"); + Element[] regexFilters = root == null ? null : getChildren(root, "filter-regex"); + if (!ArrayUtil.isEmpty(regexFilters)) { + for (Element regexFilter : regexFilters) { + String regexValue = getAttr(regexFilter, "value"); + Pattern regexPattern = Pattern.compile(regexValue, Pattern.DOTALL | Pattern.CASE_INSENSITIVE); + config.addScriptProtectRegex(regexPattern); + } + } + else { + //Loading default scriptprotect settings + Pattern invalidTagRegex = Pattern.compile(ScriptProtect.INVALID_TAG_REGEX_DEFAULT, Pattern.DOTALL | Pattern.CASE_INSENSITIVE); + config.addScriptProtectRegex(invalidTagRegex); + } + } + catch (Exception e) { + log(config, log, e); + } + } + private static void _loadDumpWriter(ConfigServerImpl configServer, ConfigImpl config, Document doc, Log log) { try { boolean hasCS = configServer != null; diff --git a/core/src/main/java/lucee/runtime/security/ScriptProtect.java b/core/src/main/java/lucee/runtime/security/ScriptProtect.java index 8946435fc2..31210051c4 100644 --- a/core/src/main/java/lucee/runtime/security/ScriptProtect.java +++ b/core/src/main/java/lucee/runtime/security/ScriptProtect.java @@ -20,7 +20,10 @@ import java.util.Iterator; import java.util.Map.Entry; +import java.util.regex.Pattern; +import lucee.runtime.config.ConfigWebPro; +import lucee.runtime.engine.ThreadLocalPageContext; import lucee.runtime.type.Collection.Key; import lucee.runtime.type.Struct; @@ -29,10 +32,10 @@ */ public final class ScriptProtect { - public static final String[] invalids = new String[] { "object", "embed", "script", "applet", "meta", "iframe" }; + public static final String INVALID_TAG_REGEX_DEFAULT = " 'z') && (c < 'A' || c > 'Z')) break; - } - tagName = str.substring(index + 1, endIndex); - - if (compareTagName(tagName)) { - if (sb == null) { - sb = new StringBuilder(); - last = 0; - } - sb.append(str.substring(last, index + 1)); - sb.append("invalidTag"); - last = endIndex; - } - else if (sb != null) { - sb.append(str.substring(last, index + 1)); - last = index + 1; - } - else last = index + 1; - - } - if (sb != null) { - if (last != str.length()) sb.append(str.substring(last)); - return sb.toString(); - } - return str; + ConfigWebPro config = (ConfigWebPro) ThreadLocalPageContext.get().getConfig(); + for(Pattern regexFilterPattern : config.getScriptProtectRegexList()){ + str = invalidateMaliciousInput(str, regexFilterPattern); + } + return str; } - private static boolean compareTagName(String tagName) { - for (int i = 0; i < invalids.length; i++) { - if (invalids[i].equalsIgnoreCase(tagName)) return true; - } - return false; - } + private static String invalidateMaliciousInput(String str, Pattern regexPattern) { + return regexPattern.matcher(str).replaceAll("invalid"); + } } \ No newline at end of file diff --git a/core/src/main/java/lucee/runtime/tag/Admin.java b/core/src/main/java/lucee/runtime/tag/Admin.java index 66cb7a8c0d..9fda0bd6b7 100755 --- a/core/src/main/java/lucee/runtime/tag/Admin.java +++ b/core/src/main/java/lucee/runtime/tag/Admin.java @@ -39,6 +39,7 @@ import java.util.TimeZone; import java.util.jar.Attributes; import java.util.jar.Manifest; +import java.util.regex.Pattern; import javax.servlet.ServletConfig; import javax.servlet.jsp.tagext.Tag; @@ -4411,6 +4412,11 @@ private void doGetApplicationSetting() throws PageException { Struct sct = new StructImpl(); pageContext.setVariable(getString("admin", action, "returnVariable"), sct); sct.set("scriptProtect", AppListenerUtil.translateScriptProtect(config.getScriptProtect())); + ArrayList scriptProtectRegexList = new ArrayList<>(); + for(Pattern pattern : config.getScriptProtectRegexList()) { + scriptProtectRegexList.add(pattern.pattern()); + } + sct.set("scriptProtectRegexList", scriptProtectRegexList); // request timeout TimeSpan ts = config.getRequestTimeout(); diff --git a/core/src/main/java/resource/config/server.xml b/core/src/main/java/resource/config/server.xml index 3c3297eb4d..55fb3dc6a9 100755 --- a/core/src/main/java/resource/config/server.xml +++ b/core/src/main/java/resource/config/server.xml @@ -320,7 +320,14 @@ Path placeholders: --> - + + + + + +