Skip to content

Commit 84c2911

Browse files
committed
feat:新增匹配请求头值的黑名单匹配,使用正则匹配
1 parent 51d792b commit 84c2911

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

dongtai-common/src/main/java/io/dongtai/iast/common/config/RequestDeny.java

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package io.dongtai.iast.common.config;
22

3+
import io.dongtai.log.DongTaiLog;
34
import org.json.JSONException;
45
import org.json.JSONObject;
56

67
import java.util.*;
8+
import java.util.regex.Pattern;
9+
import java.util.regex.PatternSyntaxException;
710

811
public class RequestDeny {
912
private static final String KEY_TARGET_TYPE = "target_type";
@@ -12,7 +15,7 @@ public class RequestDeny {
1215

1316
private static final Map<TargetType, List<Operator>> OPERATOR_MAP = new HashMap<TargetType, List<Operator>>() {{
1417
put(TargetType.URL, Arrays.asList(Operator.EQUAL, Operator.NOT_EQUAL, Operator.CONTAIN, Operator.NOT_CONTAIN));
15-
put(TargetType.HEADER_KEY, Arrays.asList(Operator.EXISTS, Operator.NOT_EXISTS));
18+
put(TargetType.HEADER_KEY, Arrays.asList(Operator.EXISTS, Operator.NOT_EXISTS,Operator.EXISTS_KEY_AND_VALUE));
1619
}};
1720

1821
public enum TargetType {
@@ -47,6 +50,8 @@ public enum Operator {
4750
NOT_CONTAIN("NOT_CONTAIN"),
4851
EXISTS("EXISTS"),
4952
NOT_EXISTS("NOT_EXISTS"),
53+
//此类型是为了兼容请求头的value匹配,此时 value使用:分割格式为key:value 值使用base64编码,需要解码使用,value使用正则匹配
54+
EXISTS_KEY_AND_VALUE("EXISTS_KEY_AND_VALUE"),
5055
;
5156

5257
private final String key;
@@ -93,11 +98,22 @@ public static RequestDeny parse(JSONObject config) {
9398
if (operator == null || !OPERATOR_MAP.get(targetType).contains(operator)) {
9499
return null;
95100
}
96-
97101
String value = config.getString(KEY_VALUE);
98102
if (value == null || value.isEmpty()) {
99103
return null;
100104
}
105+
if (Operator.EXISTS_KEY_AND_VALUE.equals(operator)){
106+
String[] split = value.split(":");
107+
String vle = new String(Base64.getDecoder().decode(split[1]));
108+
try {
109+
Pattern.compile(vle);
110+
} catch (PatternSyntaxException e) {
111+
String key = new String(Base64.getDecoder().decode(split[0]));
112+
DongTaiLog.error("the regex is not valid please check! key:{},value:{}",key,vle);
113+
return null;
114+
}
115+
116+
}
101117

102118
return new RequestDeny(targetType, operator, value);
103119
} catch (JSONException ignore) {
@@ -135,6 +151,18 @@ private boolean matchHeaderKey(Map<String, String> headers) {
135151
if (headers == null || headers.isEmpty()) {
136152
return false;
137153
}
154+
if (Operator.EXISTS_KEY_AND_VALUE.equals(operator)){
155+
String[] split = this.value.split(":");
156+
String key = new String(Base64.getDecoder().decode(split[0])).toLowerCase();
157+
String vle = new String(Base64.getDecoder().decode(split[1]));
158+
159+
for (Map.Entry<String, String> entry : headers.entrySet()) {
160+
if (key.equals(entry.getKey().toLowerCase())) {
161+
Pattern pattern = Pattern.compile(vle);
162+
return pattern.matcher(entry.getValue()).find();
163+
}
164+
}
165+
}
138166

139167
boolean exists = false;
140168
String matchVal = this.value.toLowerCase();
@@ -147,10 +175,12 @@ private boolean matchHeaderKey(Map<String, String> headers) {
147175

148176
if (Operator.EXISTS.equals(operator)) {
149177
return exists;
150-
} else if (Operator.NOT_EXISTS.equals(operator)) {
178+
}
179+
if (Operator.NOT_EXISTS.equals(operator)) {
151180
return !exists;
152181
}
153182

183+
154184
return false;
155185
}
156186

dongtai-common/src/test/java/io/dongtai/iast/common/config/RequestDenyListTest.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public void testMatch() {
1212
Map<String, String> headers = new HashMap<String, String>();
1313
headers.put("key1", "value1");
1414
headers.put("key2", "value2");
15+
headers.put("User-Agent", "Mozilla");
1516

1617
final RequestDeny urlMatch = new RequestDeny(RequestDeny.TargetType.URL,
1718
RequestDeny.Operator.CONTAIN, "foo");
@@ -22,6 +23,14 @@ public void testMatch() {
2223
final RequestDeny headerKeyNotMatch = new RequestDeny(RequestDeny.TargetType.HEADER_KEY,
2324
RequestDeny.Operator.NOT_EXISTS, "key1");
2425

26+
final RequestDeny EXISTS_KEY_AND_VALUE = new RequestDeny(RequestDeny.TargetType.HEADER_KEY,
27+
RequestDeny.Operator.EXISTS_KEY_AND_VALUE, "VXNlci1BZ2VudA==:TW96aWxsYQ==");
28+
29+
30+
boolean match = EXISTS_KEY_AND_VALUE.match(url, headers);
31+
32+
Assert.assertTrue(match);
33+
2534
Map<RequestDenyList, Boolean> tests = new HashMap<RequestDenyList, Boolean>(){{
2635
RequestDenyList requestDenyList = new RequestDenyList();
2736
requestDenyList.addRule(Collections.singletonList(urlMatch));
@@ -79,7 +88,11 @@ public void testMatch() {
7988
requestDenyList.addRule(Collections.singletonList(urlNotMatch));
8089
put(requestDenyList, false);
8190
}};
82-
91+
RequestDenyList requestDenyList = new RequestDenyList();
92+
requestDenyList = new RequestDenyList();
93+
requestDenyList.addRule(Arrays.asList(urlMatch, headerKeyNotMatch));
94+
requestDenyList.addRule(Collections.singletonList(urlNotMatch));
95+
requestDenyList.match(url,headers);
8396
for (Map.Entry<RequestDenyList, Boolean> entry : tests.entrySet()) {
8497
boolean matched = entry.getKey().match(url, headers);
8598
Assert.assertEquals("match " + entry.getKey(), entry.getValue(), matched);

0 commit comments

Comments
 (0)