Skip to content

Commit 8460db5

Browse files
Upgrade libddwaf to 1.28.1 (#9543)
Signed-off-by: sezen.leblay <[email protected]>
1 parent ec2797e commit 8460db5

File tree

8 files changed

+181
-46
lines changed

8 files changed

+181
-46
lines changed
Submodule integrations-core updated 4981 files

dd-java-agent/appsec/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ dependencies {
1414
implementation project(':internal-api')
1515
implementation project(':communication')
1616
implementation project(':telemetry')
17-
implementation group: 'io.sqreen', name: 'libsqreen', version: '17.0.0'
17+
implementation group: 'io.sqreen', name: 'libsqreen', version: '17.1.0'
1818
implementation libs.moshi
1919

2020
testImplementation libs.bytebuddy

dd-java-agent/appsec/src/main/java/com/datadog/appsec/config/AppSecConfigServiceImpl.java

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,8 @@
3939
import com.datadog.ddwaf.exception.InvalidRuleSetException;
4040
import com.datadog.ddwaf.exception.UnclassifiedWafException;
4141
import com.squareup.moshi.JsonAdapter;
42-
import com.squareup.moshi.JsonReader;
43-
import com.squareup.moshi.JsonWriter;
4442
import com.squareup.moshi.Moshi;
43+
import com.squareup.moshi.Types;
4544
import datadog.remoteconfig.ConfigurationEndListener;
4645
import datadog.remoteconfig.ConfigurationPoller;
4746
import datadog.remoteconfig.PollingRateHinter;
@@ -53,7 +52,6 @@
5352
import datadog.trace.api.ConfigOrigin;
5453
import datadog.trace.api.ProductActivation;
5554
import datadog.trace.api.UserIdCollectionMode;
56-
import datadog.trace.api.telemetry.LogCollector;
5755
import datadog.trace.api.telemetry.WafMetricCollector;
5856
import java.io.ByteArrayInputStream;
5957
import java.io.FileInputStream;
@@ -68,7 +66,6 @@
6866
import java.util.Set;
6967
import java.util.concurrent.ConcurrentHashMap;
7068
import java.util.concurrent.atomic.AtomicBoolean;
71-
import javax.annotation.Nullable;
7269
import okio.Okio;
7370
import org.slf4j.Logger;
7471
import org.slf4j.LoggerFactory;
@@ -96,25 +93,10 @@ public class AppSecConfigServiceImpl implements AppSecConfigService {
9693
new WAFInitializationResultReporter();
9794
private final WAFStatsReporter statsReporter = new WAFStatsReporter();
9895

99-
private static final JsonAdapter<Object> ADAPTER =
96+
private static final JsonAdapter<Map<String, Object>> ADAPTER =
10097
new Moshi.Builder()
101-
.add(
102-
Double.class,
103-
new JsonAdapter<Number>() {
104-
@Override
105-
public Number fromJson(JsonReader reader) throws IOException {
106-
double value = reader.nextDouble();
107-
long longValue = (long) value;
108-
return value % 1 == 0 ? longValue : value;
109-
}
110-
111-
@Override
112-
public void toJson(JsonWriter writer, @Nullable Number value) throws IOException {
113-
throw new UnsupportedOperationException();
114-
}
115-
})
11698
.build()
117-
.adapter(Object.class);
99+
.adapter(Types.newParameterizedType(Map.class, String.class, Object.class));
118100

119101
private boolean hasUserWafConfig;
120102
private boolean defaultConfigActivated;
@@ -309,7 +291,6 @@ private void handleWafUpdateResultReport(String configKey, Map<String, Object> r
309291
}
310292

311293
// TODO: Send diagnostics via telemetry
312-
final LogCollector telemetryLogger = LogCollector.get();
313294

314295
initReporter.setReportForPublication(wafDiagnostics);
315296
if (wafDiagnostics.rulesetVersion != null
@@ -488,8 +469,7 @@ private static Map<String, Object> loadDefaultWafConfig() throws IOException {
488469
throw new IOException("Resource " + DEFAULT_CONFIG_LOCATION + " not found");
489470
}
490471

491-
Map<String, Object> ret =
492-
(Map<String, Object>) ADAPTER.fromJson(Okio.buffer(Okio.source(is)));
472+
Map<String, Object> ret = ADAPTER.fromJson(Okio.buffer(Okio.source(is)));
493473

494474
StandardizedLogging._initialConfigSourceAndLibddwafVersion(log, "<bundled config>");
495475
if (log.isInfoEnabled()) {
@@ -506,8 +486,7 @@ private static Map<String, Object> loadUserWafConfig(Config tracerConfig) throws
506486
return null;
507487
}
508488
try (InputStream is = new FileInputStream(filename)) {
509-
Map<String, Object> ret =
510-
(Map<String, Object>) ADAPTER.fromJson(Okio.buffer(Okio.source(is)));
489+
Map<String, Object> ret = ADAPTER.fromJson(Okio.buffer(Okio.source(is)));
511490

512491
StandardizedLogging._initialConfigSourceAndLibddwafVersion(log, filename);
513492
if (log.isInfoEnabled()) {

dd-java-agent/appsec/src/main/java/com/datadog/appsec/ddwaf/WAFModule.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import datadog.trace.api.ProductActivation;
3535
import datadog.trace.api.ProductTraceSource;
3636
import datadog.trace.api.gateway.Flow;
37-
import datadog.trace.api.sampling.PrioritySampling;
3837
import datadog.trace.api.telemetry.LogCollector;
3938
import datadog.trace.api.telemetry.WafMetricCollector;
4039
import datadog.trace.api.time.SystemTimeSource;
@@ -432,9 +431,6 @@ public void onDataAvailable(
432431
}
433432
}
434433

435-
reqCtx.setKeepType(
436-
resultWithData.keep ? PrioritySampling.USER_KEEP : PrioritySampling.USER_DROP);
437-
438434
if (resultWithData.attributes != null && !resultWithData.attributes.isEmpty()) {
439435
reqCtx.reportDerivatives(resultWithData.attributes);
440436
}

dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/AppSecRequestContext.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import datadog.trace.api.Config;
1414
import datadog.trace.api.http.StoredBodySupplier;
1515
import datadog.trace.api.internal.TraceSegment;
16-
import datadog.trace.api.sampling.PrioritySampling;
1716
import datadog.trace.util.stacktrace.StackTraceEvent;
1817
import java.io.Closeable;
1918
import java.util.*;
@@ -147,7 +146,6 @@ public class AppSecRequestContext implements DataBundle, Closeable {
147146

148147
private volatile boolean keepOpenForApiSecurityPostProcessing;
149148
private volatile Long apiSecurityEndpointHash;
150-
private volatile byte keepType = PrioritySampling.SAMPLER_KEEP;
151149

152150
private static final AtomicIntegerFieldUpdater<AppSecRequestContext> WAF_TIMEOUTS_UPDATER =
153151
AtomicIntegerFieldUpdater.newUpdater(AppSecRequestContext.class, "wafTimeouts");
@@ -363,14 +361,6 @@ public Long getApiSecurityEndpointHash() {
363361
return this.apiSecurityEndpointHash;
364362
}
365363

366-
public void setKeepType(byte keepType) {
367-
this.keepType = keepType;
368-
}
369-
370-
public byte getKeepType() {
371-
return this.keepType;
372-
}
373-
374364
void addRequestHeader(String name, String value) {
375365
if (finishedRequestHeaders) {
376366
throw new IllegalStateException("Request headers were said to be finished before");

dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import static com.datadog.appsec.gateway.AppSecRequestContext.DEFAULT_REQUEST_HEADERS_ALLOW_LIST;
66
import static com.datadog.appsec.gateway.AppSecRequestContext.REQUEST_HEADERS_ALLOW_LIST;
77
import static com.datadog.appsec.gateway.AppSecRequestContext.RESPONSE_HEADERS_ALLOW_LIST;
8-
import static datadog.trace.bootstrap.instrumentation.api.Tags.SAMPLING_PRIORITY;
98

109
import com.datadog.appsec.AppSecSystem;
1110
import com.datadog.appsec.api.security.ApiSecuritySampler;
@@ -750,9 +749,6 @@ private NoopFlow onRequestEnded(RequestContext ctx_, IGSpanInfo spanInfo) {
750749

751750
// If detected any events - mark span at appsec.event
752751
if (!collectedEvents.isEmpty()) {
753-
// Set asm keep in case that root span was not available when events are detected
754-
traceSeg.setTagTop(Tags.ASM_KEEP, true);
755-
traceSeg.setTagTop(SAMPLING_PRIORITY, ctx.getKeepType());
756752
traceSeg.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM);
757753
traceSeg.setTagTop("appsec.event", true);
758754
traceSeg.setTagTop("network.client.ip", ctx.getPeerAddress());

dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/ddwaf/WAFModuleSpecification.groovy

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import datadog.trace.api.Config
4040
import datadog.trace.api.ConfigDefaults
4141
import datadog.trace.api.gateway.Flow
4242
import datadog.trace.api.internal.TraceSegment
43+
import datadog.trace.api.sampling.PrioritySampling
4344
import datadog.trace.api.telemetry.RuleType
4445
import datadog.trace.api.telemetry.WafMetricCollector
4546
import datadog.trace.api.telemetry.WafMetricCollector.WafErrorCode as InternalWafErrorCode
@@ -1983,6 +1984,111 @@ class WAFModuleSpecification extends DDSpecification {
19831984
!flow3.blocking
19841985
}
19851986

1987+
void 'test trace tagging rule with attributes, no keep and event (dynamic value extraction)'() {
1988+
setup:
1989+
def rulesConfig = [
1990+
version: '2.1',
1991+
metadata: [
1992+
rules_version: '1.2.7'
1993+
],
1994+
rules: [
1995+
[
1996+
id: 'arachni_rule',
1997+
name: 'Arachni',
1998+
tags: [
1999+
type: 'security_scanner',
2000+
category: 'attack_attempt'
2001+
],
2002+
conditions: [
2003+
[
2004+
parameters: [
2005+
inputs: [
2006+
[
2007+
address: 'server.request.headers.no_cookies',
2008+
key_path: ['user-agent']
2009+
]
2010+
],
2011+
regex: '^Arachni\\/v'
2012+
],
2013+
operator: 'match_regex'
2014+
]
2015+
],
2016+
transformers: [],
2017+
on_match: ['block']
2018+
]
2019+
],
2020+
rules_compat: [
2021+
[
2022+
id: 'ttr-000-004',
2023+
name: 'Trace Tagging Rule: Attributes, No Keep, Event',
2024+
tags: [
2025+
type: 'security_scanner',
2026+
category: 'attack_attempt'
2027+
],
2028+
conditions: [
2029+
[
2030+
parameters: [
2031+
inputs: [
2032+
[
2033+
address: 'server.request.headers.no_cookies',
2034+
key_path: ['user-agent']
2035+
]
2036+
],
2037+
regex: '^TraceTagging\\/v4'
2038+
],
2039+
operator: 'match_regex'
2040+
]
2041+
],
2042+
output: [
2043+
event: true,
2044+
keep: false,
2045+
attributes: [
2046+
'_dd.appsec.trace.integer': [
2047+
value: 1729
2048+
],
2049+
'_dd.appsec.trace.agent': [
2050+
address: 'server.request.headers.no_cookies',
2051+
key_path: ['user-agent']
2052+
]
2053+
]
2054+
],
2055+
on_match: []
2056+
]
2057+
]
2058+
]
2059+
2060+
when:
2061+
initialRuleAddWithMap(rulesConfig)
2062+
wafModule.applyConfig(reconf)
2063+
2064+
then:
2065+
1 * wafMetricCollector.wafInit(Waf.LIB_VERSION, _, true)
2066+
1 * wafMetricCollector.wafUpdates(_, true)
2067+
1 * reconf.reloadSubscriptions()
2068+
0 * _
2069+
2070+
when: 'test trace tagging rule with attributes, no keep and event (dynamic value extraction)'
2071+
def bundle = MapDataBundle.of(KnownAddresses.HEADERS_NO_COOKIES,
2072+
new CaseInsensitiveMap<List<String>>(['user-agent': 'TraceTagging/v4']))
2073+
def flow = new ChangeableFlow()
2074+
dataListener.onDataAvailable(flow, ctx, bundle, gwCtx)
2075+
ctx.closeWafContext()
2076+
2077+
then:
2078+
1 * ctx.getOrCreateWafContext(_, true, false)
2079+
2 * ctx.getWafMetrics() >> metrics
2080+
1 * ctx.isWafContextClosed() >> false
2081+
1 * ctx.closeWafContext()
2082+
// Should report derivatives with dynamic value extraction - the user-agent value should be extracted
2083+
1 * ctx.reportDerivatives(['_dd.appsec.trace.agent':'TraceTagging/v4', '_dd.appsec.trace.integer': 1729])
2084+
1 * ctx.reportEvents(_ as Collection<AppSecEvent>)
2085+
1 * ctx.isThrottled(null)
2086+
// CRITICAL: Verify that setKeepType is called with USER_DROP when keep: false
2087+
1 * ctx.setKeepType(PrioritySampling.USER_DROP)
2088+
0 * ctx._(*_)
2089+
!flow.blocking // Should not block since keep: false
2090+
}
2091+
19862092
private static class BadConfig implements Map<String, Object> {
19872093
@Delegate
19882094
private Map<String, Object> delegate

dd-smoke-tests/appsec/springboot/src/test/groovy/datadog/smoketest/appsec/TraceTaggingSmokeTest.groovy

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,42 @@ class TraceTaggingSmokeTest extends AbstractAppSecServerSmokeTest {
154154
]
155155
],
156156
on_match: []
157+
],
158+
[
159+
id: 'ttr-000-004',
160+
name: 'Trace Tagging Rule: Attributes, No Keep, Event',
161+
tags: [
162+
type: 'security_scanner',
163+
category: 'attack_attempt'
164+
],
165+
conditions: [
166+
[
167+
parameters: [
168+
inputs: [
169+
[
170+
address: 'server.request.headers.no_cookies',
171+
key_path: ['user-agent']
172+
]
173+
],
174+
regex: '^TraceTagging\\/v4'
175+
],
176+
operator: 'match_regex'
177+
]
178+
],
179+
output: [
180+
event: true,
181+
keep: false,
182+
attributes: [
183+
'_dd.appsec.trace.integer': [
184+
value: 1729
185+
],
186+
'_dd.appsec.trace.agent': [
187+
address: 'server.request.headers.no_cookies',
188+
key_path: ['user-agent']
189+
]
190+
]
191+
],
192+
on_match: []
157193
]
158194
]
159195
]
@@ -265,4 +301,36 @@ class TraceTaggingSmokeTest extends AbstractAppSecServerSmokeTest {
265301
assert appsecJson.triggers != null, "Missing triggers in WAF attack event"
266302
}
267303

304+
def "test trace tagging rule with attributes, no keep and event"() {
305+
when:
306+
String url = "http://localhost:${httpPort}/greeting"
307+
def request = new Request.Builder()
308+
.url(url)
309+
.addHeader("User-Agent", "TraceTagging/v4")
310+
.build()
311+
def response = client.newCall(request).execute()
312+
def responseBodyStr = response.body().string()
313+
waitForTraceCount(1)
314+
315+
then:
316+
responseBodyStr == "Sup AppSec Dawg"
317+
response.code() == 200
318+
rootSpans.size() == 1
319+
320+
def rootSpan = rootSpans[0]
321+
assert rootSpan.meta['_dd.appsec.trace.agent'] != null, "Missing _dd.appsec.trace.agent from span's meta"
322+
assert rootSpan.metrics['_dd.appsec.trace.integer'] != null, "Missing _dd.appsec.trace.integer from span's metrics"
323+
324+
assert rootSpan.meta['_dd.appsec.trace.agent'].startsWith("TraceTagging/v4")
325+
assert rootSpan.metrics['_dd.appsec.trace.integer'] == 1729
326+
327+
// Should NOT have USER_KEEP sampling priority since keep: false
328+
assert rootSpan.metrics.get('_sampling_priority_v1') < 2, "Should not have USER_KEEP sampling priority when keep: false"
329+
330+
// Check for WAF attack event (should exist since event: true)
331+
assert rootSpan.meta['_dd.appsec.json'] != null, "Missing WAF attack event"
332+
def appsecJson = new JsonSlurper().parseText(rootSpan.meta['_dd.appsec.json'])
333+
assert appsecJson.triggers != null, "Missing triggers in WAF attack event"
334+
}
335+
268336
}

0 commit comments

Comments
 (0)