Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 00358aa

Browse files
Try to match tainted objects with sources when checking vulnerabilities with unbounded objects (DataDog#6122)
1 parent b1ae59a commit 00358aa

File tree

3 files changed

+87
-4
lines changed

3 files changed

+87
-4
lines changed

‎dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/SinkModuleBase.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.datadog.iast.model.Evidence;
1010
import com.datadog.iast.model.Location;
1111
import com.datadog.iast.model.Range;
12+
import com.datadog.iast.model.Source;
1213
import com.datadog.iast.model.Vulnerability;
1314
import com.datadog.iast.model.VulnerabilityType;
1415
import com.datadog.iast.model.VulnerabilityType.InjectionType;
@@ -57,7 +58,7 @@ protected SinkModuleBase(@Nonnull final Dependencies dependencies) {
5758
if (!overheadController.consumeQuota(Operations.REPORT_VULNERABILITY, span)) {
5859
return null;
5960
}
60-
final Evidence result = newEvidence(value.toString(), ranges);
61+
final Evidence result = buildEvidence(value, ranges);
6162
report(span, type, result);
6263
return result;
6364
}
@@ -119,7 +120,7 @@ protected SinkModuleBase(@Nonnull final Dependencies dependencies) {
119120
return null;
120121
}
121122

122-
final Evidence result = newEvidence(evidence, notMarkedRanges);
123+
final Evidence result = buildEvidence(evidence, notMarkedRanges);
123124
report(span, type, result);
124125
return result;
125126
}
@@ -161,7 +162,7 @@ protected SinkModuleBase(@Nonnull final Dependencies dependencies) {
161162
if (notMarkedRanges == null || notMarkedRanges.length == 0) {
162163
return null;
163164
}
164-
final Evidence result = newEvidence(evidence.toString(), notMarkedRanges);
165+
final Evidence result = buildEvidence(evidence, notMarkedRanges);
165166
report(span, type, result);
166167
return result;
167168
}
@@ -179,6 +180,24 @@ protected StackTraceElement getCurrentStackTrace() {
179180
return stackWalker.walk(SinkModuleBase::findValidPackageForVulnerability);
180181
}
181182

183+
protected Evidence buildEvidence(final Object value, final Range[] ranges) {
184+
final Range unbound = Ranges.findUnbound(ranges);
185+
if (unbound != null) {
186+
final Source source = unbound.getSource();
187+
if (source != null && source.getValue() != null) {
188+
final String sourceValue = source.getValue();
189+
final String evidenceValue = value.toString();
190+
final int start = evidenceValue.indexOf(sourceValue);
191+
if (start >= 0) {
192+
return new Evidence(
193+
evidenceValue,
194+
new Range[] {new Range(start, sourceValue.length(), source, unbound.getMarks())});
195+
}
196+
}
197+
}
198+
return new Evidence(value instanceof String ? (String) value : value.toString(), ranges);
199+
}
200+
182201
static StackTraceElement findValidPackageForVulnerability(
183202
@Nonnull final Stream<StackTraceElement> stream) {
184203
final StackTraceElement[] first = new StackTraceElement[1];

‎dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/Ranges.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ public static Range[] forObject(final @Nonnull Source source, final int mark) {
5959
return new Range[] {new Range(0, Integer.MAX_VALUE, source, mark)};
6060
}
6161

62+
@Nullable
63+
public static Range findUnbound(@Nonnull final Range[] ranges) {
64+
if (ranges.length != 1) {
65+
return null;
66+
}
67+
final Range range = ranges[0];
68+
return range.getStart() == 0 && range.getLength() == Integer.MAX_VALUE ? range : null;
69+
}
70+
6271
public static void copyShift(
6372
final @Nonnull Range[] src, final @Nonnull Range[] dst, final int dstPos, final int shift) {
6473
copyShift(src, dst, dstPos, shift, src.length);

‎dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/AbstractSinkModuleTest.groovy

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,37 @@
11
package com.datadog.iast.sink
22

33
import com.datadog.iast.IastModuleImplTestBase
4+
import com.datadog.iast.IastRequestContext
5+
import com.datadog.iast.model.Source
6+
import com.datadog.iast.overhead.Operations
7+
import com.datadog.iast.propagation.PropagationModuleImpl
8+
import com.datadog.iast.taint.Ranges
9+
import datadog.trace.api.gateway.RequestContext
10+
import datadog.trace.api.gateway.RequestContextSlot
11+
import datadog.trace.bootstrap.instrumentation.api.AgentSpan
412

5-
class AbstractSinkModuleTest extends IastModuleImplTestBase {
13+
import static com.datadog.iast.model.VulnerabilityType.SSRF
14+
import static datadog.trace.api.iast.SourceTypes.REQUEST_PARAMETER_VALUE
15+
16+
class AbstractSinkModuleTest extends IastModuleImplTestBase {
617

718
final StackTraceElement ignoredPackageClassElement = element("org.springframework.Ignored")
819
final StackTraceElement notIgnoredPackageClassElement = element("datadog.smoketest.NotIgnored")
920
final StackTraceElement notInIastExclusionTrie = element("not.in.iast.exclusion.Class")
1021

22+
private IastRequestContext ctx
23+
private AgentSpan span
24+
25+
void setup() {
26+
ctx = new IastRequestContext()
27+
final reqCtx = Mock(RequestContext) {
28+
getData(RequestContextSlot.IAST) >> ctx
29+
}
30+
span = Mock(AgentSpan) {
31+
getRequestContext() >> reqCtx
32+
}
33+
tracer.activeSpan() >> span
34+
}
1135

1236
void 'filter ignored package element from stack'() {
1337

@@ -43,6 +67,37 @@ class AbstractSinkModuleTest extends IastModuleImplTestBase {
4367
result == expected
4468
}
4569

70+
void 'test reporting evidence on objects'() {
71+
given:
72+
overheadController.consumeQuota(Operations.REPORT_VULNERABILITY, span) >> true
73+
final sink = new SinkModuleBase(dependencies) {}
74+
final propagation = new PropagationModuleImpl()
75+
final input = new String(source.value)
76+
ctx.getTaintedObjects().taint(input, Ranges.forCharSequence(input, source))
77+
78+
when:
79+
propagation.taintIfTainted(toReport, input)
80+
final evidence = sink.checkInjection(span, ctx, SSRF, toReport)
81+
82+
then:
83+
evidence.ranges.length == 1
84+
final range = evidence.ranges[0]
85+
if (matches) {
86+
final taintedEvidence = evidence.value.substring(range.start, range.start + range.length)
87+
taintedEvidence == input
88+
} else {
89+
final taintedEvidence = evidence.value
90+
taintedEvidence != input
91+
}
92+
93+
where:
94+
source | toReport | matches
95+
new Source(REQUEST_PARAMETER_VALUE, 'url', 'datadog.com') | new URL('https://datadog.com/index.html') | true
96+
new Source(REQUEST_PARAMETER_VALUE, 'url', 'datadog.com') | new URI('https://datadog.com/index.html') | true
97+
new Source(REQUEST_PARAMETER_VALUE, 'url', 'datadog.com') | new URI('https://dAtAdOg.com/index.html') | false
98+
new Source(REQUEST_PARAMETER_VALUE, 'url', 'datadog.com') | new URI('https://dAtAdOg.com/index.html') | false
99+
}
100+
46101
private StackTraceElement element(final String declaringClass) {
47102
return new StackTraceElement(declaringClass, "method", "fileName", 1)
48103
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /