Skip to content

Commit 4917fba

Browse files
authored
Merge pull request #596 from UzJu/beta
feat: 漏洞检测-新增QLExpress表达式注入检测时判断安全配置是否开启
2 parents c970c6b + d1c59b5 commit 4917fba

File tree

5 files changed

+109
-2
lines changed

5 files changed

+109
-2
lines changed

dongtai-core/src/main/java/io/dongtai/iast/core/AgentEngine.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import io.dongtai.iast.common.state.AgentState;
66
import io.dongtai.iast.common.state.State;
77
import io.dongtai.iast.core.handler.hookpoint.models.policy.PolicyManager;
8+
import io.dongtai.iast.core.handler.hookpoint.vulscan.dynamic.FastjsonCheck;
9+
import io.dongtai.iast.core.handler.hookpoint.vulscan.dynamic.QLExpressCheck;
810
import io.dongtai.iast.core.init.IEngine;
911
import io.dongtai.iast.core.init.impl.ConfigEngine;
1012
import io.dongtai.iast.core.init.impl.TransformEngine;
@@ -92,6 +94,10 @@ public static void stop() {
9294
public static void destroy(String mode, String propertiesFilePath, Instrumentation inst) {
9395
try {
9496
DongTaiLog.info("Uninstall engine");
97+
// 卸载对FastJson和QLExpress的调用
98+
FastjsonCheck.clearJsonClassLoader();
99+
FastjsonCheck.clearParseConfigClassLoader();
100+
QLExpressCheck.clearQLClassLoader();
95101
AgentEngine agentEngine = AgentEngine.getInstance();
96102
assert agentEngine != null;
97103
agentEngine.destroy();

dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/IastClassFileTransformer.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.dongtai.iast.core.handler.hookpoint.SpyDispatcherImpl;
1111
import io.dongtai.iast.core.handler.hookpoint.models.policy.PolicyManager;
1212
import io.dongtai.iast.core.handler.hookpoint.vulscan.dynamic.FastjsonCheck;
13+
import io.dongtai.iast.core.handler.hookpoint.vulscan.dynamic.QLExpressCheck;
1314
import io.dongtai.iast.core.utils.AsmUtils;
1415
import io.dongtai.iast.core.utils.PropertyUtils;
1516
import io.dongtai.iast.core.utils.matcher.ConfigMatcher;
@@ -145,7 +146,9 @@ public byte[] transform(final ClassLoader loader,
145146

146147
try {
147148
ScopeManager.SCOPE_TRACKER.getPolicyScope().enterAgent();
148-
149+
if (" com/ql/util/express/config/QLExpressRunStrategy".substring(1).equals(internalClassName)){
150+
QLExpressCheck.setQLClassLoader(loader);
151+
}
149152
if (" com/alibaba/fastjson/JSON".substring(1).equals(internalClassName)) {
150153
FastjsonCheck.setJsonClassLoader(loader);
151154
} else if (" com/alibaba/fastjson/parser/ParserConfig".substring(1).equals(internalClassName)) {

dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/vulscan/dynamic/DynamicPropagatorScanner.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
public class DynamicPropagatorScanner implements IVulScan {
2626
private final static Set<SinkSafeChecker> SAFE_CHECKERS = new HashSet<>(Arrays.asList(
2727
new FastjsonCheck(),
28-
new XXECheck()
28+
new XXECheck(),
29+
new QLExpressCheck()
2930
));
3031

3132
private final static Set<SinkSourceChecker> SOURCE_CHECKERS = new HashSet<>(Arrays.asList(

dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/vulscan/dynamic/FastjsonCheck.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,12 @@ public static void setJsonClassLoader(ClassLoader jsonClassLoader) {
8383
public static void setParseConfigClassLoader(ClassLoader parseConfigClassLoader) {
8484
PARSE_CONFIG_CLASS_LOADER = parseConfigClassLoader;
8585
}
86+
87+
public static void clearJsonClassLoader(){
88+
JSON_CLASS_LOADER = null;
89+
}
90+
91+
public static void clearParseConfigClassLoader(){
92+
PARSE_CONFIG_CLASS_LOADER = null;
93+
}
8694
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package io.dongtai.iast.core.handler.hookpoint.vulscan.dynamic;
2+
3+
import io.dongtai.iast.core.handler.hookpoint.models.MethodEvent;
4+
import io.dongtai.iast.core.handler.hookpoint.models.policy.SignatureMethodMatcher;
5+
import io.dongtai.iast.core.handler.hookpoint.models.policy.SinkNode;
6+
import io.dongtai.log.DongTaiLog;
7+
8+
import java.lang.reflect.Field;
9+
import java.lang.reflect.Modifier;
10+
import java.util.Arrays;
11+
import java.util.List;
12+
import java.util.Set;
13+
14+
/**
15+
* @author UzJu
16+
* @date 2023/10/24 16:02
17+
* @Site UzzJu.com
18+
* @Comment :)
19+
*/
20+
21+
public class QLExpressCheck implements SinkSafeChecker {
22+
public static List<String> QLExpress_SINK_METHODS = Arrays.asList(
23+
" com.ql.util.express.ExpressRunner.parseInstructionSet(java.lang.String)".substring(1)
24+
);
25+
private String policySignature;
26+
private static ClassLoader QL_CLASS_LOADER;
27+
28+
@Override
29+
public boolean match(MethodEvent event, SinkNode sinkNode) {
30+
if (sinkNode.getMethodMatcher() instanceof SignatureMethodMatcher) {
31+
this.policySignature = ((SignatureMethodMatcher) sinkNode.getMethodMatcher()).getSignature().toString();
32+
}
33+
34+
return QLExpress_SINK_METHODS.contains(this.policySignature);
35+
}
36+
37+
@Override
38+
public boolean isSafe(MethodEvent event, SinkNode sinkNode){
39+
/**
40+
* The QLExpress component provides the forbidInvokeSecurityRiskMethods configuration function to enable blacklist detection. Therefore, in addition to determining the sink point, you must also determine if the user has this configuration enabled.
41+
* If this configuration is enabled, you will be prompted when calling a blacklisted class: com.ql.util.express.exception.QLSecurityRiskException: An unsafe system method was called using QLExpress: public java.lang.Process java. lang.Runtime.exec(java.lang.String) throws java.io.IOException
42+
* */
43+
DongTaiLog.debug("Start determining whether the forbidInvokeSecurityRiskMethods field of the QLExpress component is true or not.");
44+
try {
45+
Class<?> cls;
46+
if (QL_CLASS_LOADER == null){
47+
cls = Class.forName(" com.ql.util.express.config.QLExpressRunStrategy".substring(1));
48+
}else {
49+
cls = Class.forName(" com.ql.util.express.config.QLExpressRunStrategy".substring(1), false, QL_CLASS_LOADER);
50+
}
51+
52+
Field getBlackListField = cls.getDeclaredField("forbidInvokeSecurityRiskMethods");
53+
Field getSendBoxModeField = cls.getDeclaredField("sandboxMode");
54+
Field getWhiteListField = cls.getDeclaredField("SECURE_METHOD_LIST");
55+
56+
if (Modifier.isStatic(getBlackListField.getModifiers()) && Modifier.isPrivate(getBlackListField.getModifiers()) && Modifier.isStatic(getSendBoxModeField.getModifiers()) && Modifier.isPrivate(getSendBoxModeField.getModifiers()) && Modifier.isStatic(getWhiteListField.getModifiers()) && Modifier.isPrivate(getWhiteListField.getModifiers())) {
57+
// Make private fields accessible to reflection
58+
getBlackListField.setAccessible(true);
59+
getSendBoxModeField.setAccessible(true);
60+
getWhiteListField.setAccessible(true);
61+
62+
// get fields value
63+
boolean blackListBoolean = getBlackListField.getBoolean(null);
64+
boolean sendBoxBoolean = getSendBoxModeField.getBoolean(null);
65+
Set<String> secureMethodList = (Set<String>) getWhiteListField.get(null);
66+
DongTaiLog.debug("SECURE_METHOD_LIST = " + secureMethodList);
67+
DongTaiLog.debug("sandboxMode = " + sendBoxBoolean);
68+
DongTaiLog.debug("forbidInvokeSecurityRiskMethods = " + blackListBoolean);
69+
// All three conditions need to be met
70+
return (secureMethodList != null && !secureMethodList.isEmpty()) || sendBoxBoolean || blackListBoolean;
71+
} else {
72+
DongTaiLog.debug("Field is not static and private.");
73+
return true;
74+
}
75+
}catch (Throwable e){
76+
DongTaiLog.debug("An error occurred while retrieving the fields of the QLExpress component.: {}, {}",
77+
e.getClass().getName() + ": " + e.getMessage(),
78+
e.getCause() != null ? e.getCause().getMessage() : "");
79+
return true;
80+
}
81+
}
82+
public static void setQLClassLoader(ClassLoader qlClassLoader) {
83+
QL_CLASS_LOADER = qlClassLoader;
84+
}
85+
86+
public static void clearQLClassLoader(){
87+
QL_CLASS_LOADER = null;
88+
}
89+
}

0 commit comments

Comments
 (0)