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#
+
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:
-->
-
+
+
+
+
+
+