From 46093d9bf7ac9c11d151888dd43ae0847b8edd62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20=C3=81lvarez=20=C3=81lvarez?= Date: Fri, 3 Jan 2025 11:53:59 +0100 Subject: [PATCH] Add propagation to URI#toURL method --- .../instrumentation/java/net/URICallSite.java | 16 ++++++++++++++++ .../java/net/URICallSIteTest.groovy | 1 + .../test/java/foo/bar/TestURICallSiteSuite.java | 9 +++++++++ .../springboot/controller/SsrfController.java | 16 ++++++++++++++++ .../smoketest/AbstractIastSpringBootTest.groovy | 10 ++++++---- 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/dd-java-agent/instrumentation/java-net/src/main/java/datadog/trace/instrumentation/java/net/URICallSite.java b/dd-java-agent/instrumentation/java-net/src/main/java/datadog/trace/instrumentation/java/net/URICallSite.java index adab398831a..b0244563f59 100644 --- a/dd-java-agent/instrumentation/java-net/src/main/java/datadog/trace/instrumentation/java/net/URICallSite.java +++ b/dd-java-agent/instrumentation/java-net/src/main/java/datadog/trace/instrumentation/java/net/URICallSite.java @@ -9,6 +9,7 @@ import datadog.trace.api.iast.propagation.CodecModule; import datadog.trace.api.iast.propagation.PropagationModule; import java.net.URI; +import java.net.URL; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -105,4 +106,19 @@ public static URI afterNormalize( } return result; } + + @Propagation + @CallSite.After("java.net.URL java.net.URI.toURL()") + public static URL afterToURL(@CallSite.This final URI uri, @CallSite.Return final URL result) { + final PropagationModule module = InstrumentationBridge.PROPAGATION; + if (module != null && result != null) { + try { + boolean keepRanges = uri.toString().equals(result.toString()); + module.taintObjectIfTainted(result, uri, keepRanges, NOT_MARKED); + } catch (final Throwable e) { + module.onUnexpectedException("After toURL threw", e); + } + } + return result; + } } diff --git a/dd-java-agent/instrumentation/java-net/src/test/groovy/datadog/trace/instrumentation/java/net/URICallSIteTest.groovy b/dd-java-agent/instrumentation/java-net/src/test/groovy/datadog/trace/instrumentation/java/net/URICallSIteTest.groovy index 7ba0764dbd6..882f8dc7605 100644 --- a/dd-java-agent/instrumentation/java-net/src/test/groovy/datadog/trace/instrumentation/java/net/URICallSIteTest.groovy +++ b/dd-java-agent/instrumentation/java-net/src/test/groovy/datadog/trace/instrumentation/java/net/URICallSIteTest.groovy @@ -69,5 +69,6 @@ class URICallSIteTest extends AgentTestRunner { 'toASCIIString' | 'String' | [new URI('http://test.com/index?name=value#fragment')] | true 'toASCIIString' | 'String' | [new URI('http://test.com/漢/index?name=value#fragment')] | false 'toString' | 'String' | [new URI('http://test.com/index?name=value#fragment')] | true + 'toURL' | 'Object' | [new URI('http://test.com/index?name=value#fragment')] | true } } diff --git a/dd-java-agent/instrumentation/java-net/src/test/java/foo/bar/TestURICallSiteSuite.java b/dd-java-agent/instrumentation/java-net/src/test/java/foo/bar/TestURICallSiteSuite.java index 84effd9d680..4dce0724886 100644 --- a/dd-java-agent/instrumentation/java-net/src/test/java/foo/bar/TestURICallSiteSuite.java +++ b/dd-java-agent/instrumentation/java-net/src/test/java/foo/bar/TestURICallSiteSuite.java @@ -1,7 +1,9 @@ package foo.bar; +import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -105,4 +107,11 @@ public static String toASCIIString(final URI uri) { LOGGER.debug("After toAsciiString {}", result); return result; } + + public static URL toURL(final URI uri) throws MalformedURLException { + LOGGER.debug("Before toURL {}", uri); + final URL result = uri.toURL(); + LOGGER.debug("After toURL {}", result); + return result; + } } diff --git a/dd-smoke-tests/iast-util/src/main/java/datadog/smoketest/springboot/controller/SsrfController.java b/dd-smoke-tests/iast-util/src/main/java/datadog/smoketest/springboot/controller/SsrfController.java index 64bcdc4ce66..4b180706aa1 100644 --- a/dd-smoke-tests/iast-util/src/main/java/datadog/smoketest/springboot/controller/SsrfController.java +++ b/dd-smoke-tests/iast-util/src/main/java/datadog/smoketest/springboot/controller/SsrfController.java @@ -3,6 +3,7 @@ import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import java.net.HttpURLConnection; +import java.net.URI; import java.net.URL; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; @@ -39,6 +40,21 @@ public String ssrf( return "ok"; } + @PostMapping("/uri") + public String uri( + @RequestParam(value = "url", required = false) final String url, + @RequestParam(value = "host", required = false) final String host) { + try { + final URI uri = + url != null ? new URI(url) : new URI("https", null, host, 443, "/test", null, null); + final URL target = uri.toURL(); + final HttpURLConnection conn = (HttpURLConnection) target.openConnection(); + conn.disconnect(); + } catch (final Exception e) { + } + return "ok"; + } + @PostMapping("/apache-httpclient4") public String apacheHttpClient4( @RequestParam(value = "url", required = false) final String url, diff --git a/dd-smoke-tests/iast-util/src/testFixtures/groovy/datadog/smoketest/AbstractIastSpringBootTest.groovy b/dd-smoke-tests/iast-util/src/testFixtures/groovy/datadog/smoketest/AbstractIastSpringBootTest.groovy index 806d8e2bdf9..916dedf17cf 100644 --- a/dd-smoke-tests/iast-util/src/testFixtures/groovy/datadog/smoketest/AbstractIastSpringBootTest.groovy +++ b/dd-smoke-tests/iast-util/src/testFixtures/groovy/datadog/smoketest/AbstractIastSpringBootTest.groovy @@ -688,7 +688,7 @@ abstract class AbstractIastSpringBootTest extends AbstractIastServerSmokeTest { void 'ssrf is present'() { setup: - final url = "http://localhost:${httpPort}/ssrf" + final url = "http://localhost:${httpPort}/ssrf${path}" final body = new FormBody.Builder().add(parameter, value).build() final request = new Request.Builder().url(url).post(body).build() @@ -715,9 +715,11 @@ abstract class AbstractIastSpringBootTest extends AbstractIastServerSmokeTest { } where: - parameter | value - 'url' | 'https://dd.datad0g.com/' - 'host' | 'dd.datad0g.com' + path | parameter | value + '' | 'url' | 'https://dd.datad0g.com/' + '' | 'host' | 'dd.datad0g.com' + '/uri' | 'url' | 'https://dd.datad0g.com/' + '/uri' | 'host' | 'dd.datad0g.com' } void 'ssrf is present (#path) (#parameter)'() {