diff --git a/Changelog.md b/Changelog.md index 4a56862fb..2f50c7c7f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,21 @@ Noteworthy changes to the agent are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.7.0] - TBD +### Adds +- [PR-395](https://github.com/newrelic/csec-java-agent/pull/395) **Support for Deserialization Vulnerability Detection**: Implemented mechanisms to detect vulnerabilities arising from unsafe deserialization processes. +- [PR-395](https://github.com/newrelic/csec-java-agent/pull/395) **Support for Vulnerability Detection of Remote Code Invocation via Reflection**: Enhanced capability to identify security risks associated with remote code execution through reflection. +- [PR-343](https://github.com/newrelic/csec-java-agent/pull/343) **HTTP Response Handling for Vulnerabilities**: Developed the functionality to send HTTP responses for detected vulnerabilities directly to the UI. + +### Changes +- [PR-343](https://github.com/newrelic/csec-java-agent/pull/343) **Trimmed Response Body**: Updated the response handling logic to trim response bodies to a maximum of 500KB when larger. This optimization aids in performance and resource conservation. +- [PR-396](https://github.com/newrelic/csec-java-agent/pull/396) Upgraded _commons-io:commons-io_ from version 2.7 to 2.14.0 +- [PR-403](https://github.com/newrelic/csec-java-agent/pull/403) GraphQL Supported Version Range: Restricted the supported version range for GraphQL due to the release of a new version on April 7th, 2025 + +### Fixes +- [PR-372](https://github.com/newrelic/csec-java-agent/pull/372) **Repeat IAST Request Relay Commands**: Reconfigured logic to repeat IAST control commands until the endpoint is confirmed. + + ## [1.6.1] - 2025-3-1 ### Adds - [PR-309](https://github.com/newrelic/csec-java-agent/pull/309) Introduced API Endpoint detection for Resin Server. [NR-293077](https://new-relic.atlassian.net/browse/NR-293077) @@ -17,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [PR-364](https://github.com/newrelic/csec-java-agent/pull/364) Modified HealthCheck to include the iastTestIdentifier and adjusted WebSocket headers to send instance-count only when its value is greater than zero. [NR-347851](https://new-relic.atlassian.net/browse/NR-347851) - [PR-349](https://github.com/newrelic/csec-java-agent/pull/349) Enhanced the process for rolling over log files, allowing for specific prefixes and suffixes. [NR-337016](https://new-relic.atlassian.net/browse/NR-337016) + ## [1.6.0] - 2024-12-16 ### Adds - [PR-329](https://github.com/newrelic/csec-java-agent/pull/329) Apache Pekko Server Support: The security agent now supports Apache Pekko Server version 1.0.0 and newer, compatible with Scala 2.13 and above. [NR-308780](https://new-relic.atlassian.net/browse/NR-308780), [NR-308781](https://new-relic.atlassian.net/browse/NR-308781), [NR-308791](https://new-relic.atlassian.net/browse/NR-308791), [NR-308792](https://new-relic.atlassian.net/browse/NR-308792) [NR-308782](https://new-relic.atlassian.net/browse/NR-308782) diff --git a/gradle.properties b/gradle.properties index a1f827f58..8be8f55a6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # The agent version. agentVersion=1.6.1 -jsonVersion=1.2.10 +jsonVersion=1.2.11 # Updated exposed NR APM API version. nrAPIVersion=8.12.0 diff --git a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/AkkaResponseHelper.scala b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/AkkaResponseHelper.scala index 6e8725dc5..9625d209e 100644 --- a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/AkkaResponseHelper.scala +++ b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/AkkaResponseHelper.scala @@ -16,6 +16,8 @@ import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityExcepti import com.newrelic.api.agent.security.utils.logging.LogLevel import java.lang +import java.util.{HashMap => JavaHashMap} +import scala.concurrent.{ExecutionContext, Future} import scala.runtime.AbstractFunction1 class AkkaResponseHelper extends AbstractFunction1[HttpResponse, HttpResponse] { @@ -25,7 +27,9 @@ class AkkaResponseHelper extends AbstractFunction1[HttpResponse, HttpResponse] { val stringResponse = new lang.StringBuilder() val isLockAquired = GenericHelper.acquireLockIfPossible(AkkaCoreUtils.NR_SEC_CUSTOM_ATTRIB_NAME); stringResponse.append(httpResponse.entity.asInstanceOf[HttpEntity.Strict].getData().decodeString("utf-8")) - AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, httpResponse.entity.contentType.toString(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken()) + val headers = new JavaHashMap[String, String]() + httpResponse.headers.foreach(header => headers.put(header.name(), header.value())) + AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, httpResponse.entity.contentType.toString(), headers, httpResponse.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken()) } catch { case t: NewRelicSecurityException => NewRelicSecurity.getAgent.log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, AkkaCoreUtils.AKKA_HTTP_10_0_0, t.getMessage), t, classOf[AkkaCoreUtils].getName) diff --git a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java index 8d819d36a..065a1d128 100644 --- a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java @@ -17,6 +17,7 @@ import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import com.newrelic.api.agent.security.utils.logging.LogLevel; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; @@ -33,18 +34,18 @@ public static boolean acquireServletLockIfPossible() { return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME); } - public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, String className, String methodName, Token token) { - if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ - return; - } + public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, HashMap headers, int responseCode, String className, String methodName, Token token) { try { token.linkAndExpire(); - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive() || Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class))){ return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(contentType); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(responseBody); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(contentType); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(headers); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setBody(responseBody); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(responseCode); + LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); RXSSOperation rxssOperation = new RXSSOperation(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest(), diff --git a/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java b/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java index 5e056694d..c58f7193d 100644 --- a/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java @@ -35,21 +35,18 @@ public static boolean acquireServletLockIfPossible() { return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME); } - public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder response, String contentType, int responseCode, String className, String methodName, Token token) { + public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder response, String contentType, HashMap headers, int responseCode, String className, String methodName, Token token) { try { - if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ - return; - } token.linkAndExpire(); if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive()){ return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(contentType); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(response); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(responseCode); - ServletHelper.executeBeforeExitingTransaction(); - + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(contentType); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(headers); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setBody(response); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(responseCode); +// ServletHelper.executeBeforeExitingTransaction(); LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); if(!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseContentType())) { diff --git a/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala b/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala index bcff48b24..ac67f8762 100644 --- a/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala +++ b/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala @@ -15,12 +15,12 @@ import akka.stream.scaladsl.Sink import akka.util.ByteString import com.newrelic.api.agent.security.NewRelicSecurity import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper -import com.newrelic.api.agent.security.schema.StringUtils import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException import com.newrelic.api.agent.security.utils.logging.LogLevel import com.newrelic.api.agent.{NewRelic, Token} import java.lang +import java.util.{HashMap => JavaHashMap} import scala.concurrent.{ExecutionContext, Future} object ResponseFutureHelper { @@ -41,7 +41,9 @@ object ResponseFutureHelper { processingResult.onComplete { _ => { token.linkAndExpire() - AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, response.entity.contentType.toString(), response.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken) + val headers = new JavaHashMap[String, String]() + response.headers.foreach(header => headers.put(header.name(), header.value())) + AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, response.entity.contentType.toString(), headers, response.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken) } } @@ -67,8 +69,9 @@ object ResponseFutureHelper { stringResponse.append(chunk) } val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) - - AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, httpResponse.entity.contentType.toString(), httpResponse.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken()) + val headers = new JavaHashMap[String, String]() + httpResponse.headers.foreach(header => headers.put(header.name(), header.value())) + AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, httpResponse.entity.contentType.toString(), headers, httpResponse.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken()) } catch { case t: NewRelicSecurityException => NewRelicSecurity.getAgent.log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, AkkaCoreUtils.AKKA_HTTP_CORE_10_0, t.getMessage), t, classOf[AkkaCoreUtils].getName) diff --git a/instrumentation-security/akka-http-core-10.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala b/instrumentation-security/akka-http-core-10.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala index 05aaa5904..ebcfeee09 100644 --- a/instrumentation-security/akka-http-core-10.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala +++ b/instrumentation-security/akka-http-core-10.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala @@ -233,7 +233,7 @@ class AkkaHttpCoreTest { Assert.assertFalse("response should not be empty", operation.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", operation.getResponse.getResponseContentType, contentType) - Assert.assertEquals("Invalid responseBody.", operation.getResponse.getResponseBody.toString, responseBody) + Assert.assertEquals("Invalid responseBody.", operation.getResponse.getBody.toString, responseBody) } private def assertMetaData(metaData: SecurityMetaData): Unit = { Assert.assertFalse("response should not be empty", metaData.getResponse.isEmpty) @@ -241,7 +241,7 @@ class AkkaHttpCoreTest { Assert.assertEquals("Invalid responseBody.", metaData.getRequest.getBody.toString, requestBody) Assert.assertFalse("response should not be empty", metaData.getRequest.isEmpty) Assert.assertEquals("Invalid response content-type.", metaData.getResponse.getResponseContentType, contentType) - Assert.assertEquals("Invalid responseBody.", metaData.getResponse.getResponseBody.toString, responseBody) + Assert.assertEquals("Invalid responseBody.", metaData.getResponse.getBody.toString, responseBody) Assert.assertEquals("Invalid protocol.", metaData.getRequest.getProtocol, "http") } } diff --git a/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java b/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java index 1c09036ee..dd82e2dbe 100644 --- a/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java @@ -35,20 +35,18 @@ public static boolean acquireServletLockIfPossible() { return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME); } - public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, int responseCode, String className, String methodName, Token token) { + public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, HashMap headers, int responseCode, String className, String methodName, Token token) { try { - if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ - return; - } token.linkAndExpire(); if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive()){ return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(contentType); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(responseBody); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(responseCode); - ServletHelper.executeBeforeExitingTransaction(); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(contentType); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setBody(responseBody); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(responseCode); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(headers); +// ServletHelper.executeBeforeExitingTransaction(); LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala b/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala index 2bf76c1b1..a78afdfe7 100644 --- a/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala +++ b/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala @@ -15,12 +15,12 @@ import akka.stream.scaladsl.Sink import akka.util.ByteString import com.newrelic.api.agent.security.NewRelicSecurity import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper -import com.newrelic.api.agent.security.schema.StringUtils import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException import com.newrelic.api.agent.security.utils.logging.LogLevel import com.newrelic.api.agent.{NewRelic, Token} import java.lang +import java.util.{HashMap => JavaHashMap} import scala.concurrent.{ExecutionContext, Future} object ResponseFutureHelper { @@ -41,7 +41,9 @@ object ResponseFutureHelper { processingResult.onComplete { _ => { token.linkAndExpire() - AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, response.entity.contentType.toString(), response.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken) + val headers = new JavaHashMap[String, String]() + response.headers.foreach(header => headers.put(header.name(), header.value())) + AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, response.entity.contentType.toString(), headers, response.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken) } } @@ -67,8 +69,9 @@ object ResponseFutureHelper { stringResponse.append(chunk) } val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) - - AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, httpResponse.entity.contentType.toString(), httpResponse.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken()) + val headers = new JavaHashMap[String, String]() + httpResponse.headers.foreach(header => headers.put(header.name(), header.value())) + AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, httpResponse.entity.contentType.toString(), headers, httpResponse.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken()) } catch { case t: NewRelicSecurityException => NewRelicSecurity.getAgent.log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, AkkaCoreUtils.AKKA_HTTP_CORE_10_0_11, t.getMessage), t, classOf[AkkaCoreUtils].getName) diff --git a/instrumentation-security/akka-http-core-2.11_10.0.11/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala b/instrumentation-security/akka-http-core-2.11_10.0.11/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala index 727220cd9..6a43116af 100644 --- a/instrumentation-security/akka-http-core-2.11_10.0.11/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala +++ b/instrumentation-security/akka-http-core-2.11_10.0.11/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala @@ -233,7 +233,7 @@ class AkkaHttpCoreTest { Assert.assertFalse("response should not be empty", operation.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", operation.getResponse.getResponseContentType, contentType) - Assert.assertEquals("Invalid responseBody.", operation.getResponse.getResponseBody.toString, responseBody) + Assert.assertEquals("Invalid responseBody.", operation.getResponse.getBody.toString, responseBody) } private def assertMetaData(metaData: SecurityMetaData): Unit = { Assert.assertFalse("response should not be empty", metaData.getResponse.isEmpty) @@ -241,7 +241,7 @@ class AkkaHttpCoreTest { Assert.assertEquals("Invalid responseBody.", metaData.getRequest.getBody.toString, requestBody) Assert.assertFalse("response should not be empty", metaData.getRequest.isEmpty) Assert.assertEquals("Invalid response content-type.", metaData.getResponse.getResponseContentType, contentType) - Assert.assertEquals("Invalid responseBody.", metaData.getResponse.getResponseBody.toString, responseBody) + Assert.assertEquals("Invalid responseBody.", metaData.getResponse.getBody.toString, responseBody) Assert.assertEquals("Invalid protocol.", metaData.getRequest.getProtocol, "http") } } diff --git a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java index 4c26329a2..8622adbbf 100644 --- a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java @@ -35,18 +35,16 @@ public static boolean acquireServletLockIfPossible() { return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME); } - public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, int responseCode, String className, String methodName, Token token) { + public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, Map headers, int responseCode, String className, String methodName, Token token) { try { - if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ - return; - } token.linkAndExpire(); if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive()){ return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(contentType); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(responseBody); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(responseCode); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(contentType); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setBody(responseBody); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(responseCode); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(headers); LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); if(!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseContentType())) { diff --git a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala index f294ed015..71e13c6fc 100644 --- a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala +++ b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala @@ -15,12 +15,12 @@ import akka.stream.scaladsl.Sink import akka.util.ByteString import com.newrelic.api.agent.security.NewRelicSecurity import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper -import com.newrelic.api.agent.security.schema.StringUtils import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException import com.newrelic.api.agent.security.utils.logging.LogLevel import com.newrelic.api.agent.{NewRelic, Token} import java.lang +import java.util.{HashMap => JavaHashMap} import scala.concurrent.{ExecutionContext, Future} object ResponseFutureHelper { @@ -41,7 +41,9 @@ object ResponseFutureHelper { processingResult.onComplete { _ => { token.linkAndExpire() - AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, response.entity.contentType.toString(), response.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken) + val headers = new JavaHashMap[String, String]() + response.headers.foreach(header => headers.put(header.name(), header.value())) + AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, response.entity.contentType.toString(), headers, response.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken) } } @@ -67,8 +69,9 @@ object ResponseFutureHelper { stringResponse.append(chunk) } val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) - - AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, httpResponse.entity.contentType.toString(), httpResponse.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken) + val headers = new JavaHashMap[String, String]() + httpResponse.headers.foreach(header => headers.put(header.name(), header.value())) + AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, httpResponse.entity.contentType.toString(), headers, httpResponse.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken) } catch { case t: NewRelicSecurityException => NewRelicSecurity.getAgent.log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, AkkaCoreUtils.AKKA_HTTP_CORE_10_0_11, t.getMessage), t, classOf[AkkaCoreUtils].getName) diff --git a/instrumentation-security/akka-http-core-2.13_10.1.8/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala b/instrumentation-security/akka-http-core-2.13_10.1.8/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala index 3fb9cd304..9b11118fc 100644 --- a/instrumentation-security/akka-http-core-2.13_10.1.8/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala +++ b/instrumentation-security/akka-http-core-2.13_10.1.8/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala @@ -233,7 +233,7 @@ class AkkaHttpCoreTest { Assert.assertFalse("response should not be empty", operation.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", operation.getResponse.getResponseContentType, contentType) - Assert.assertEquals("Invalid responseBody.", operation.getResponse.getResponseBody.toString, responseBody) + Assert.assertEquals("Invalid responseBody.", operation.getResponse.getBody.toString, responseBody) } private def assertMetaData(metaData: SecurityMetaData): Unit = { Assert.assertFalse("response should not be empty", metaData.getResponse.isEmpty) @@ -241,7 +241,7 @@ class AkkaHttpCoreTest { Assert.assertEquals("Invalid responseBody.", metaData.getRequest.getBody.toString, requestBody) Assert.assertFalse("response should not be empty", metaData.getRequest.isEmpty) Assert.assertEquals("Invalid response content-type.", metaData.getResponse.getResponseContentType, contentType) - Assert.assertEquals("Invalid responseBody.", metaData.getResponse.getResponseBody.toString, responseBody) + Assert.assertEquals("Invalid responseBody.", metaData.getResponse.getBody.toString, responseBody) Assert.assertEquals("Invalid protocol.", metaData.getRequest.getProtocol, "http") } } diff --git a/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java b/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java index b52bce019..b385195d3 100644 --- a/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java @@ -37,19 +37,19 @@ public static boolean acquireServletLockIfPossible() { return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME); } - public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, int responseCode, String className, String methodName, Token token) { + public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, Map headers, int responseCode, String className, String methodName, Token token) { try { - if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ - return; - } + token.linkAndExpire(); if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive()){ return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(contentType); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(responseBody); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(responseCode); - ServletHelper.executeBeforeExitingTransaction(); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(contentType); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(headers); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setBody(responseBody); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(responseCode); + +// ServletHelper.executeBeforeExitingTransaction(); LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); if(!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseContentType())) { diff --git a/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala b/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala index 78a4ee019..429ccbdb2 100644 --- a/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala +++ b/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala @@ -15,12 +15,12 @@ import akka.stream.scaladsl.Sink import akka.util.ByteString import com.newrelic.api.agent.security.NewRelicSecurity import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper -import com.newrelic.api.agent.security.schema.StringUtils import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException import com.newrelic.api.agent.security.utils.logging.LogLevel import com.newrelic.api.agent.{NewRelic, Token} import java.lang +import java.util.{HashMap => JavaHashMap} import scala.concurrent.{ExecutionContext, Future} object ResponseFutureHelper { @@ -41,7 +41,9 @@ object ResponseFutureHelper { processingResult.onComplete { _ => { token.linkAndExpire() - AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, response.entity.contentType.toString(), response.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken) + val headers = new JavaHashMap[String, String]() + response.headers.foreach(header => headers.put(header.name(), header.value())) + AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, response.entity.contentType.toString(), headers, response.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken) } } @@ -67,8 +69,9 @@ object ResponseFutureHelper { stringResponse.append(chunk) } val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) - - AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, httpResponse.entity.contentType.toString(), httpResponse.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken()) + val headers = new JavaHashMap[String, String]() + httpResponse.headers.foreach(header => headers.put(header.name(), header.value())) + AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, httpResponse.entity.contentType.toString(), headers, httpResponse.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken()) } catch { case t: NewRelicSecurityException => NewRelicSecurity.getAgent.log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, AkkaCoreUtils.AKKA_HTTP_CORE_2_13_10_2_0, t.getMessage), t, classOf[AkkaCoreUtils].getName) diff --git a/instrumentation-security/akka-http-core-2.13_10.2.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala b/instrumentation-security/akka-http-core-2.13_10.2.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala index dd1337dd3..c81b0ac43 100644 --- a/instrumentation-security/akka-http-core-2.13_10.2.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala +++ b/instrumentation-security/akka-http-core-2.13_10.2.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala @@ -231,7 +231,7 @@ class AkkaHttpCoreTest { Assert.assertFalse("response should not be empty", operation.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", operation.getResponse.getResponseContentType, contentType) - Assert.assertEquals("Invalid responseBody.", operation.getResponse.getResponseBody.toString, responseBody) + Assert.assertEquals("Invalid responseBody.", operation.getResponse.getBody.toString, responseBody) } private def assertMetaData(metaData: SecurityMetaData): Unit = { Assert.assertFalse("response should not be empty", metaData.getResponse.isEmpty) @@ -239,7 +239,7 @@ class AkkaHttpCoreTest { Assert.assertEquals("Invalid responseBody.", metaData.getRequest.getBody.toString, requestBody) Assert.assertFalse("response should not be empty", metaData.getRequest.isEmpty) Assert.assertEquals("Invalid response content-type.", metaData.getResponse.getResponseContentType, contentType) - Assert.assertEquals("Invalid responseBody.", metaData.getResponse.getResponseBody.toString, responseBody) + Assert.assertEquals("Invalid responseBody.", metaData.getResponse.getBody.toString, responseBody) Assert.assertEquals("Invalid protocol.", metaData.getRequest.getProtocol, "http") } } diff --git a/instrumentation-security/apache-pekko-http-core-2.13_1/src/main/scala/org.apache.pekko/http/scaladsl/PekkoCoreUtils.java b/instrumentation-security/apache-pekko-http-core-2.13_1/src/main/scala/org.apache.pekko/http/scaladsl/PekkoCoreUtils.java index 73fa86c44..dd6b869c6 100644 --- a/instrumentation-security/apache-pekko-http-core-2.13_1/src/main/scala/org.apache.pekko/http/scaladsl/PekkoCoreUtils.java +++ b/instrumentation-security/apache-pekko-http-core-2.13_1/src/main/scala/org.apache.pekko/http/scaladsl/PekkoCoreUtils.java @@ -68,12 +68,12 @@ public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringB if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(contentType); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(responseBody); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(contentType); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setBody(responseBody); if (!contentType.equals(NO_MEDIA_CONTENT_TYPE)) { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(responseCode); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(responseCode); } - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); if(!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseContentType())) { diff --git a/instrumentation-security/apache-pekko-http-core-2.13_1/src/test/scala/com/agent/instrumentation/org.apache.pekko/http/core/PekkoHttpCoreTest.scala b/instrumentation-security/apache-pekko-http-core-2.13_1/src/test/scala/com/agent/instrumentation/org.apache.pekko/http/core/PekkoHttpCoreTest.scala index 690f9ea88..3ee0ff6b5 100644 --- a/instrumentation-security/apache-pekko-http-core-2.13_1/src/test/scala/com/agent/instrumentation/org.apache.pekko/http/core/PekkoHttpCoreTest.scala +++ b/instrumentation-security/apache-pekko-http-core-2.13_1/src/test/scala/com/agent/instrumentation/org.apache.pekko/http/core/PekkoHttpCoreTest.scala @@ -18,7 +18,7 @@ import org.junit.{Assert, FixMethodOrder, Test} import java.net.ServerSocket import java.util.UUID import scala.concurrent.Await -import scala.concurrent.duration.{Duration, DurationInt} +import scala.concurrent.duration.DurationInt import scala.jdk.CollectionConverters._ import scala.jdk.javaapi.FutureConverters @@ -224,7 +224,7 @@ class PekkoHttpCoreTest { Assert.assertFalse("response should not be empty", operation.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, operation.getResponse.getResponseContentType) - Assert.assertEquals("Invalid responseBody.", responseBody, operation.getResponse.getResponseBody.toString) + Assert.assertEquals("Invalid responseBody.", responseBody, operation.getResponse.getBody.toString) } private def assertMetaData(metaData: SecurityMetaData): Unit = { Assert.assertFalse("response should not be empty", metaData.getRequest.isEmpty) @@ -232,7 +232,7 @@ class PekkoHttpCoreTest { Assert.assertEquals("Invalid responseBody.", requestBody, metaData.getRequest.getBody.toString) Assert.assertFalse("response should not be empty", metaData.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, metaData.getResponse.getResponseContentType) - Assert.assertEquals("Invalid responseBody.", responseBody, metaData.getResponse.getResponseBody.toString) + Assert.assertEquals("Invalid responseBody.", responseBody, metaData.getResponse.getBody.toString) Assert.assertEquals("Invalid protocol.", metaData.getRequest.getProtocol, "http") } } diff --git a/instrumentation-security/deserialisation/build.gradle b/instrumentation-security/deserialisation/build.gradle new file mode 100644 index 000000000..40fb3a3e9 --- /dev/null +++ b/instrumentation-security/deserialisation/build.gradle @@ -0,0 +1,16 @@ +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") +} + +// This instrumentation module should not use the bootstrap classpath + + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.deserialisation' } +} + +verifyInstrumentation { + verifyClasspath = false // We don't want to verify classpath since these are JDK classes +} diff --git a/instrumentation-security/deserialisation/src/main/java/java/io/ObjectInputStreamHelper.java b/instrumentation-security/deserialisation/src/main/java/java/io/ObjectInputStreamHelper.java new file mode 100644 index 000000000..cefbab4f6 --- /dev/null +++ b/instrumentation-security/deserialisation/src/main/java/java/io/ObjectInputStreamHelper.java @@ -0,0 +1,7 @@ +package java.io; + +public class ObjectInputStreamHelper { + public static final String METHOD_NAME_READ_OBJECT = "readObject"; + + public static final String NR_SEC_CUSTOM_ATTRIB_NAME = "UNSAFE-DESERIALISATION-LOCK-JAVA-IO-%s-"; +} \ No newline at end of file diff --git a/instrumentation-security/deserialisation/src/main/java/java/io/ObjectInputStream_Instrumentation.java b/instrumentation-security/deserialisation/src/main/java/java/io/ObjectInputStream_Instrumentation.java new file mode 100644 index 000000000..e57ac907a --- /dev/null +++ b/instrumentation-security/deserialisation/src/main/java/java/io/ObjectInputStream_Instrumentation.java @@ -0,0 +1,133 @@ +package java.io; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.schema.*; +import com.newrelic.api.agent.security.schema.Serializable; +import com.newrelic.api.agent.security.schema.operation.DeserializationOperation; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +import java.util.Arrays; + + +@Weave(type = MatchType.BaseClass, originalName = "java.io.ObjectInputStream") +public abstract class ObjectInputStream_Instrumentation { + + private void readSerialData(Object obj, ObjectStreamClass desc) + throws IOException { + if(NewRelicSecurity.isHookProcessingActive()) { + DeserializationInfo dInfo = preProcessSecurityHook(obj); + } + Weaver.callOriginal(); + } + + private void filterCheck(Class clazz, int arrayLength) + throws InvalidClassException { + boolean isLockAcquired = acquireLockIfPossible("filterCheck"); + boolean filterCheck = false; + try { + Weaver.callOriginal(); + filterCheck = true; + } finally { + if(isLockAcquired) { + processFilterCheck(clazz, filterCheck); + GenericHelper.releaseLock(String.format(ObjectInputStreamHelper.NR_SEC_CUSTOM_ATTRIB_NAME, "filterCheck")); + } + } + } + + protected Class resolveClass(ObjectStreamClass desc) + throws IOException, ClassNotFoundException + { + boolean isLockAcquired = acquireLockIfPossible("resolve"); + Class returnValue = null; + try { + returnValue = Weaver.callOriginal(); + } finally { + if(isLockAcquired) { + processResolveClass(desc, returnValue); + GenericHelper.releaseLock(String.format(ObjectInputStreamHelper.NR_SEC_CUSTOM_ATTRIB_NAME, "resolve")); + } + } + return returnValue; + } + + private DeserializationInfo preProcessSecurityHook(Object obj) { + DeserializationInfo dInfo = new DeserializationInfo(obj.getClass().getName(), obj); + NewRelicSecurity.getAgent().getSecurityMetaData().addToDeserializationRoot(dInfo); + return dInfo; + } + + + private final Object readObject(Class type) + throws IOException, ClassNotFoundException { + boolean isLockAcquired = acquireLockIfPossible("readObject"); + DeserializationInvocation deserializationInvocation = null; + DeserializationOperation operation = null; + + if(isLockAcquired) { + operation = new DeserializationOperation( + this.getClass().getName(), + ObjectInputStreamHelper.METHOD_NAME_READ_OBJECT + ); + deserializationInvocation = new DeserializationInvocation(true, operation.getExecutionId()); + NewRelicSecurity.getAgent().getSecurityMetaData().setDeserializationInvocation(deserializationInvocation); + operation.setDeserializationInvocation(deserializationInvocation); +// NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(InstrumentationConstants.ACTIVE_DESERIALIZATION, true); + } + try { + return Weaver.callOriginal(); + } finally { + if(isLockAcquired) { + if(NewRelicSecurity.getAgent().getSecurityMetaData().peekDeserializationRoot() != null) { + operation.setRootDeserializationInfo(NewRelicSecurity.getAgent().getSecurityMetaData() + .peekDeserializationRoot()); + operation.setEntityName(operation.getRootDeserializationInfo().getType()); + } + NewRelicSecurity.getAgent().registerOperation(operation); + NewRelicSecurity.getAgent().getSecurityMetaData().setDeserializationInvocation(null); + NewRelicSecurity.getAgent().getSecurityMetaData().resetDeserializationRoot(); + GenericHelper.releaseLock(String.format(ObjectInputStreamHelper.NR_SEC_CUSTOM_ATTRIB_NAME, "readObject")); + } + } + } + + private void processFilterCheck(Class clazz, boolean filterCheck) { + + DeserializationInvocation deserializationInvocation = NewRelicSecurity.getAgent().getSecurityMetaData().getDeserializationInvocation(); + if(deserializationInvocation != null && clazz != null) { + com.newrelic.api.agent.security.schema.Serializable serializable = deserializationInvocation.getEncounteredSerializableByName(clazz.getName()); + if(serializable == null) { + serializable = new Serializable(clazz.getName(), true); + serializable.setKlass(clazz); + deserializationInvocation.addEncounteredSerializable(serializable); +// serializable.setClassDefinition(getClassDefinition(ObjectStreamClass.lookup(clazz))); + } + if(!filterCheck) { + serializable.setDeserializable(false); + } + } + } + + private void processResolveClass(ObjectStreamClass desc, Class returnValue) { + DeserializationInvocation deserializationInvocation = NewRelicSecurity.getAgent().getSecurityMetaData().getDeserializationInvocation(); + if(deserializationInvocation != null) { + Serializable serializable = deserializationInvocation.getEncounteredSerializableByName(desc.getName()); + if(serializable == null) { + serializable = new Serializable(desc.getName(), true); + serializable.setKlass(returnValue); + deserializationInvocation.addEncounteredSerializable(serializable); +// serializable.setClassDefinition(getClassDefinition(desc)); + } + if(returnValue == null) { + serializable.setDeserializable(false); + } + } + } + + private boolean acquireLockIfPossible(String operation) { + return GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.UNSAFE_DESERIALIZATION, String.format(ObjectInputStreamHelper.NR_SEC_CUSTOM_ATTRIB_NAME, operation)); + } +} \ No newline at end of file diff --git a/instrumentation-security/deserialisation/src/main/java/java/io/ObjectStreamClass_Instrumentation.java b/instrumentation-security/deserialisation/src/main/java/java/io/ObjectStreamClass_Instrumentation.java new file mode 100644 index 000000000..4e0fb5197 --- /dev/null +++ b/instrumentation-security/deserialisation/src/main/java/java/io/ObjectStreamClass_Instrumentation.java @@ -0,0 +1,27 @@ +package java.io; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.schema.DeserializationInvocation; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +@Weave(type = MatchType.BaseClass, originalName = "java.io.ObjectStreamClass") +public class ObjectStreamClass_Instrumentation { + + void invokeReadObject(Object obj, ObjectInputStream in) + throws ClassNotFoundException, IOException, + UnsupportedOperationException + { + if(NewRelicSecurity.isHookProcessingActive()) { + DeserializationInvocation deserializationInvocation = NewRelicSecurity.getAgent().getSecurityMetaData().getDeserializationInvocation(); + if (deserializationInvocation != null) { + deserializationInvocation.pushReadObjectInAction(obj.getClass().getName()); + } + Weaver.callOriginal(); + if (deserializationInvocation != null) { + deserializationInvocation.popReadObjectInAction(); + } + } + } +} diff --git a/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/GrpcServerUtils.java b/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/GrpcServerUtils.java index c20978838..437c91c42 100644 --- a/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/GrpcServerUtils.java +++ b/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/GrpcServerUtils.java @@ -24,8 +24,8 @@ public class GrpcServerUtils { private static final String X_FORWARDED_FOR = "x-forwarded-for"; private static final String EMPTY = ""; - public static final String NR_SEC_CUSTOM_ATTRIB_NAME = "NR_CSEC_GRPC_SERVER_OPERATIONAL_LOCK_"; public static final String METHOD_NAME_START_CALL = "startCall"; + public static final String NR_SEC_CUSTOM_ATTRIB_NAME = "NR_CSEC_GRPC_SERVER_OPERATIONAL_LOCK_"; private static Set typeRegistries = new HashSet<>(); @@ -90,9 +90,9 @@ public static void postProcessSecurityHook(Metadata metadata, int statusCode, St if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()) { return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(statusCode); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(statusCode); - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); @@ -101,9 +101,9 @@ public static void postProcessSecurityHook(Metadata metadata, int statusCode, St NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getHeaders().put(headerKey, metadata.get(Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER))); } if (headerNames.contains("content-type")) { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(metadata.get(Metadata.Key.of("content-type", Metadata.ASCII_STRING_MARSHALLER))); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(metadata.get(Metadata.Key.of("content-type", Metadata.ASCII_STRING_MARSHALLER))); } else { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType("application/grpc"); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType("application/grpc"); } if (!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseContentType())) { diff --git a/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/GrpcServerUtils.java b/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/GrpcServerUtils.java index 87cb954c5..c5436919e 100644 --- a/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/GrpcServerUtils.java +++ b/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/GrpcServerUtils.java @@ -95,9 +95,9 @@ public static void postProcessSecurityHook(Metadata metadata, int statusCode, St if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()) { return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(statusCode); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(statusCode); - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); @@ -106,9 +106,9 @@ public static void postProcessSecurityHook(Metadata metadata, int statusCode, St NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getHeaders().put(headerKey, metadata.get(Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER))); } if (headerNames.contains("content-type")){ - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(metadata.get(Metadata.Key.of("content-type", Metadata.ASCII_STRING_MARSHALLER))); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(metadata.get(Metadata.Key.of("content-type", Metadata.ASCII_STRING_MARSHALLER))); } else { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType("application/grpc"); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType("application/grpc"); } if(!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseContentType())) { diff --git a/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/GrpcServerUtils.java b/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/GrpcServerUtils.java index 3b65ebbf0..ddab7b4db 100644 --- a/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/GrpcServerUtils.java +++ b/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/GrpcServerUtils.java @@ -90,9 +90,9 @@ public static void postProcessSecurityHook(Metadata metadata, int statusCode, St if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()) { return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(statusCode); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(statusCode); - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); @@ -101,9 +101,9 @@ public static void postProcessSecurityHook(Metadata metadata, int statusCode, St NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getHeaders().put(headerKey, metadata.get(Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER))); } if (headerNames.contains("content-type")){ - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(metadata.get(Metadata.Key.of("content-type", Metadata.ASCII_STRING_MARSHALLER))); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(metadata.get(Metadata.Key.of("content-type", Metadata.ASCII_STRING_MARSHALLER))); } else { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType("application/grpc"); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType("application/grpc"); } if(!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseContentType())) { diff --git a/instrumentation-security/http4s-blaze-server-2.12_0.21/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala b/instrumentation-security/http4s-blaze-server-2.12_0.21/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala index ceb9aa337..aaa73668b 100644 --- a/instrumentation-security/http4s-blaze-server-2.12_0.21/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala +++ b/instrumentation-security/http4s-blaze-server-2.12_0.21/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala @@ -139,13 +139,13 @@ object RequestProcessor { try { if (NewRelicSecurity.isHookProcessingActive && isLockAcquired && !NewRelicSecurity.getAgent.getIastDetectionCategory.getRxssEnabled) { val securityResponse = NewRelicSecurity.getAgent.getSecurityMetaData.getResponse - securityResponse.setResponseCode(response.status.code) + securityResponse.setStatusCode(response.status.code) processResponseHeaders(response.headers, securityResponse) - securityResponse.setResponseContentType(getContentType(securityResponse.getHeaders)) + securityResponse.setContentType(getContentType(securityResponse.getHeaders)) - securityResponse.getResponseBody.append(body) + securityResponse.getBody.append(body) - ServletHelper.executeBeforeExitingTransaction() +// ServletHelper.executeBeforeExitingTransaction() if (!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent.getSecurityMetaData.getResponse.getResponseContentType)) { NewRelicSecurity.getAgent.getSecurityMetaData.getMetaData.setFromJumpRequiredInStackTrace(3) val rxssOperation = new RXSSOperation(NewRelicSecurity.getAgent.getSecurityMetaData.getRequest, NewRelicSecurity.getAgent.getSecurityMetaData.getResponse, this.getClass.getName, METHOD_WITH_HTTP_APP) diff --git a/instrumentation-security/http4s-blaze-server-2.12_0.21/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala b/instrumentation-security/http4s-blaze-server-2.12_0.21/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala index 00dc05603..886cd260b 100644 --- a/instrumentation-security/http4s-blaze-server-2.12_0.21/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala +++ b/instrumentation-security/http4s-blaze-server-2.12_0.21/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala @@ -93,8 +93,8 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", operation.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, operation.getResponse.getResponseContentType) Assert.assertFalse("Headers should not be empty", operation.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getResponseBody.toString) - Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getBody.toString) + Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getStatusCode) } private def assertMetaData(metaData: SecurityMetaData): Unit = { @@ -106,9 +106,9 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", metaData.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, metaData.getResponse.getResponseContentType) - Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getStatusCode) Assert.assertFalse("Headers should not be empty", metaData.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getResponseBody.toString) + Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getBody.toString) } } diff --git a/instrumentation-security/http4s-blaze-server-2.12_0.22/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala b/instrumentation-security/http4s-blaze-server-2.12_0.22/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala index 5006fa96b..c7167d958 100644 --- a/instrumentation-security/http4s-blaze-server-2.12_0.22/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala +++ b/instrumentation-security/http4s-blaze-server-2.12_0.22/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala @@ -141,13 +141,13 @@ object RequestProcessor { try { if (NewRelicSecurity.isHookProcessingActive && isLockAcquired && !NewRelicSecurity.getAgent.getIastDetectionCategory.getRxssEnabled) { val securityResponse = NewRelicSecurity.getAgent.getSecurityMetaData.getResponse - securityResponse.setResponseCode(response.status.code) + securityResponse.setStatusCode(response.status.code) processResponseHeaders(response.headers, securityResponse) - securityResponse.setResponseContentType(getContentType(securityResponse.getHeaders)) + securityResponse.setContentType(getContentType(securityResponse.getHeaders)) - securityResponse.getResponseBody.append(body) + securityResponse.getBody.append(body) - ServletHelper.executeBeforeExitingTransaction() +// ServletHelper.executeBeforeExitingTransaction() if (!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent.getSecurityMetaData.getResponse.getResponseContentType)) { NewRelicSecurity.getAgent.getSecurityMetaData.getMetaData.setFromJumpRequiredInStackTrace(3) val rxssOperation = new RXSSOperation(NewRelicSecurity.getAgent.getSecurityMetaData.getRequest, NewRelicSecurity.getAgent.getSecurityMetaData.getResponse, this.getClass.getName, METHOD_WITH_HTTP_APP) diff --git a/instrumentation-security/http4s-blaze-server-2.12_0.22/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala b/instrumentation-security/http4s-blaze-server-2.12_0.22/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala index 3fc5dc675..e06299cdd 100644 --- a/instrumentation-security/http4s-blaze-server-2.12_0.22/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala +++ b/instrumentation-security/http4s-blaze-server-2.12_0.22/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala @@ -93,8 +93,8 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", operation.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, operation.getResponse.getResponseContentType) Assert.assertFalse("Headers should not be empty", operation.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getResponseBody.toString) - Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getBody.toString) + Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getStatusCode) } private def assertMetaData(metaData: SecurityMetaData): Unit = { @@ -106,9 +106,9 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", metaData.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, metaData.getResponse.getResponseContentType) - Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getStatusCode) Assert.assertFalse("Headers should not be empty", metaData.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getResponseBody.toString) + Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getBody.toString) } } diff --git a/instrumentation-security/http4s-blaze-server-2.12_0.23/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala b/instrumentation-security/http4s-blaze-server-2.12_0.23/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala index f96537f72..1d1eaaa37 100644 --- a/instrumentation-security/http4s-blaze-server-2.12_0.23/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala +++ b/instrumentation-security/http4s-blaze-server-2.12_0.23/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala @@ -141,13 +141,13 @@ object RequestProcessor { try { if (NewRelicSecurity.isHookProcessingActive && isLockAcquired && !NewRelicSecurity.getAgent.getIastDetectionCategory.getRxssEnabled) { val securityResponse = NewRelicSecurity.getAgent.getSecurityMetaData.getResponse - securityResponse.setResponseCode(response.status.code) + securityResponse.setStatusCode(response.status.code) processResponseHeaders(response.headers, securityResponse) - securityResponse.setResponseContentType(getContentType(securityResponse.getHeaders)) + securityResponse.setContentType(getContentType(securityResponse.getHeaders)) - securityResponse.getResponseBody.append(body) + securityResponse.getBody.append(body) - ServletHelper.executeBeforeExitingTransaction() +// ServletHelper.executeBeforeExitingTransaction() if (!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent.getSecurityMetaData.getResponse.getResponseContentType)) { NewRelicSecurity.getAgent.getSecurityMetaData.getMetaData.setFromJumpRequiredInStackTrace(3) val rxssOperation = new RXSSOperation(NewRelicSecurity.getAgent.getSecurityMetaData.getRequest, NewRelicSecurity.getAgent.getSecurityMetaData.getResponse, this.getClass.getName, METHOD_WITH_HTTP_APP) diff --git a/instrumentation-security/http4s-blaze-server-2.12_0.23/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala b/instrumentation-security/http4s-blaze-server-2.12_0.23/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala index 3fc5dc675..e06299cdd 100644 --- a/instrumentation-security/http4s-blaze-server-2.12_0.23/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala +++ b/instrumentation-security/http4s-blaze-server-2.12_0.23/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala @@ -93,8 +93,8 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", operation.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, operation.getResponse.getResponseContentType) Assert.assertFalse("Headers should not be empty", operation.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getResponseBody.toString) - Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getBody.toString) + Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getStatusCode) } private def assertMetaData(metaData: SecurityMetaData): Unit = { @@ -106,9 +106,9 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", metaData.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, metaData.getResponse.getResponseContentType) - Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getStatusCode) Assert.assertFalse("Headers should not be empty", metaData.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getResponseBody.toString) + Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getBody.toString) } } diff --git a/instrumentation-security/http4s-blaze-server-2.13_0.21/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala b/instrumentation-security/http4s-blaze-server-2.13_0.21/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala index 5d249bf6e..c00a12fc2 100644 --- a/instrumentation-security/http4s-blaze-server-2.13_0.21/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala +++ b/instrumentation-security/http4s-blaze-server-2.13_0.21/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala @@ -138,13 +138,13 @@ object RequestProcessor { try { if (NewRelicSecurity.isHookProcessingActive && isLockAcquired && !NewRelicSecurity.getAgent.getIastDetectionCategory.getRxssEnabled) { val securityResponse = NewRelicSecurity.getAgent.getSecurityMetaData.getResponse - securityResponse.setResponseCode(response.status.code) + securityResponse.setStatusCode(response.status.code) processResponseHeaders(response.headers, securityResponse) - securityResponse.setResponseContentType(getContentType(securityResponse.getHeaders)) + securityResponse.setContentType(getContentType(securityResponse.getHeaders)) - securityResponse.getResponseBody.append(body) + securityResponse.getBody.append(body) - ServletHelper.executeBeforeExitingTransaction() +// ServletHelper.executeBeforeExitingTransaction() if (!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent.getSecurityMetaData.getResponse.getResponseContentType)) { NewRelicSecurity.getAgent.getSecurityMetaData.getMetaData.setFromJumpRequiredInStackTrace(3) val rxssOperation = new RXSSOperation(NewRelicSecurity.getAgent.getSecurityMetaData.getRequest, NewRelicSecurity.getAgent.getSecurityMetaData.getResponse, this.getClass.getName, METHOD_WITH_HTTP_APP) diff --git a/instrumentation-security/http4s-blaze-server-2.13_0.21/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala b/instrumentation-security/http4s-blaze-server-2.13_0.21/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala index 00dc05603..886cd260b 100644 --- a/instrumentation-security/http4s-blaze-server-2.13_0.21/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala +++ b/instrumentation-security/http4s-blaze-server-2.13_0.21/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala @@ -93,8 +93,8 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", operation.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, operation.getResponse.getResponseContentType) Assert.assertFalse("Headers should not be empty", operation.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getResponseBody.toString) - Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getBody.toString) + Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getStatusCode) } private def assertMetaData(metaData: SecurityMetaData): Unit = { @@ -106,9 +106,9 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", metaData.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, metaData.getResponse.getResponseContentType) - Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getStatusCode) Assert.assertFalse("Headers should not be empty", metaData.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getResponseBody.toString) + Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getBody.toString) } } diff --git a/instrumentation-security/http4s-blaze-server-2.13_0.22/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala b/instrumentation-security/http4s-blaze-server-2.13_0.22/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala index 9186f4613..ebd6c6d09 100644 --- a/instrumentation-security/http4s-blaze-server-2.13_0.22/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala +++ b/instrumentation-security/http4s-blaze-server-2.13_0.22/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala @@ -141,13 +141,13 @@ object RequestProcessor { try { if (NewRelicSecurity.isHookProcessingActive && isLockAcquired && !NewRelicSecurity.getAgent.getIastDetectionCategory.getRxssEnabled) { val securityResponse = NewRelicSecurity.getAgent.getSecurityMetaData.getResponse - securityResponse.setResponseCode(response.status.code) + securityResponse.setStatusCode(response.status.code) processResponseHeaders(response.headers, securityResponse) - securityResponse.setResponseContentType(getContentType(securityResponse.getHeaders)) + securityResponse.setContentType(getContentType(securityResponse.getHeaders)) - securityResponse.getResponseBody.append(body) + securityResponse.getBody.append(body) - ServletHelper.executeBeforeExitingTransaction() +// ServletHelper.executeBeforeExitingTransaction() if (!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent.getSecurityMetaData.getResponse.getResponseContentType)) { val rxssOperation = new RXSSOperation(NewRelicSecurity.getAgent.getSecurityMetaData.getRequest, NewRelicSecurity.getAgent.getSecurityMetaData.getResponse, this.getClass.getName, METHOD_WITH_HTTP_APP) NewRelicSecurity.getAgent.getSecurityMetaData.getMetaData.setFromJumpRequiredInStackTrace(3) diff --git a/instrumentation-security/http4s-blaze-server-2.13_0.22/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala b/instrumentation-security/http4s-blaze-server-2.13_0.22/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala index 72aa40728..a058faa92 100644 --- a/instrumentation-security/http4s-blaze-server-2.13_0.22/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala +++ b/instrumentation-security/http4s-blaze-server-2.13_0.22/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala @@ -93,8 +93,8 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", operation.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, operation.getResponse.getResponseContentType) Assert.assertFalse("Headers should not be empty", operation.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getResponseBody.toString) - Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getBody.toString) + Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getStatusCode) } private def assertMetaData(metaData: SecurityMetaData): Unit = { @@ -106,9 +106,9 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", metaData.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, metaData.getResponse.getResponseContentType) - Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getStatusCode) Assert.assertFalse("Headers should not be empty", metaData.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getResponseBody.toString) + Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getBody.toString) } } diff --git a/instrumentation-security/http4s-blaze-server-2.13_0.23/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala b/instrumentation-security/http4s-blaze-server-2.13_0.23/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala index bbcc5281b..6c448fdc3 100644 --- a/instrumentation-security/http4s-blaze-server-2.13_0.23/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala +++ b/instrumentation-security/http4s-blaze-server-2.13_0.23/src/main/scala/com/newrelic/agent/security/http4s/blaze/server/RequestProcessor.scala @@ -142,13 +142,13 @@ object RequestProcessor { try { if (NewRelicSecurity.isHookProcessingActive && isLockAcquired && !NewRelicSecurity.getAgent.getIastDetectionCategory.getRxssEnabled) { val securityResponse = NewRelicSecurity.getAgent.getSecurityMetaData.getResponse - securityResponse.setResponseCode(response.status.code) + securityResponse.setStatusCode(response.status.code) processResponseHeaders(response.headers, securityResponse) - securityResponse.setResponseContentType(getContentType(securityResponse.getHeaders)) + securityResponse.setContentType(getContentType(securityResponse.getHeaders)) - securityResponse.getResponseBody.append(body) + securityResponse.getBody.append(body) - ServletHelper.executeBeforeExitingTransaction() +// ServletHelper.executeBeforeExitingTransaction() if (!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent.getSecurityMetaData.getResponse.getResponseContentType)) { NewRelicSecurity.getAgent.getSecurityMetaData.getMetaData.setFromJumpRequiredInStackTrace(3) val rxssOperation = new RXSSOperation(NewRelicSecurity.getAgent.getSecurityMetaData.getRequest, NewRelicSecurity.getAgent.getSecurityMetaData.getResponse, this.getClass.getName, METHOD_WITH_HTTP_APP) diff --git a/instrumentation-security/http4s-blaze-server-2.13_0.23/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala b/instrumentation-security/http4s-blaze-server-2.13_0.23/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala index 3fc5dc675..e06299cdd 100644 --- a/instrumentation-security/http4s-blaze-server-2.13_0.23/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala +++ b/instrumentation-security/http4s-blaze-server-2.13_0.23/src/test/scala/com/nr/agent/security/instrumentation/blaze/server/BlazeServerBuilderTest.scala @@ -93,8 +93,8 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", operation.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, operation.getResponse.getResponseContentType) Assert.assertFalse("Headers should not be empty", operation.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getResponseBody.toString) - Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getBody.toString) + Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getStatusCode) } private def assertMetaData(metaData: SecurityMetaData): Unit = { @@ -106,9 +106,9 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", metaData.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, metaData.getResponse.getResponseContentType) - Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getStatusCode) Assert.assertFalse("Headers should not be empty", metaData.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getResponseBody.toString) + Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getBody.toString) } } diff --git a/instrumentation-security/http4s-ember-server-2.12_0.23/src/main/scala/com.newrelic.agent.security.http4s.ember.server/RequestProcessor.scala b/instrumentation-security/http4s-ember-server-2.12_0.23/src/main/scala/com.newrelic.agent.security.http4s.ember.server/RequestProcessor.scala index c648c61e4..ccfa37a10 100644 --- a/instrumentation-security/http4s-ember-server-2.12_0.23/src/main/scala/com.newrelic.agent.security.http4s.ember.server/RequestProcessor.scala +++ b/instrumentation-security/http4s-ember-server-2.12_0.23/src/main/scala/com.newrelic.agent.security.http4s.ember.server/RequestProcessor.scala @@ -86,13 +86,13 @@ object RequestProcessor { try { if (isLockAcquired && NewRelicSecurity.isHookProcessingActive && !NewRelicSecurity.getAgent.getIastDetectionCategory.getRxssEnabled) { val securityResponse = NewRelicSecurity.getAgent.getSecurityMetaData.getResponse - securityResponse.setResponseCode(response.status.code) + securityResponse.setStatusCode(response.status.code) processResponseHeaders(response.headers, securityResponse) - securityResponse.setResponseContentType(getContentType(securityResponse.getHeaders)) + securityResponse.setContentType(getContentType(securityResponse.getHeaders)) - securityResponse.getResponseBody.append(body) + securityResponse.getBody.append(body) - ServletHelper.executeBeforeExitingTransaction() +// ServletHelper.executeBeforeExitingTransaction() if (!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent.getSecurityMetaData.getResponse.getResponseContentType)) { val rxssOperation = new RXSSOperation(NewRelicSecurity.getAgent.getSecurityMetaData.getRequest, NewRelicSecurity.getAgent.getSecurityMetaData.getResponse, this.getClass.getName, METHOD_WITH_HTTP_APP) NewRelicSecurity.getAgent.registerOperation(rxssOperation) diff --git a/instrumentation-security/http4s-ember-server-2.12_0.23/src/test/scala/com/nr/agent/security/instrumentation/ember/server/EmberServerBuilderTest.scala b/instrumentation-security/http4s-ember-server-2.12_0.23/src/test/scala/com/nr/agent/security/instrumentation/ember/server/EmberServerBuilderTest.scala index 1c289baf7..25bb8b912 100644 --- a/instrumentation-security/http4s-ember-server-2.12_0.23/src/test/scala/com/nr/agent/security/instrumentation/ember/server/EmberServerBuilderTest.scala +++ b/instrumentation-security/http4s-ember-server-2.12_0.23/src/test/scala/com/nr/agent/security/instrumentation/ember/server/EmberServerBuilderTest.scala @@ -93,8 +93,8 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", operation.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, operation.getResponse.getResponseContentType) Assert.assertFalse("Headers should not be empty", operation.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getResponseBody.toString) - Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getBody.toString) + Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getStatusCode) } private def assertMetaData(metaData: SecurityMetaData): Unit = { @@ -107,9 +107,9 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", metaData.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, metaData.getResponse.getResponseContentType) - Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getStatusCode) Assert.assertFalse("Headers should not be empty", metaData.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getResponseBody.toString) + Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getBody.toString) } } diff --git a/instrumentation-security/http4s-ember-server-2.13_0.23/src/main/scala/com.newrelic.agent.security.http4s.ember.server/RequestProcessor.scala b/instrumentation-security/http4s-ember-server-2.13_0.23/src/main/scala/com.newrelic.agent.security.http4s.ember.server/RequestProcessor.scala index 536ecfc10..1c8e76225 100644 --- a/instrumentation-security/http4s-ember-server-2.13_0.23/src/main/scala/com.newrelic.agent.security.http4s.ember.server/RequestProcessor.scala +++ b/instrumentation-security/http4s-ember-server-2.13_0.23/src/main/scala/com.newrelic.agent.security.http4s.ember.server/RequestProcessor.scala @@ -95,13 +95,13 @@ object RequestProcessor { try { if (isLockAcquired && NewRelicSecurity.isHookProcessingActive && !NewRelicSecurity.getAgent.getIastDetectionCategory.getRxssEnabled) { val securityResponse = NewRelicSecurity.getAgent.getSecurityMetaData.getResponse - securityResponse.setResponseCode(response.status.code) + securityResponse.setStatusCode(response.status.code) processResponseHeaders(response.headers, securityResponse) - securityResponse.setResponseContentType(getContentType(securityResponse.getHeaders)) + securityResponse.setContentType(getContentType(securityResponse.getHeaders)) - securityResponse.getResponseBody.append(body) + securityResponse.getBody.append(body) - ServletHelper.executeBeforeExitingTransaction() +// ServletHelper.executeBeforeExitingTransaction() if (!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent.getSecurityMetaData.getResponse.getResponseContentType)) { val rxssOperation = new RXSSOperation(NewRelicSecurity.getAgent.getSecurityMetaData.getRequest, NewRelicSecurity.getAgent.getSecurityMetaData.getResponse, this.getClass.getName, METHOD_WITH_HTTP_APP) NewRelicSecurity.getAgent.registerOperation(rxssOperation) diff --git a/instrumentation-security/http4s-ember-server-2.13_0.23/src/test/scala/com/nr/agent/security/instrumentation/ember/server/EmberServerBuilderTest.scala b/instrumentation-security/http4s-ember-server-2.13_0.23/src/test/scala/com/nr/agent/security/instrumentation/ember/server/EmberServerBuilderTest.scala index 44e5ef126..f11e4b8e9 100644 --- a/instrumentation-security/http4s-ember-server-2.13_0.23/src/test/scala/com/nr/agent/security/instrumentation/ember/server/EmberServerBuilderTest.scala +++ b/instrumentation-security/http4s-ember-server-2.13_0.23/src/test/scala/com/nr/agent/security/instrumentation/ember/server/EmberServerBuilderTest.scala @@ -93,8 +93,8 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", operation.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, operation.getResponse.getResponseContentType) Assert.assertFalse("Headers should not be empty", operation.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getResponseBody.toString) - Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response body", "Hello, bob.", operation.getResponse.getBody.toString) + Assert.assertEquals("Invalid Response code", 200, operation.getResponse.getStatusCode) } private def assertMetaData(metaData: SecurityMetaData): Unit = { @@ -107,9 +107,9 @@ class EmberServerBuilderTest { Assert.assertFalse("response should not be empty", metaData.getResponse.isEmpty) Assert.assertEquals("Invalid response content-type.", contentType, metaData.getResponse.getResponseContentType) - Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getResponseCode) + Assert.assertEquals("Invalid Response code", 200, metaData.getResponse.getStatusCode) Assert.assertFalse("Headers should not be empty", metaData.getResponse.getHeaders.isEmpty) - Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getResponseBody.toString) + Assert.assertEquals("Invalid Response body", "Hello, bob.", metaData.getResponse.getBody.toString) } } diff --git a/instrumentation-security/java-io-stream/src/main/java/java/io/PrintWriter_Instrumentation.java b/instrumentation-security/java-io-stream/src/main/java/java/io/PrintWriter_Instrumentation.java index 379e073d4..bb7d8174a 100644 --- a/instrumentation-security/java-io-stream/src/main/java/java/io/PrintWriter_Instrumentation.java +++ b/instrumentation-security/java-io-stream/src/main/java/java/io/PrintWriter_Instrumentation.java @@ -37,7 +37,7 @@ public PrintWriter append(char c) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(c); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(c); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -62,7 +62,7 @@ public PrintWriter append(CharSequence csq) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(csq); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(csq); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -87,7 +87,7 @@ public PrintWriter append(CharSequence csq, int start, int end) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(csq, start, end); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(csq, start, end); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -113,7 +113,7 @@ public void print(boolean b) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(b); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(b); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -136,7 +136,7 @@ public void print(char c) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(c); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(c); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -159,7 +159,7 @@ public void print(int i) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(i); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(i); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -182,7 +182,7 @@ public void print(long l) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(l); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(l); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -205,7 +205,7 @@ public void print(float f) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(f); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(f); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -228,7 +228,7 @@ public void print(double d) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(d); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(d); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -251,7 +251,7 @@ public void print(char s[]) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(s); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(s); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -274,7 +274,7 @@ public void print(String s) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(s); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(s); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -297,7 +297,7 @@ public void print(Object obj) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(obj); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(obj); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -320,7 +320,7 @@ public void println() { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(IOStreamHelper.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(IOStreamHelper.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -343,8 +343,8 @@ public void println(boolean x) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(x); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(IOStreamHelper.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(x); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(IOStreamHelper.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -366,8 +366,8 @@ public void println(char x) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(x); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(IOStreamHelper.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(x); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(IOStreamHelper.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -389,8 +389,8 @@ public void println(int x) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(x); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(IOStreamHelper.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(x); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(IOStreamHelper.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -412,8 +412,8 @@ public void println(long x) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(x); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(IOStreamHelper.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(x); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(IOStreamHelper.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -435,8 +435,8 @@ public void println(float x) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(x); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(IOStreamHelper.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(x); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(IOStreamHelper.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -458,8 +458,8 @@ public void println(double x) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(x); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(IOStreamHelper.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(x); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(IOStreamHelper.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -481,8 +481,8 @@ public void println(char x[]) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(x); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(IOStreamHelper.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(x); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(IOStreamHelper.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -504,8 +504,8 @@ public void println(String x) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(x); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(IOStreamHelper.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(x); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(IOStreamHelper.LF); } catch (Throwable ignored) { ignored.printStackTrace(System.out); } @@ -527,8 +527,8 @@ public void println(Object x) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(x); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(IOStreamHelper.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(x); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(IOStreamHelper.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -551,7 +551,7 @@ public void write(String s, int off, int len) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(s, off, len); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(s, off, len); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -573,7 +573,7 @@ public void write(String s) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(s); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(s); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -595,7 +595,7 @@ public void write(char buf[]) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(buf); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(buf); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -617,7 +617,7 @@ public void write(char buf[], int off, int len) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(buf, off, len); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(buf, off, len); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -639,7 +639,7 @@ public void write(int c) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(c); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(c); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -662,7 +662,7 @@ public PrintWriter printf(String format, Object ... args) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(String.format(format, args)); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(String.format(format, args)); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -687,7 +687,7 @@ public PrintWriter printf(Locale l, String format, Object ... args) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(String.format(l, format, args)); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(String.format(l, format, args)); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -711,7 +711,7 @@ public PrintWriter format(String format, Object ... args) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(String.format(format, args)); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(String.format(format, args)); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -736,7 +736,7 @@ public PrintWriter format(Locale l, String format, Object ... args) { // Preprocess Phase if (isLockAcquired) { try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(String.format(l, format, args)); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(String.format(l, format, args)); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } diff --git a/instrumentation-security/java-io-stream/src/test/java/com/nr/agent/security/instrumentation/inputstream/OutputStreamTest.java b/instrumentation-security/java-io-stream/src/test/java/com/nr/agent/security/instrumentation/inputstream/OutputStreamTest.java index 486b24fed..cbf4ea734 100644 --- a/instrumentation-security/java-io-stream/src/test/java/com/nr/agent/security/instrumentation/inputstream/OutputStreamTest.java +++ b/instrumentation-security/java-io-stream/src/test/java/com/nr/agent/security/instrumentation/inputstream/OutputStreamTest.java @@ -77,7 +77,7 @@ public void testWrite() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); // Assert.assertFalse("Empty response in security meta data", meta.getResponse().isEmpty()); - Assert.assertEquals(DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA, meta.getResponse().getBody().toString()); } @Test @@ -96,7 +96,7 @@ public void testWrite1() throws JsonProcessingException { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); // Assert.assertFalse("Empty response in security meta data", meta.getResponse().isEmpty()); - Assert.assertEquals(DATA.substring(2, 27), meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA.substring(2, 27), meta.getResponse().getBody().toString()); } @Test @@ -115,6 +115,6 @@ public void testErrorInWrite() throws JsonProcessingException { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); Assert.assertTrue("Non-empty response in security meta data", meta.getResponse().isEmpty()); - Assert.assertEquals("", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("", meta.getResponse().getBody().toString()); } } diff --git a/instrumentation-security/java-io-stream/src/test/java/com/nr/agent/security/instrumentation/inputstream/PrintWriterTest.java b/instrumentation-security/java-io-stream/src/test/java/com/nr/agent/security/instrumentation/inputstream/PrintWriterTest.java index 86a2c7e9a..aba1a1dd3 100644 --- a/instrumentation-security/java-io-stream/src/test/java/com/nr/agent/security/instrumentation/inputstream/PrintWriterTest.java +++ b/instrumentation-security/java-io-stream/src/test/java/com/nr/agent/security/instrumentation/inputstream/PrintWriterTest.java @@ -69,7 +69,7 @@ public void testAppendChar() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(String.valueOf(DATA.charAt(5)), meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(String.valueOf(DATA.charAt(5)), meta.getResponse().getBody().toString()); } @Test @@ -87,7 +87,7 @@ public void testAppendString() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA, meta.getResponse().getBody().toString()); } @Test @@ -105,7 +105,7 @@ public void testAppendString1() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA.substring(2, 20), meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA.substring(2, 20), meta.getResponse().getBody().toString()); } @Test @@ -123,7 +123,7 @@ public void testPrintBoolean() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("true", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("true", meta.getResponse().getBody().toString()); } @Test @@ -141,7 +141,7 @@ public void testPrintChar() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(String.valueOf(DATA.charAt(9)), meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(String.valueOf(DATA.charAt(9)), meta.getResponse().getBody().toString()); } @Test @@ -160,7 +160,7 @@ public void testPrintCharArray() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA, meta.getResponse().getBody().toString()); } @Test @@ -178,7 +178,7 @@ public void testPrintInt() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("2", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("2", meta.getResponse().getBody().toString()); } @Test @@ -196,7 +196,7 @@ public void testPrintLong() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("2", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("2", meta.getResponse().getBody().toString()); } @Test @@ -214,7 +214,7 @@ public void testPrintFloat() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("2.0", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("2.0", meta.getResponse().getBody().toString()); } @Test @@ -232,7 +232,7 @@ public void testPrintDouble() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("2.0", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("2.0", meta.getResponse().getBody().toString()); } @Test @@ -250,7 +250,7 @@ public void testPrintString() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA, meta.getResponse().getBody().toString()); } @Test @@ -269,7 +269,7 @@ public void testPrintObject() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(ob.toString(), meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(ob.toString(), meta.getResponse().getBody().toString()); } @Test @@ -287,7 +287,7 @@ public void testPrintln() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("\n", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("\n", meta.getResponse().getBody().toString()); } @Test @@ -305,7 +305,7 @@ public void testPrintlnBoolean() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("true\n", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("true\n", meta.getResponse().getBody().toString()); } @Test @@ -323,7 +323,7 @@ public void testPrintlnChar() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(String.valueOf(DATA.charAt(9))+"\n", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(String.valueOf(DATA.charAt(9))+"\n", meta.getResponse().getBody().toString()); } @Test @@ -342,7 +342,7 @@ public void testPrintlnCharArray() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA+"\n", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA+"\n", meta.getResponse().getBody().toString()); } @Test @@ -360,7 +360,7 @@ public void testPrintlnInt() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("2\n", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("2\n", meta.getResponse().getBody().toString()); } @Test @@ -378,7 +378,7 @@ public void testPrintlnLong() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("2\n", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("2\n", meta.getResponse().getBody().toString()); } @Test @@ -396,7 +396,7 @@ public void testPrintlnFloat() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("2.0\n", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("2.0\n", meta.getResponse().getBody().toString()); } @Test @@ -414,7 +414,7 @@ public void testPrintlnDouble() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("2.0\n", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("2.0\n", meta.getResponse().getBody().toString()); } @Test @@ -432,7 +432,7 @@ public void testPrintlnString() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA+"\n", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA+"\n", meta.getResponse().getBody().toString()); } @Test @@ -451,7 +451,7 @@ public void testPrintlnObject() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(ob+"\n", meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(ob+"\n", meta.getResponse().getBody().toString()); } @Test @@ -469,7 +469,7 @@ public void testPrintf() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("test "+DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("test "+DATA, meta.getResponse().getBody().toString()); } @Test @@ -487,7 +487,7 @@ public void testPrintf1() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA, meta.getResponse().getBody().toString()); } @Test @@ -505,7 +505,7 @@ public void testPrintfLocale() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("test "+DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("test "+DATA, meta.getResponse().getBody().toString()); } @Test @@ -523,7 +523,7 @@ public void testPrintfLocale1() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA, meta.getResponse().getBody().toString()); } @Test @@ -541,7 +541,7 @@ public void testWriteString() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA, meta.getResponse().getBody().toString()); } @Test @@ -559,7 +559,7 @@ public void testWriteString1() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA.substring(2, 8), meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA.substring(2, 8), meta.getResponse().getBody().toString()); } @Test @@ -578,7 +578,7 @@ public void testWriteChar() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA, meta.getResponse().getBody().toString()); } @Test @@ -597,7 +597,7 @@ public void testWriteChar1() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA.substring(2, 10), meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA.substring(2, 10), meta.getResponse().getBody().toString()); } @Test @@ -615,7 +615,7 @@ public void testWriteInt() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(1, Integer.parseInt(meta.getResponse().getResponseBody().toString())); + Assert.assertEquals(1, Integer.parseInt(meta.getResponse().getBody().toString())); } @Test @@ -633,7 +633,7 @@ public void testFormat() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("test "+DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("test "+DATA, meta.getResponse().getBody().toString()); } @Test @@ -651,7 +651,7 @@ public void testFormat1() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA, meta.getResponse().getBody().toString()); } @Test @@ -669,7 +669,7 @@ public void testFormatLocale() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals("test "+DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals("test "+DATA, meta.getResponse().getBody().toString()); } @Test @@ -687,7 +687,7 @@ public void testFormatLocale1() { SecurityMetaData meta = introspector.getSecurityMetaData(); Assert.assertNotNull("Empty security meta data", meta); - Assert.assertEquals(DATA, meta.getResponse().getResponseBody().toString()); + Assert.assertEquals(DATA, meta.getResponse().getBody().toString()); } } diff --git a/instrumentation-security/java-reflection/build.gradle b/instrumentation-security/java-reflection/build.gradle new file mode 100644 index 000000000..d41d6b414 --- /dev/null +++ b/instrumentation-security/java-reflection/build.gradle @@ -0,0 +1,16 @@ +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") +} + +// This instrumentation module should not use the bootstrap classpath + + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.java-reflection' } +} + +verifyInstrumentation { + verifyClasspath = false // We don't want to verify classpath since these are JDK classes +} diff --git a/instrumentation-security/java-reflection/src/main/java/java/lang/reflect/Method_Instrumentation.java b/instrumentation-security/java-reflection/src/main/java/java/lang/reflect/Method_Instrumentation.java new file mode 100644 index 000000000..ac7868d0f --- /dev/null +++ b/instrumentation-security/java-reflection/src/main/java/java/lang/reflect/Method_Instrumentation.java @@ -0,0 +1,73 @@ +package java.lang.reflect; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; +import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.JavaReflectionOperation; +import com.newrelic.api.agent.security.utils.logging.LogLevel; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@Weave(type = MatchType.ExactClass, originalName = "java.lang.reflect.Method") +public abstract class Method_Instrumentation { + + public abstract String getName(); + + public abstract Class getDeclaringClass(); + + public abstract Class[] getParameterTypes(); + + public Object invoke(Object obj, Object... args) { + AbstractOperation operation = null; + if(NewRelicSecurity.isHookProcessingActive()) { + operation = preprocessSecurityHook(obj, getDeclaringClass(), getParameterTypes(), getName(), args); + } + Object returnValue = Weaver.callOriginal(); + registerExitOperation(operation); + return returnValue; + } + + private void registerExitOperation(AbstractOperation operation) { + if (operation == null || !NewRelicSecurity.isHookProcessingActive() || + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() || GenericHelper.skipExistsEvent() + ) { + return; + } + NewRelicSecurity.getAgent().registerExitEvent(operation); + } + + private AbstractOperation preprocessSecurityHook(Object obj, Class declaringClass, Class[] parameterTypes, String name, Object[] args) { + try { + if(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() || !GenericHelper.isLockAcquirePossible(VulnerabilityCaseType.REFLECTION)) { + return null; + } + + JavaReflectionOperation operation = new JavaReflectionOperation(this.getClass().getName(), "invoke", declaringClass.getName(), name, args, obj); + List methodNames = new ArrayList<>(); + for (Method method : declaringClass.getDeclaredMethods()) { + if(Arrays.equals(method.getParameterTypes(), parameterTypes)) { + methodNames.add(method.getName()); + } + } + operation.setDeclaredMethods(methodNames); + NewRelicSecurity.getAgent().registerOperation(operation); + return operation; + } catch (Throwable e) { + if(e instanceof NewRelicSecurityException){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "JAVA-REFLECTION", e.getMessage()), e, Method_Instrumentation.class.getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "JAVA-REFLECTION", e.getMessage()), e, Method_Instrumentation.class.getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "JAVA-REFLECTION", e.getMessage()), e, Method_Instrumentation.class.getName()); + } + return null; + } +} diff --git a/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java b/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java index d3fae0771..ff327152a 100644 --- a/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java +++ b/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java @@ -28,13 +28,13 @@ public abstract class ContainerResponse_Instrumentation { ContainerResponse_Instrumentation(final ContainerRequest requestContext, final OutboundJaxrsResponse response) { if (NewRelicSecurity.getAgent().getSecurityMetaData() != null) { if (response != null) { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(response.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(response.getStatus()); } if (GenericHelper.isLockAcquired(HttpRequestHelper.getNrSecCustomAttribForPostProcessing()) && response != null && response.getContext() != null && response.getContext().hasEntity()) { Object responseObject = response.getContext().getEntity(); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(new StringBuilder(String.valueOf(responseObject))); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setBody(new StringBuilder(String.valueOf(responseObject))); } } } @@ -44,7 +44,7 @@ public abstract class ContainerResponse_Instrumentation { public void close() { boolean isLockAcquired = false; try { - isLockAcquired = GenericHelper.acquireLockIfPossible(SERVLET_GET_IS_OPERATION_LOCK); + isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SERVLET_GET_IS_OPERATION_LOCK); if(isLockAcquired && GenericHelper.isLockAcquired(HttpRequestHelper.getNrSecCustomAttribForPostProcessing())) { HttpRequestHelper.postProcessSecurityHook(this.getClass().getName(), getWrappedMessageContext()); } diff --git a/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java b/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java index caf2e17b2..9f60b2a96 100644 --- a/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java +++ b/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java @@ -77,7 +77,7 @@ public static void postProcessSecurityHook(String className, OutboundMessageCont ) { return; } - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(getHeaders(wrappedMessageContext)); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); @@ -105,7 +105,7 @@ private static Map getHeaders(OutboundMessageContext outboundMes for (String key : outboundMessageContext.getStringHeaders().keySet()) { headers.put(key, outboundMessageContext.getHeaderString(key)); if(StringUtils.equalsAny(StringUtils.lowerCase(key), "content-type", "contenttype")){ - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(outboundMessageContext.getHeaderString(key)); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(outboundMessageContext.getHeaderString(key)); } } return headers; diff --git a/instrumentation-security/jersey-2.16/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java b/instrumentation-security/jersey-2.16/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java index 19fb1f5d3..8d7b14891 100644 --- a/instrumentation-security/jersey-2.16/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java +++ b/instrumentation-security/jersey-2.16/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java @@ -202,7 +202,7 @@ private void assertOperation(List operations, boolean hasHead assertFalse(response.isEmpty()); assertEquals(MediaType.TEXT_HTML, response.getResponseContentType()); assertEquals(2, responseBody.length); - assertEquals(responseBody[0], response.getResponseBody().toString()); + assertEquals(responseBody[0], response.getBody().toString()); assertFalse(hashCode.isEmpty()); assertEquals(Collections.singleton(Integer.parseInt(responseBody[1])), hashCode); } diff --git a/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java b/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java index 69d0ae019..b31cdb629 100644 --- a/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java +++ b/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java @@ -27,13 +27,13 @@ public abstract class ContainerResponse_Instrumentation { ContainerResponse_Instrumentation(final ContainerRequest requestContext, final OutboundJaxrsResponse response) { if (NewRelicSecurity.getAgent().getSecurityMetaData() != null) { if (response != null) { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(response.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(response.getStatus()); } if (GenericHelper.isLockAcquired(HttpRequestHelper.getNrSecCustomAttribForPostProcessing()) && response != null && response.getContext() != null && response.getContext().hasEntity()) { Object responseObject = response.getContext().getEntity(); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(new StringBuilder(String.valueOf(responseObject))); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setBody(new StringBuilder(String.valueOf(responseObject))); } } } @@ -43,7 +43,7 @@ public abstract class ContainerResponse_Instrumentation { public void close() { boolean isLockAcquired = false; try { - isLockAcquired = GenericHelper.acquireLockIfPossible(SERVLET_GET_IS_OPERATION_LOCK); + isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SERVLET_GET_IS_OPERATION_LOCK); if(isLockAcquired && GenericHelper.isLockAcquired(HttpRequestHelper.getNrSecCustomAttribForPostProcessing())) { HttpRequestHelper.postProcessSecurityHook(this.getClass().getName(), getWrappedMessageContext()); } diff --git a/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java b/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java index 1cb4cc819..9987a470f 100644 --- a/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java +++ b/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java @@ -79,7 +79,7 @@ public static void postProcessSecurityHook(String className, OutboundMessageCont if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled() || Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class))) { return; } - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(getHeaders(wrappedMessageContext)); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); @@ -107,7 +107,7 @@ private static Map getHeaders(OutboundMessageContext outboundMes for (String key : outboundMessageContext.getStringHeaders().keySet()) { headers.put(key, outboundMessageContext.getHeaderString(key)); if(StringUtils.equalsAny(StringUtils.lowerCase(key), CONTENT_TYPE, HEADER_CONTENT_TYPE)){ - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(outboundMessageContext.getHeaderString(key)); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(outboundMessageContext.getHeaderString(key)); } } return headers; diff --git a/instrumentation-security/jersey-2/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java b/instrumentation-security/jersey-2/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java index fe5b4e607..792b93ced 100644 --- a/instrumentation-security/jersey-2/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java +++ b/instrumentation-security/jersey-2/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java @@ -205,7 +205,7 @@ private void assertOperation(List operations, boolean hasHead assertFalse(response.isEmpty()); assertEquals(MediaType.TEXT_HTML, response.getResponseContentType()); assertEquals(2, responseBody.length); - assertEquals(responseBody[0], response.getResponseBody().toString()); + assertEquals(responseBody[0], response.getBody().toString()); assertFalse(hashCode.isEmpty()); assertEquals(Collections.singleton(Integer.parseInt(responseBody[1])), hashCode); } diff --git a/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java b/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java index 69d0ae019..b31cdb629 100644 --- a/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java +++ b/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java @@ -27,13 +27,13 @@ public abstract class ContainerResponse_Instrumentation { ContainerResponse_Instrumentation(final ContainerRequest requestContext, final OutboundJaxrsResponse response) { if (NewRelicSecurity.getAgent().getSecurityMetaData() != null) { if (response != null) { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(response.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(response.getStatus()); } if (GenericHelper.isLockAcquired(HttpRequestHelper.getNrSecCustomAttribForPostProcessing()) && response != null && response.getContext() != null && response.getContext().hasEntity()) { Object responseObject = response.getContext().getEntity(); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(new StringBuilder(String.valueOf(responseObject))); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setBody(new StringBuilder(String.valueOf(responseObject))); } } } @@ -43,7 +43,7 @@ public abstract class ContainerResponse_Instrumentation { public void close() { boolean isLockAcquired = false; try { - isLockAcquired = GenericHelper.acquireLockIfPossible(SERVLET_GET_IS_OPERATION_LOCK); + isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SERVLET_GET_IS_OPERATION_LOCK); if(isLockAcquired && GenericHelper.isLockAcquired(HttpRequestHelper.getNrSecCustomAttribForPostProcessing())) { HttpRequestHelper.postProcessSecurityHook(this.getClass().getName(), getWrappedMessageContext()); } diff --git a/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java b/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java index 14d88c1af..0be06171a 100644 --- a/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java +++ b/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java @@ -82,7 +82,7 @@ public static void postProcessSecurityHook(String className, OutboundMessageCont ) { return; } - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(getHeaders(wrappedMessageContext)); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); @@ -110,7 +110,7 @@ private static Map getHeaders(OutboundMessageContext outboundMes for (String key : outboundMessageContext.getStringHeaders().keySet()) { headers.put(key, outboundMessageContext.getHeaderString(key)); if(StringUtils.equalsAny(StringUtils.lowerCase(key), "content-type", "contenttype")){ - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(outboundMessageContext.getHeaderString(key)); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(outboundMessageContext.getHeaderString(key)); } } return headers; diff --git a/instrumentation-security/jersey-3/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java b/instrumentation-security/jersey-3/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java index 0ccf39689..5f7bf1163 100644 --- a/instrumentation-security/jersey-3/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java +++ b/instrumentation-security/jersey-3/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java @@ -202,7 +202,7 @@ private void assertOperation(List operations, boolean hasHead assertFalse(response.isEmpty()); assertEquals(MediaType.TEXT_HTML, response.getResponseContentType()); assertEquals(2, responseBody.length); - assertEquals(responseBody[0], response.getResponseBody().toString()); + assertEquals(responseBody[0], response.getBody().toString()); assertFalse(hashCode.isEmpty()); assertEquals(Collections.singleton(Integer.parseInt(responseBody[1])), hashCode); } diff --git a/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java b/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java index a7462ae17..7c05f59e3 100644 --- a/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java +++ b/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java @@ -158,9 +158,10 @@ public static void postProcessSecurityHook(HttpServletRequest request, HttpServl if(!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ return; } - - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(response.getStatus()); - ServletHelper.executeBeforeExitingTransaction(); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(response.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(response.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(JettyUtils.getHttpResponseHeaders(response)); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); if(!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseContentType())){ diff --git a/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/JettyUtils.java b/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/JettyUtils.java index 7fcafd722..f776f3b3f 100644 --- a/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/JettyUtils.java +++ b/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/JettyUtils.java @@ -1,8 +1,12 @@ package com.newrelic.agent.security.instrumentation.jetty11; import com.newrelic.api.agent.security.schema.StringUtils; +import jakarta.servlet.http.HttpServletResponse; +import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; public class JettyUtils { public static String getProtocol(List protocols) { @@ -16,4 +20,13 @@ public static String getProtocol(List protocols) { return null; } + + public static Map getHttpResponseHeaders(HttpServletResponse response) { + Collection headerNames = response.getHeaderNames(); + Map headers = new java.util.HashMap<>(); + headerNames.forEach( headerName -> { + headers.put(headerName, response.getHeader(headerName)); + }); + return headers; + } } diff --git a/instrumentation-security/jetty-12/src/main/java/com/newrelic/agent/security/instrumentation/jetty12/server/HttpServletHelper.java b/instrumentation-security/jetty-12/src/main/java/com/newrelic/agent/security/instrumentation/jetty12/server/HttpServletHelper.java index d0d8f8637..42ccfe1e6 100644 --- a/instrumentation-security/jetty-12/src/main/java/com/newrelic/agent/security/instrumentation/jetty12/server/HttpServletHelper.java +++ b/instrumentation-security/jetty-12/src/main/java/com/newrelic/agent/security/instrumentation/jetty12/server/HttpServletHelper.java @@ -152,16 +152,16 @@ public static void preprocessSecurityHook(Request request) { public static void postProcessSecurityHook(Request request, Response response, String className, String methodName) { try { - if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ - return; - } if (!NewRelicSecurity.isHookProcessingActive()) { return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(response.getStatus()); - ServletHelper.executeBeforeExitingTransaction(); - //Add request URI hash to low severity event filter + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(response.getStatus()); + JettyUtils.processResponseHeaders(response, NewRelicSecurity.getAgent().getSecurityMetaData().getResponse()); LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); + +// ServletHelper.executeBeforeExitingTransaction(); + //Add request URI hash to low severity event filter + RXSSOperation rxssOperation = new RXSSOperation(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest(), NewRelicSecurity.getAgent().getSecurityMetaData().getResponse(), className, methodName); diff --git a/instrumentation-security/jetty-12/src/main/java/com/newrelic/agent/security/instrumentation/jetty12/server/JettyUtils.java b/instrumentation-security/jetty-12/src/main/java/com/newrelic/agent/security/instrumentation/jetty12/server/JettyUtils.java index 98a3364ae..b475ce3d2 100644 --- a/instrumentation-security/jetty-12/src/main/java/com/newrelic/agent/security/instrumentation/jetty12/server/JettyUtils.java +++ b/instrumentation-security/jetty-12/src/main/java/com/newrelic/agent/security/instrumentation/jetty12/server/JettyUtils.java @@ -1,6 +1,9 @@ package com.newrelic.agent.security.instrumentation.jetty12.server; +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.schema.HttpResponse; import com.newrelic.api.agent.security.schema.StringUtils; +import org.eclipse.jetty.server.Response; import java.util.List; @@ -16,4 +19,13 @@ public static String getProtocol(List protocols) { return null; } + + public static void processResponseHeaders(Response jettyResponse, HttpResponse response) { + jettyResponse.getHeaders().forEach(header -> { + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getHeaders().put(header.getName(), header.getValue()); + if(StringUtils.equalsAny(StringUtils.lowerCase(header.getName()), "content-type", "contenttype")){ + response.setContentType(header.getValue()); + } + }); + } } diff --git a/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java b/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java index 6ceb729a8..8c0b32eef 100644 --- a/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java +++ b/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java @@ -159,9 +159,10 @@ public static void postProcessSecurityHook(HttpServletRequest request, HttpServl if(!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ return; } - - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(response.getStatus()); - ServletHelper.executeBeforeExitingTransaction(); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(response.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(response.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(JettyUtils.getHttpResponseHeaders(response)); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); if(!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseContentType())) { diff --git a/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/JettyUtils.java b/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/JettyUtils.java index a572a7796..8070f534d 100644 --- a/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/JettyUtils.java +++ b/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/JettyUtils.java @@ -2,7 +2,10 @@ import com.newrelic.api.agent.security.schema.StringUtils; +import javax.servlet.http.HttpServletResponse; +import java.util.Collection; import java.util.List; +import java.util.Map; public class JettyUtils { public static String getProtocol(List protocols) { @@ -16,4 +19,13 @@ public static String getProtocol(List protocols) { return null; } + + public static Map getHttpResponseHeaders(HttpServletResponse response) { + Collection headerNames = response.getHeaderNames(); + Map headers = new java.util.HashMap<>(); + headerNames.forEach( headerName -> { + headers.put(headerName, response.getHeader(headerName)); + }); + return headers; + } } diff --git a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/domain/ByteArrayHttpEntity_Instrumentation.java b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/domain/ByteArrayHttpEntity_Instrumentation.java index eeea3a477..787c5cc26 100644 --- a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/domain/ByteArrayHttpEntity_Instrumentation.java +++ b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/domain/ByteArrayHttpEntity_Instrumentation.java @@ -37,7 +37,7 @@ private void extractResponseBody(byte[] content) throws IOException { SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); if (MuleHelper.preprocessStream(this.hashCode(), MuleHelper.RESPONSE_ENTITY_STREAM)) { - securityMetaData.getResponse().getResponseBody().append(body); + securityMetaData.getResponse().getBody().append(body); } else if (MuleHelper.preprocessStream(this.hashCode(), MuleHelper.REQUEST_ENTITY_STREAM)) { securityMetaData.getRequest().getBody().append(body); } diff --git a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/domain/response/HttpResponseBuilder_Instrumentation.java b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/domain/response/HttpResponseBuilder_Instrumentation.java index 9adaa1d8f..2bd4cb9e0 100644 --- a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/domain/response/HttpResponseBuilder_Instrumentation.java +++ b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/domain/response/HttpResponseBuilder_Instrumentation.java @@ -19,8 +19,8 @@ @Weave(type = MatchType.ExactClass, originalName = "org.mule.module.http.internal.domain.response.HttpResponseBuilder") public class HttpResponseBuilder_Instrumentation { - private ResponseStatus responseStatus = Weaver.callOriginal(); - private HttpEntity body = Weaver.callOriginal(); + private final ResponseStatus responseStatus = Weaver.callOriginal(); + private final HttpEntity body = Weaver.callOriginal(); public HttpResponse build() { HttpResponse response = Weaver.callOriginal(); @@ -39,8 +39,8 @@ private void postProcessSecurityHook(HttpResponse response) { com.newrelic.api.agent.security.schema.HttpResponse securityResponse = NewRelicSecurity.getAgent().getSecurityMetaData().getResponse(); MuleHelper.processHttpResponseHeaders(securityResponse, response); - securityResponse.setResponseCode(response.getStatusCode()); - securityResponse.setResponseContentType(MuleHelper.getContentType(securityResponse.getHeaders())); + securityResponse.setStatusCode(response.getStatusCode()); + securityResponse.setContentType(MuleHelper.getContentType(securityResponse.getHeaders())); } catch (Throwable e) { NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.ERROR_PARSING_HTTP_RESPONSE, MuleHelper.MULE_36, e.getMessage()), e, this.getClass().getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.ERROR_PARSING_HTTP_RESPONSE, MuleHelper.MULE_36, e.getMessage()), e, this.getClass().getName()); diff --git a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java index 826faab83..58dbb2324 100644 --- a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java +++ b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java @@ -79,7 +79,9 @@ private static void preprocessSecurityHook(HttpRequestContext requestContext) { securityRequest.setContentType(MuleHelper.getContentType(securityRequest.getHeaders())); securityRequest.setRequestParsed(true); - } catch (Throwable ignored){} + } catch (Throwable ignored){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, MuleHelper.MULE_36, ignored.getMessage()), ignored, HttpRequestToMuleEvent_Instrumentation.class.getName()); + } } private static void postProcessSecurityHook() { @@ -89,7 +91,7 @@ private static void postProcessSecurityHook() { return; } ServletHelper.registerUserLevelCode(MuleHelper.LIBRARY_NAME); - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); @@ -108,6 +110,8 @@ private static void postProcessSecurityHook() { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, MuleHelper.MULE_36, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); throw e; } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_36, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_36, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); } } diff --git a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java index 55972e708..4c79c587e 100644 --- a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java +++ b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java @@ -78,7 +78,7 @@ private void postProcessSecurityHook() { return; } ServletHelper.registerUserLevelCode(MuleHelper.LIBRARY_NAME); - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/domain/ByteArrayHttpEntity_Instrumentation.java b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/domain/ByteArrayHttpEntity_Instrumentation.java index e4288ad1c..bac4cf4a2 100644 --- a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/domain/ByteArrayHttpEntity_Instrumentation.java +++ b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/domain/ByteArrayHttpEntity_Instrumentation.java @@ -36,7 +36,7 @@ private void extractResponseBody(byte[] content) throws IOException { SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); if (MuleHelper.preprocessStream(this.hashCode(), MuleHelper.RESPONSE_ENTITY_STREAM)) { - securityMetaData.getResponse().getResponseBody().append(body); + securityMetaData.getResponse().getBody().append(body); } else if (MuleHelper.preprocessStream(this.hashCode(), MuleHelper.REQUEST_ENTITY_STREAM)) { securityMetaData.getRequest().getBody().append(body); } diff --git a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/domain/response/HttpResponseBuilder_Instrumentation.java b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/domain/response/HttpResponseBuilder_Instrumentation.java index e0b3bac37..ef15c71b3 100644 --- a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/domain/response/HttpResponseBuilder_Instrumentation.java +++ b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/domain/response/HttpResponseBuilder_Instrumentation.java @@ -19,8 +19,8 @@ @Weave(type = MatchType.ExactClass, originalName = "org.mule.module.http.internal.domain.response.HttpResponseBuilder") public class HttpResponseBuilder_Instrumentation { - private ResponseStatus responseStatus = Weaver.callOriginal(); - private HttpEntity body = Weaver.callOriginal(); + private final ResponseStatus responseStatus = Weaver.callOriginal(); + private final HttpEntity body = Weaver.callOriginal(); public HttpResponse build() { HttpResponse response = Weaver.callOriginal(); @@ -39,8 +39,8 @@ private void postProcessSecurityHook(HttpResponse response) { } com.newrelic.api.agent.security.schema.HttpResponse securityResponse = NewRelicSecurity.getAgent().getSecurityMetaData().getResponse(); MuleHelper.processHttpResponseHeaders(securityResponse, response); - securityResponse.setResponseCode(response.getStatusCode()); - securityResponse.setResponseContentType(MuleHelper.getContentType(securityResponse.getHeaders())); + securityResponse.setStatusCode(response.getStatusCode()); + securityResponse.setContentType(MuleHelper.getContentType(securityResponse.getHeaders())); } catch (Throwable e) { NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.ERROR_PARSING_HTTP_RESPONSE, MuleHelper.MULE_37, e.getMessage()), e, this.getClass().getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.ERROR_PARSING_HTTP_RESPONSE, MuleHelper.MULE_37, e.getMessage()), e, this.getClass().getName()); diff --git a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java index a3895f206..d9805fc16 100644 --- a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java +++ b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java @@ -85,7 +85,9 @@ private static void preprocessSecurityHook(HttpRequestContext requestContext) { securityRequest.setContentType(MuleHelper.getContentType(securityRequest.getHeaders())); securityRequest.setRequestParsed(true); - } catch (Throwable ignored){} + } catch (Throwable ignored){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, MuleHelper.MULE_37, ignored.getMessage()), ignored, HttpRequestToMuleEvent_Instrumentation.class.getName()); + } } private static void postProcessSecurityHook() { @@ -94,7 +96,7 @@ private static void postProcessSecurityHook() { return; } ServletHelper.registerUserLevelCode(MuleHelper.LIBRARY_NAME); - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); @@ -111,6 +113,8 @@ private static void postProcessSecurityHook() { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, MuleHelper.MULE_37, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); throw e; } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_37, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_37, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); } } diff --git a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java index 4d89bbc40..c7edfb67c 100644 --- a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java +++ b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java @@ -19,6 +19,7 @@ @Weave(type = MatchType.Interface, originalName = "org.mule.module.http.internal.listener.async.RequestHandler") public class RequestHandler_Instrumentation { + public void handleRequest(HttpRequestContext requestContext, HttpResponseReadyCallback responseCallback) { boolean isLockAcquired = acquireLockIfPossible(requestContext.hashCode()); if (isLockAcquired) { @@ -70,7 +71,9 @@ private void preprocessSecurityHook(HttpRequestContext requestContext) { securityRequest.setContentType(MuleHelper.getContentType(securityRequest.getHeaders())); securityRequest.setRequestParsed(true); - } catch (Throwable ignored){} + } catch (Throwable ignored){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, MuleHelper.MULE_37, ignored.getMessage()), ignored, RequestHandler_Instrumentation.class.getName()); + } } private void postProcessSecurityHook() { @@ -79,7 +82,7 @@ private void postProcessSecurityHook() { return; } ServletHelper.registerUserLevelCode(MuleHelper.LIBRARY_NAME); - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); @@ -98,6 +101,8 @@ private void postProcessSecurityHook() { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, MuleHelper.MULE_37, e.getMessage()), e, this.getClass().getName()); throw e; } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_37, e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_37, e.getMessage()), e, this.getClass().getName()); } } diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java index 9833b89d7..b9b37c33a 100644 --- a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java @@ -176,8 +176,8 @@ public static void processSecurityResponse(ChannelHandlerContext ctx, Object msg com.newrelic.api.agent.security.schema.HttpResponse securityResponse = securityMetaData.getResponse(); processResponseHeaders((HttpResponse) msg, securityResponse); - securityResponse.setResponseContentType(((FullHttpResponse) msg).headers().get(HttpHeaders.Names.CONTENT_TYPE)); - securityResponse.getResponseBody().append(((FullHttpResponse) msg).content().toString(StandardCharsets.UTF_8)); + securityResponse.setContentType(((FullHttpResponse) msg).headers().get(HttpHeaders.Names.CONTENT_TYPE)); + securityResponse.getBody().append(((FullHttpResponse) msg).content().toString(StandardCharsets.UTF_8)); } } catch (Throwable e) { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(ERROR_PARSING_HTTP_RESPONSE_DATA, NETTY_4_0_0, e.getMessage()), e, NettyUtils.class.getName()); @@ -189,8 +189,8 @@ public static void sendRXSSEvent(ChannelHandlerContext ctx, Object msg, String c if (!NewRelicSecurity.isHookProcessingActive() || !(msg instanceof FullHttpResponse) || NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()) { return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(((FullHttpResponse) msg).getStatus().code()); - ServletHelper.executeBeforeExitingTransaction(); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(((FullHttpResponse) msg).getStatus().code()); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/netty-4.0.0/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java b/instrumentation-security/netty-4.0.0/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java index 23a4f9ed8..c648ca0e2 100644 --- a/instrumentation-security/netty-4.0.0/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java +++ b/instrumentation-security/netty-4.0.0/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java @@ -59,7 +59,7 @@ public void testChannelRXSS() throws IOException { HttpResponse response = introspector.getSecurityMetaData().getResponse(); Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); - Assert.assertEquals("Invalid response body", "write data", response.getResponseBody().toString()); + Assert.assertEquals("Invalid response body", "write data", response.getBody().toString()); } @Test public void testChannelRead() { @@ -92,7 +92,7 @@ public void testWrite() { HttpResponse response = introspector.getSecurityMetaData().getResponse(); Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); - Assert.assertEquals("Invalid response body", "write data", response.getResponseBody().toString()); + Assert.assertEquals("Invalid response body", "write data", response.getBody().toString()); } @Test @@ -110,7 +110,7 @@ public void testWriteAndFlush() { HttpResponse response = introspector.getSecurityMetaData().getResponse(); Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); - Assert.assertEquals("Invalid response body", "write flush data", response.getResponseBody().toString()); + Assert.assertEquals("Invalid response body", "write flush data", response.getBody().toString()); } @Test @@ -128,7 +128,7 @@ public void testWriteAndFlushPromise() { HttpResponse response = introspector.getSecurityMetaData().getResponse(); Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); - Assert.assertEquals("Invalid response body", "write flush promise data", response.getResponseBody().toString()); + Assert.assertEquals("Invalid response body", "write flush promise data", response.getBody().toString()); } @Test @@ -146,7 +146,7 @@ public void testEncode() { HttpResponse response = introspector.getSecurityMetaData().getResponse(); Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); - Assert.assertEquals("Invalid response body", "encode data", response.getResponseBody().toString()); + Assert.assertEquals("Invalid response body", "encode data", response.getBody().toString()); } @Trace(dispatcher = true) diff --git a/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/utils/NettyUtils.java b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/utils/NettyUtils.java index 557dfed6e..c03aae308 100644 --- a/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/utils/NettyUtils.java +++ b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/utils/NettyUtils.java @@ -175,8 +175,8 @@ public static void processSecurityResponse(ChannelHandlerContext ctx, Object msg com.newrelic.api.agent.security.schema.HttpResponse securityResponse = securityMetaData.getResponse(); processResponseHeaders((HttpResponse) msg, securityResponse); - securityResponse.setResponseContentType(((FullHttpResponse) msg).headers().get(HttpHeaders.Names.CONTENT_TYPE)); - securityResponse.getResponseBody().append(((FullHttpResponse) msg).content().toString(StandardCharsets.UTF_8)); + securityResponse.setContentType(((FullHttpResponse) msg).headers().get(HttpHeaders.Names.CONTENT_TYPE)); + securityResponse.getBody().append(((FullHttpResponse) msg).content().toString(StandardCharsets.UTF_8)); } } catch (Throwable e) { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(ERROR_PARSING_HTTP_RESPONSE_DATA, NETTY_4_0_0, e.getMessage()), e, NettyUtils.class.getName()); @@ -188,8 +188,8 @@ public static void sendRXSSEvent(ChannelHandlerContext ctx, Object msg, String c if (!NewRelicSecurity.isHookProcessingActive() || !(msg instanceof FullHttpResponse) || NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()) { return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(((FullHttpResponse) msg).getStatus().code()); - ServletHelper.executeBeforeExitingTransaction(); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(((FullHttpResponse) msg).getStatus().code()); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java b/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java index d04b4b722..6f7fba89d 100644 --- a/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java +++ b/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java @@ -1,12 +1,9 @@ package com.nr.agent.security.instrumentation.netty400; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.newrelic.agent.security.introspec.InstrumentationTestConfig; import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; -import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.HttpRequest; import com.newrelic.api.agent.security.schema.HttpResponse; @@ -61,7 +58,7 @@ public void testChannelRXSS() throws IOException { HttpResponse response = introspector.getSecurityMetaData().getResponse(); Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); - Assert.assertEquals("Invalid response body", "write data", response.getResponseBody().toString()); + Assert.assertEquals("Invalid response body", "write data", response.getBody().toString()); } @Test public void testChannelRead() { @@ -94,7 +91,7 @@ public void testWrite() { HttpResponse response = introspector.getSecurityMetaData().getResponse(); Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); - Assert.assertEquals("Invalid response body", "write data", response.getResponseBody().toString()); + Assert.assertEquals("Invalid response body", "write data", response.getBody().toString()); } @Test @@ -112,7 +109,7 @@ public void testWriteAndFlush() { HttpResponse response = introspector.getSecurityMetaData().getResponse(); Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); - Assert.assertEquals("Invalid response body", "write flush data", response.getResponseBody().toString()); + Assert.assertEquals("Invalid response body", "write flush data", response.getBody().toString()); } @Test @@ -130,7 +127,7 @@ public void testWriteAndFlushPromise() { HttpResponse response = introspector.getSecurityMetaData().getResponse(); Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); - Assert.assertEquals("Invalid response body", "write flush promise data", response.getResponseBody().toString()); + Assert.assertEquals("Invalid response body", "write flush promise data", response.getBody().toString()); } @Test @@ -148,7 +145,7 @@ public void testEncode() { HttpResponse response = introspector.getSecurityMetaData().getResponse(); Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); - Assert.assertEquals("Invalid response body", "encode data", response.getResponseBody().toString()); + Assert.assertEquals("Invalid response body", "encode data", response.getBody().toString()); } @Trace(dispatcher = true) diff --git a/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java b/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java index fe7a9cd76..df05aa564 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java +++ b/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java @@ -7,8 +7,14 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; +import javax.servlet.ServletContext; +import javax.servlet.ServletRegistration; +import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Collection; import java.util.Enumeration; +import java.util.Iterator; import java.util.Map; public class HttpServletHelper { @@ -97,5 +103,14 @@ public static void releaseServletLock() { private static String getNrSecCustomAttribName() { return NR_SEC_CUSTOM_ATTRIB_NAME + Thread.currentThread().getId(); } - + public static Map getHttpResponseHeaders(HttpServletResponse httpServletResponse) { + Map headers = new java.util.HashMap<>(); + Collection headerNames = httpServletResponse.getHeaderNames(); + Iterator iterator = headerNames.iterator(); + while (iterator.hasNext()) { + String headerName = iterator.next(); + headers.put(headerName, httpServletResponse.getHeader(headerName)); + } + return headers; + } } diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/FilterChain_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/FilterChain_Instrumentation.java index b68541a09..c54ca6ff5 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/FilterChain_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/FilterChain_Instrumentation.java @@ -98,10 +98,11 @@ private void postProcessSecurityHook(ServletRequest request, ServletResponse res } if(NewRelic.getAgent().getTransaction().isWebTransaction() && response != null) { HttpServletResponse httpServletResponse = (HttpServletResponse) response; - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(httpServletResponse.getStatus()); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(httpServletResponse.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(HttpServletHelper.getHttpResponseHeaders(httpServletResponse)); } - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Filter_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Filter_Instrumentation.java index d25adede3..fbbd8fe4b 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Filter_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Filter_Instrumentation.java @@ -91,10 +91,11 @@ private void postProcessSecurityHook(ServletRequest request, ServletResponse res } if(NewRelic.getAgent().getTransaction().isWebTransaction() && response != null) { HttpServletResponse httpServletResponse = (HttpServletResponse) response; - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(httpServletResponse.getStatus()); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(httpServletResponse.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(HttpServletHelper.getHttpResponseHeaders(httpServletResponse)); } - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletOutputStream_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletOutputStream_Instrumentation.java index 1f620f058..91be89097 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletOutputStream_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletOutputStream_Instrumentation.java @@ -40,7 +40,7 @@ public void write(int b) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append((char) b); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append((char) b); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -62,7 +62,7 @@ public void print(String o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -84,7 +84,7 @@ public void print(boolean o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -105,7 +105,7 @@ public void print(char o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -126,7 +126,7 @@ public void print(int o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -147,7 +147,7 @@ public void print(long o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -168,7 +168,7 @@ public void print(float o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -189,7 +189,7 @@ public void print(double o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -210,7 +210,7 @@ public void println() throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -231,8 +231,8 @@ public void println(String o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -253,8 +253,8 @@ public void println(boolean o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -275,8 +275,8 @@ public void println(char o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -297,8 +297,8 @@ public void println(int o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -319,8 +319,8 @@ public void println(long o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -341,8 +341,8 @@ public void println(float o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -363,8 +363,8 @@ public void println(double o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletResponse_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletResponse_Instrumentation.java index f0a4c9407..71cb892d4 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletResponse_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletResponse_Instrumentation.java @@ -31,7 +31,7 @@ public ServletOutputStream_Instrumentation getOutputStream() throws IOException obj = Weaver.callOriginal(); if (isLockAcquired && obj != null) { ServletResponseCallback.registerOutputStreamHashIfNeeded(obj.hashCode()); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(getContentType()); } } finally { if(isLockAcquired) { @@ -50,7 +50,7 @@ public PrintWriter getWriter() throws IOException{ obj = Weaver.callOriginal(); if (isLockAcquired && obj != null) { ServletResponseCallback.registerWriterHashIfNeeded(obj.hashCode()); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(getContentType()); } } finally { if(isLockAcquired) { diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Servlet_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Servlet_Instrumentation.java index b02224d9c..063343fa4 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Servlet_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Servlet_Instrumentation.java @@ -103,9 +103,11 @@ private void postProcessSecurityHook(ServletRequest_Instrumentation request, Ser } if(NewRelic.getAgent().getTransaction().isWebTransaction()) { HttpServletResponse httpServletResponse = (HttpServletResponse) response; - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(httpServletResponse.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(httpServletResponse.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(HttpServletHelper.getHttpResponseHeaders(httpServletResponse)); } - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); @@ -125,4 +127,5 @@ private void postProcessSecurityHook(ServletRequest_Instrumentation request, Ser NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, HttpServletHelper.SERVLET_2_4, e.getMessage()), e, Servlet_Instrumentation.class.getName()); } } + } diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletOutputStreamTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletOutputStreamTest.java index ec8969eb0..5abafea8d 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletOutputStreamTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletOutputStreamTest.java @@ -51,7 +51,7 @@ public void testWrite() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Request Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong Response Content-type detected", "multipart/form-data", targetOperation.getResponse().getResponseContentType()); } @@ -74,7 +74,7 @@ public void testPrintString() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong request Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -97,7 +97,7 @@ public void testPrintBoolean() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - boolean resBody = Boolean.parseBoolean(String.valueOf(targetOperation.getResponse().getResponseBody())); + boolean resBody = Boolean.parseBoolean(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected", expected, resBody); } @@ -120,7 +120,7 @@ public void testPrintChar() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - char resBody = String.valueOf(targetOperation.getResponse().getResponseBody()).charAt(0); + char resBody = String.valueOf(targetOperation.getResponse().getBody()).charAt(0); Assert.assertEquals("Wrong response detected", expected, resBody); } @@ -144,7 +144,7 @@ public void testPrintInt() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - int resBody = Integer.parseInt(String.valueOf(targetOperation.getResponse().getResponseBody())); + int resBody = Integer.parseInt(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected", expected, resBody); } @@ -167,7 +167,7 @@ public void testPrintLong() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - long resBody = Long.parseLong(String.valueOf(targetOperation.getResponse().getResponseBody())); + long resBody = Long.parseLong(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected", expected, resBody); } @@ -190,7 +190,7 @@ public void testPrintFloat() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - float resBody = Float.parseFloat(String.valueOf(targetOperation.getResponse().getResponseBody())); + float resBody = Float.parseFloat(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected",expected, resBody, 0.0f); } @@ -213,7 +213,7 @@ public void testPrintDouble() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - double resBody = Double.parseDouble(String.valueOf(targetOperation.getResponse().getResponseBody())); + double resBody = Double.parseDouble(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected", expected, resBody, 0.0d); } @@ -235,7 +235,7 @@ public void testPrintln() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -265,7 +265,7 @@ public void testPrintlnString() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -287,7 +287,7 @@ public void testPrintlnBoolean() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -309,7 +309,7 @@ public void testPrintlnChar() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -331,7 +331,7 @@ public void testPrintlnInt() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -353,7 +353,7 @@ public void testPrintlnLong() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @Test @@ -374,7 +374,7 @@ public void testPrintlnFloat() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @Test @@ -395,7 +395,7 @@ public void testPrintlnDouble() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @Trace(dispatcher = true) private String write() throws URISyntaxException, IOException { diff --git a/instrumentation-security/servlet-5.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet5/HttpServletHelper.java b/instrumentation-security/servlet-5.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet5/HttpServletHelper.java index 6db1b6e07..66b89aea2 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet5/HttpServletHelper.java +++ b/instrumentation-security/servlet-5.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet5/HttpServletHelper.java @@ -1,7 +1,10 @@ package com.newrelic.agent.security.instrumentation.servlet5; import com.newrelic.api.agent.security.NewRelicSecurity; -import com.newrelic.api.agent.security.instrumentation.helpers.*; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.schema.HttpRequest; @@ -12,9 +15,11 @@ import jakarta.servlet.ServletContext; import jakarta.servlet.ServletRegistration; import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.util.Collection; import java.util.Enumeration; +import java.util.Iterator; import java.util.Map; public class HttpServletHelper { @@ -140,4 +145,15 @@ else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, SERVLET_5_0, e.getMessage()), e, HttpServletHelper.class.getName()); } } + + public static Map getHttpResponseHeaders(HttpServletResponse httpServletResponse) { + Map headers = new java.util.HashMap<>(); + Collection headerNames = httpServletResponse.getHeaderNames(); + Iterator iterator = headerNames.iterator(); + while (iterator.hasNext()) { + String headerName = iterator.next(); + headers.put(headerName, httpServletResponse.getHeader(headerName)); + } + return headers; + } } diff --git a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java index 4c5712fea..10c247bd5 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java +++ b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java @@ -91,10 +91,11 @@ private void postProcessSecurityHook(ServletRequest request, ServletResponse res } if(NewRelic.getAgent().getTransaction().isWebTransaction() && response != null) { HttpServletResponse httpServletResponse = (HttpServletResponse) response; - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(httpServletResponse.getStatus()); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(httpServletResponse.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(HttpServletHelper.getHttpResponseHeaders(httpServletResponse)); } - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java index 1869018ec..ad423c4ed 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java +++ b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java @@ -93,10 +93,11 @@ private void postProcessSecurityHook(ServletRequest request, ServletResponse res } if(NewRelic.getAgent().getTransaction().isWebTransaction() && response != null) { HttpServletResponse httpServletResponse = (HttpServletResponse) response; - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(httpServletResponse.getStatus()); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(httpServletResponse.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(HttpServletHelper.getHttpResponseHeaders(httpServletResponse)); } - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/ServletOutputStream_Instrumentation.java b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/ServletOutputStream_Instrumentation.java index 95b3eb23c..b3228c1a2 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/ServletOutputStream_Instrumentation.java +++ b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/ServletOutputStream_Instrumentation.java @@ -40,7 +40,7 @@ public void write(int b) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append((char) b); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append((char) b); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -62,7 +62,7 @@ public void print(String o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -84,7 +84,7 @@ public void print(boolean o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -105,7 +105,7 @@ public void print(char o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -126,7 +126,7 @@ public void print(int o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -147,7 +147,7 @@ public void print(long o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -168,7 +168,7 @@ public void print(float o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -189,7 +189,7 @@ public void print(double o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -210,7 +210,7 @@ public void println() throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -231,8 +231,8 @@ public void println(String o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -253,8 +253,8 @@ public void println(boolean o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -275,8 +275,8 @@ public void println(char o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -297,8 +297,8 @@ public void println(int o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -319,8 +319,8 @@ public void println(long o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -341,8 +341,8 @@ public void println(float o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -363,8 +363,8 @@ public void println(double o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } diff --git a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/ServletResponse_Instrumentation.java b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/ServletResponse_Instrumentation.java index c9092df70..7f648b4b1 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/ServletResponse_Instrumentation.java +++ b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/ServletResponse_Instrumentation.java @@ -30,7 +30,7 @@ public ServletOutputStream_Instrumentation getOutputStream() throws IOException obj = Weaver.callOriginal(); if (isLockAcquired && obj != null) { ServletResponseCallback.registerOutputStreamHashIfNeeded(obj.hashCode()); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(getContentType()); } } finally { if(isLockAcquired) { @@ -49,7 +49,7 @@ public PrintWriter getWriter() throws IOException{ obj = Weaver.callOriginal(); if (isLockAcquired && obj != null) { ServletResponseCallback.registerWriterHashIfNeeded(obj.hashCode()); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(getContentType()); } } finally { if(isLockAcquired) { diff --git a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java index b4a82c2cb..c52a4c93e 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java +++ b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java @@ -98,9 +98,11 @@ private void postProcessSecurityHook(ServletRequest_Instrumentation request, Ser } if(NewRelic.getAgent().getTransaction().isWebTransaction()) { HttpServletResponse httpServletResponse = (HttpServletResponse) response; - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(httpServletResponse.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(httpServletResponse.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(HttpServletHelper.getHttpResponseHeaders(httpServletResponse)); } - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletOutputStreamTest.java b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletOutputStreamTest.java index 7b9070168..b3d2c3686 100644 --- a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletOutputStreamTest.java +++ b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletOutputStreamTest.java @@ -51,7 +51,7 @@ public void testWrite() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Request Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong Response Content-type detected", "multipart/form-data", targetOperation.getResponse().getResponseContentType()); } @@ -74,7 +74,7 @@ public void testPrintString() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong request Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -97,7 +97,7 @@ public void testPrintBoolean() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - boolean resBody = Boolean.parseBoolean(String.valueOf(targetOperation.getResponse().getResponseBody())); + boolean resBody = Boolean.parseBoolean(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected", expected, resBody); } @@ -120,7 +120,7 @@ public void testPrintChar() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - char resBody = String.valueOf(targetOperation.getResponse().getResponseBody()).charAt(0); + char resBody = String.valueOf(targetOperation.getResponse().getBody()).charAt(0); Assert.assertEquals("Wrong response detected", expected, resBody); } @@ -144,7 +144,7 @@ public void testPrintInt() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - int resBody = Integer.parseInt(String.valueOf(targetOperation.getResponse().getResponseBody())); + int resBody = Integer.parseInt(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected", expected, resBody); } @@ -167,7 +167,7 @@ public void testPrintLong() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - long resBody = Long.parseLong(String.valueOf(targetOperation.getResponse().getResponseBody())); + long resBody = Long.parseLong(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected", expected, resBody); } @@ -190,7 +190,7 @@ public void testPrintFloat() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - float resBody = Float.parseFloat(String.valueOf(targetOperation.getResponse().getResponseBody())); + float resBody = Float.parseFloat(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected",expected, resBody, 0.0f); } @@ -213,7 +213,7 @@ public void testPrintDouble() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - double resBody = Double.parseDouble(String.valueOf(targetOperation.getResponse().getResponseBody())); + double resBody = Double.parseDouble(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected", expected, resBody, 0.0d); } @@ -235,7 +235,7 @@ public void testPrintln() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -257,7 +257,7 @@ public void testPrintlnString() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -279,7 +279,7 @@ public void testPrintlnBoolean() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -301,7 +301,7 @@ public void testPrintlnChar() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -323,7 +323,7 @@ public void testPrintlnInt() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -345,7 +345,7 @@ public void testPrintlnLong() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @Test @@ -366,7 +366,7 @@ public void testPrintlnFloat() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @Test @@ -387,7 +387,7 @@ public void testPrintlnDouble() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @Trace(dispatcher = true) private String write() throws URISyntaxException, IOException { diff --git a/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java b/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java index 43f823c78..a7ea5e7ae 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java +++ b/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java @@ -12,6 +12,7 @@ import jakarta.servlet.ServletContext; import jakarta.servlet.ServletRegistration; import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.util.Collection; import java.util.Enumeration; @@ -141,4 +142,15 @@ else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, SERVLET_6_0, e.getMessage()), e, HttpServletHelper.class.getName()); } } + + public static Map getHttpResponseHeaders(HttpServletResponse httpServletResponse) { + Map headers = new java.util.HashMap<>(); + Collection headerNames = httpServletResponse.getHeaderNames(); + Iterator iterator = headerNames.iterator(); + while (iterator.hasNext()) { + String headerName = iterator.next(); + headers.put(headerName, httpServletResponse.getHeader(headerName)); + } + return headers; + } } diff --git a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java index a73bf35de..4f7f66c6e 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java +++ b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java @@ -93,10 +93,11 @@ private void postProcessSecurityHook(ServletRequest request, ServletResponse res } if(NewRelic.getAgent().getTransaction().isWebTransaction() && response != null) { HttpServletResponse httpServletResponse = (HttpServletResponse) response; - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(httpServletResponse.getStatus()); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(httpServletResponse.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(HttpServletHelper.getHttpResponseHeaders(httpServletResponse)); } - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java index 0e801334d..291aa89ea 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java +++ b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java @@ -95,10 +95,10 @@ private void postProcessSecurityHook(ServletRequest request, ServletResponse res } if(NewRelic.getAgent().getTransaction().isWebTransaction() && response != null) { HttpServletResponse httpServletResponse = (HttpServletResponse) response; - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(httpServletResponse.getStatus()); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(httpServletResponse.getContentType()); - } - ServletHelper.executeBeforeExitingTransaction(); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(httpServletResponse.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(HttpServletHelper.getHttpResponseHeaders(httpServletResponse)); } +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/ServletOutputStream_Instrumentation.java b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/ServletOutputStream_Instrumentation.java index c9cedbb76..5160952ad 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/ServletOutputStream_Instrumentation.java +++ b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/ServletOutputStream_Instrumentation.java @@ -40,7 +40,7 @@ public void write(int b) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append((char) b); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append((char) b); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -62,7 +62,7 @@ public void print(String o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -84,7 +84,7 @@ public void print(boolean o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -105,7 +105,7 @@ public void print(char o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -126,7 +126,7 @@ public void print(int o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -147,7 +147,7 @@ public void print(long o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -168,7 +168,7 @@ public void print(float o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -189,7 +189,7 @@ public void print(double o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -210,7 +210,7 @@ public void println() throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -231,8 +231,8 @@ public void println(String o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -253,8 +253,8 @@ public void println(boolean o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -275,8 +275,8 @@ public void println(char o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -297,8 +297,8 @@ public void println(int o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -319,8 +319,8 @@ public void println(long o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -341,8 +341,8 @@ public void println(float o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } @@ -363,8 +363,8 @@ public void println(double o) throws IOException { // Preprocess Phase if(isLockAcquired){ try { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(o); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(ServletResponseCallback.LF); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(o); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(ServletResponseCallback.LF); } catch (Throwable ignored) { // ignored.printStackTrace(System.out); } diff --git a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/ServletResponse_Instrumentation.java b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/ServletResponse_Instrumentation.java index f1d3adf6d..6b6e30080 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/ServletResponse_Instrumentation.java +++ b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/ServletResponse_Instrumentation.java @@ -31,7 +31,7 @@ public ServletOutputStream_Instrumentation getOutputStream() throws IOException obj = Weaver.callOriginal(); if (isLockAcquired && obj != null) { ServletResponseCallback.registerOutputStreamHashIfNeeded(obj.hashCode()); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(getContentType()); } } finally { if(isLockAcquired) { @@ -50,7 +50,7 @@ public PrintWriter getWriter() throws IOException{ obj = Weaver.callOriginal(); if (isLockAcquired && obj != null) { ServletResponseCallback.registerWriterHashIfNeeded(obj.hashCode()); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(getContentType()); } } finally { if(isLockAcquired) { diff --git a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java index eac50ff96..49b4535ff 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java +++ b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java @@ -98,9 +98,11 @@ private void postProcessSecurityHook(ServletRequest_Instrumentation request, Ser } if(NewRelic.getAgent().getTransaction().isWebTransaction()) { HttpServletResponse httpServletResponse = (HttpServletResponse) response; - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(httpServletResponse.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(httpServletResponse.getStatus()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(httpServletResponse.getContentType()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setHeaders(HttpServletHelper.getHttpResponseHeaders(httpServletResponse)); } - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletOutputStreamTest.java b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletOutputStreamTest.java index d417c55b3..a01274247 100644 --- a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletOutputStreamTest.java +++ b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletOutputStreamTest.java @@ -50,7 +50,7 @@ public void testWrite() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Request Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong Response Content-type detected", "multipart/form-data", targetOperation.getResponse().getResponseContentType()); } @@ -73,7 +73,7 @@ public void testPrintString() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong request Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -96,7 +96,7 @@ public void testPrintBoolean() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - boolean resBody = Boolean.parseBoolean(String.valueOf(targetOperation.getResponse().getResponseBody())); + boolean resBody = Boolean.parseBoolean(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected", expected, resBody); } @@ -119,7 +119,7 @@ public void testPrintChar() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - char resBody = String.valueOf(targetOperation.getResponse().getResponseBody()).charAt(0); + char resBody = String.valueOf(targetOperation.getResponse().getBody()).charAt(0); Assert.assertEquals("Wrong response detected", expected, resBody); } @@ -143,7 +143,7 @@ public void testPrintInt() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - int resBody = Integer.parseInt(String.valueOf(targetOperation.getResponse().getResponseBody())); + int resBody = Integer.parseInt(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected", expected, resBody); } @@ -166,7 +166,7 @@ public void testPrintLong() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - long resBody = Long.parseLong(String.valueOf(targetOperation.getResponse().getResponseBody())); + long resBody = Long.parseLong(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected", expected, resBody); } @@ -189,7 +189,7 @@ public void testPrintFloat() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - float resBody = Float.parseFloat(String.valueOf(targetOperation.getResponse().getResponseBody())); + float resBody = Float.parseFloat(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected",expected, resBody, 0.0f); } @@ -212,7 +212,7 @@ public void testPrintDouble() throws URISyntaxException, IOException { Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - double resBody = Double.parseDouble(String.valueOf(targetOperation.getResponse().getResponseBody())); + double resBody = Double.parseDouble(String.valueOf(targetOperation.getResponse().getBody())); Assert.assertEquals("Wrong response detected", expected, resBody, 0.0d); } @@ -234,7 +234,7 @@ public void testPrintln() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -256,7 +256,7 @@ public void testPrintlnString() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -278,7 +278,7 @@ public void testPrintlnBoolean() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -300,7 +300,7 @@ public void testPrintlnChar() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -322,7 +322,7 @@ public void testPrintlnInt() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @@ -344,7 +344,7 @@ public void testPrintlnLong() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @Test @@ -365,7 +365,7 @@ public void testPrintlnFloat() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @Test @@ -386,7 +386,7 @@ public void testPrintlnDouble() throws URISyntaxException, IOException { Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "application/x-www-form-urlencoded", targetOperation.getRequest().getContentType()); - Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getResponseBody())); + Assert.assertEquals("Wrong response detected", expected, String.valueOf(targetOperation.getResponse().getBody())); } @Trace(dispatcher = true) private String write() throws URISyntaxException, IOException { diff --git a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java index 96857735f..d2f1d8504 100644 --- a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java +++ b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java @@ -123,9 +123,9 @@ public static void postProcessSecurityHook(HttpResponse httpResponse, String cla if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()) { return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(httpResponse.status().intValue()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(httpResponse.status().intValue()); - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); @@ -145,4 +145,14 @@ public static void postProcessSecurityHook(HttpResponse httpResponse, String cla NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SPRAY_CAN_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); } } + + public static void processResponseHeaders(List headers, com.newrelic.api.agent.security.schema.HttpResponse response) { + Iterator headerIterator = headers.iterator(); + while (headerIterator.hasNext()) { + HttpHeader element = headerIterator.next(); + String headerKey = element.name(); + String headerValue = element.value(); + response.getHeaders().put(headerKey, headerValue); + } + } } diff --git a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/rendering/ResponseRendering_Instrumentation.java b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/rendering/ResponseRendering_Instrumentation.java index b6f2dfda2..3f24c3dfa 100644 --- a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/rendering/ResponseRendering_Instrumentation.java +++ b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/rendering/ResponseRendering_Instrumentation.java @@ -22,10 +22,11 @@ public class ResponseRendering_Instrumentation { boolean isLockAcquired = GenericHelper.acquireLockIfPossible(SprayHttpUtils.getNrSecCustomAttribNameForResponse()); try { if (isLockAcquired && response.entity().nonEmpty()) { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(new StringBuilder(response.entity().data().asString(StandardCharsets.UTF_8))); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setBody(new StringBuilder(response.entity().data().asString(StandardCharsets.UTF_8))); if (response.entity() instanceof HttpEntity.NonEmpty) { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(((HttpEntity.NonEmpty) response.entity()).contentType().value()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(((HttpEntity.NonEmpty) response.entity()).contentType().value()); } + SprayHttpUtils.processResponseHeaders(response.headers(), NewRelicSecurity.getAgent().getSecurityMetaData().getResponse()); SprayHttpUtils.postProcessSecurityHook(response, ResponseRendering_Instrumentation.class.getName(), "renderResponse$1"); } } catch (Exception e){ diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java index 0ee3063f8..cce5b4dd4 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java @@ -123,8 +123,8 @@ public static void postProcessSecurityHook(HttpResponse httpResponse, String cla if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()) { return; } - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(httpResponse.status().intValue()); - ServletHelper.executeBeforeExitingTransaction(); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setStatusCode(httpResponse.status().intValue()); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); @@ -144,4 +144,14 @@ public static void postProcessSecurityHook(HttpResponse httpResponse, String cla NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); } } + + public static void processResponseHeaders(List headers, com.newrelic.api.agent.security.schema.HttpResponse response) { + Iterator headerIterator = headers.iterator(); + while (headerIterator.hasNext()) { + HttpHeader element = headerIterator.next(); + String headerKey = element.name(); + String headerValue = element.value(); + response.getHeaders().put(headerKey, headerValue); + } + } } diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java index 715989c4f..3e2f2dd39 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java @@ -29,10 +29,11 @@ public void marshalTo(HttpResponse httpResponse) { boolean isLockAcquired = GenericHelper.acquireLockIfPossible(SprayHttpUtils.getNrSecCustomAttribNameForResponse()); try { if (isLockAcquired && httpResponse.entity().nonEmpty()) { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(new StringBuilder(httpResponse.entity().data().asString(StandardCharsets.UTF_8))); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setBody(new StringBuilder(httpResponse.entity().data().asString(StandardCharsets.UTF_8))); if (httpResponse.entity() instanceof HttpEntity.NonEmpty) { - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(((HttpEntity.NonEmpty) httpResponse.entity()).contentType().value()); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(((HttpEntity.NonEmpty) httpResponse.entity()).contentType().value()); } + SprayHttpUtils.processResponseHeaders(httpResponse.headers(), NewRelicSecurity.getAgent().getSecurityMetaData().getResponse()); SprayHttpUtils.postProcessSecurityHook(httpResponse, this.getClass().getName(), "marshalTo"); } } catch (Exception e){ diff --git a/instrumentation-security/spray-http-1.3.1/src/test/java/com/nr/agent/security/instrumentation/spray/http/SprayTest.java b/instrumentation-security/spray-http-1.3.1/src/test/java/com/nr/agent/security/instrumentation/spray/http/SprayTest.java index a96b77eda..b301b95b7 100644 --- a/instrumentation-security/spray-http-1.3.1/src/test/java/com/nr/agent/security/instrumentation/spray/http/SprayTest.java +++ b/instrumentation-security/spray-http-1.3.1/src/test/java/com/nr/agent/security/instrumentation/spray/http/SprayTest.java @@ -49,7 +49,7 @@ public void testGet() throws IOException { Assert.assertEquals("Wrong Content-type detected", StringUtils.EMPTY, operation.getRequest().getContentType()); Assert.assertNotNull("Empty response detected", operation.getResponse()); - Assert.assertEquals("Wrong port detected", "testing API", operation.getResponse().getResponseBody().toString()); + Assert.assertEquals("Wrong port detected", "testing API", operation.getResponse().getBody().toString()); Assert.assertEquals("Wrong Content-type detected", "text/plain", operation.getResponse().getResponseContentType()); } @@ -73,7 +73,7 @@ public void testPost() throws IOException { Assert.assertEquals("Wrong Content-type detected", "data", operation.getRequest().getBody().toString()); Assert.assertNotNull("Empty response detected", operation.getResponse()); - Assert.assertEquals("Wrong port detected", "testing API", operation.getResponse().getResponseBody().toString()); + Assert.assertEquals("Wrong port detected", "testing API", operation.getResponse().getBody().toString()); Assert.assertEquals("Wrong Content-type detected", "text/plain", operation.getResponse().getResponseContentType()); } @@ -98,7 +98,7 @@ public void testWithCSECHeader() throws IOException { Assert.assertEquals("Wrong Content-type detected", StringUtils.EMPTY, operation.getRequest().getContentType()); Assert.assertNotNull("Empty response detected", operation.getResponse()); - Assert.assertEquals("Wrong port detected", "testing API", operation.getResponse().getResponseBody().toString()); + Assert.assertEquals("Wrong port detected", "testing API", operation.getResponse().getBody().toString()); Assert.assertEquals("Wrong Content-type detected", "text/plain", operation.getResponse().getResponseContentType()); Map headers = operation.getRequest().getHeaders(); diff --git a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/Filter_Instrumentation.java b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/Filter_Instrumentation.java index ddd7cf2ff..8aac2bc31 100644 --- a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/Filter_Instrumentation.java +++ b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/Filter_Instrumentation.java @@ -59,13 +59,17 @@ private void preprocessSecurityHook(HttpExchange exchange) { securityRequest.setProtocol(HttpServerHelper.getProtocol(exchange)); securityRequest.setUrl(String.valueOf(exchange.getRequestURI())); + String queryString = exchange.getRequestURI().getQuery(); + if (queryString != null && !queryString.trim().isEmpty()) { + securityRequest.setUrl(securityRequest.getUrl() + HttpServerHelper.QUESTION_MARK + queryString); + } + securityRequest.setContentType(HttpServerHelper.getContentType(securityRequest.getHeaders())); securityRequest.setRequestParsed(true); } catch (Throwable e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, HttpServerHelper.SUN_NET_HTTPSERVER, e.getMessage()), e, this.getClass().getName()); } } - private void postProcessSecurityHook(HttpExchange exchange) { try { if(!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ @@ -73,11 +77,11 @@ private void postProcessSecurityHook(HttpExchange exchange) { } HttpResponse securityResponse = NewRelicSecurity.getAgent().getSecurityMetaData().getResponse(); - securityResponse.setResponseCode(exchange.getResponseCode()); - HttpServerHelper.processHttpResponseHeaders(exchange.getResponseHeaders(), securityResponse); - securityResponse.setResponseContentType(HttpServerHelper.getContentType(securityResponse.getHeaders())); + securityResponse.setStatusCode(exchange.getResponseCode()); + securityResponse.setHeaders(HttpServerHelper.getHttpResponseHeaders(exchange.getResponseHeaders())); + securityResponse.setContentType(HttpServerHelper.getContentType(securityResponse.getHeaders())); - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpHandler_Instrumentation.java b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpHandler_Instrumentation.java index dcd72eb40..43f3bb0bd 100644 --- a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpHandler_Instrumentation.java +++ b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpHandler_Instrumentation.java @@ -60,6 +60,11 @@ private void preprocessSecurityHook(HttpExchange exchange) { securityRequest.setProtocol(HttpServerHelper.getProtocol(exchange)); securityRequest.setUrl(String.valueOf(exchange.getRequestURI())); + String queryString = exchange.getRequestURI().getQuery(); + if (queryString != null && !queryString.trim().isEmpty()) { + securityRequest.setUrl(securityRequest.getUrl() + HttpServerHelper.QUESTION_MARK + queryString); + } + securityRequest.setContentType(HttpServerHelper.getContentType(securityRequest.getHeaders())); securityRequest.setRequestParsed(true); } catch (Throwable e){ @@ -72,11 +77,11 @@ private void postProcessSecurityHook(HttpExchange exchange) { return; } HttpResponse securityResponse = NewRelicSecurity.getAgent().getSecurityMetaData().getResponse(); - securityResponse.setResponseCode(exchange.getResponseCode()); + securityResponse.setStatusCode(exchange.getResponseCode()); HttpServerHelper.processHttpResponseHeaders(exchange.getResponseHeaders(), securityResponse); - securityResponse.setResponseContentType(HttpServerHelper.getContentType(securityResponse.getHeaders())); + securityResponse.setContentType(HttpServerHelper.getContentType(securityResponse.getHeaders())); - ServletHelper.executeBeforeExitingTransaction(); +// ServletHelper.executeBeforeExitingTransaction(); //Add request URI hash to low severity event filter LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); diff --git a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java index f5522e1f9..9ecd18d54 100644 --- a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java +++ b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java @@ -10,11 +10,10 @@ import com.newrelic.api.agent.security.schema.HttpResponse; import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; +import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; public class HttpServerHelper { public static final String SUN_NET_HTTPSERVER = "SUN NET HTTPSERVER"; @@ -155,6 +154,20 @@ public static String getProtocol(HttpExchange exchange){ return HTTP_PROTOCOL; } + public static Map getHttpResponseHeaders(Headers responseHeaders) { + Map headers = new HashMap<>(); + if(responseHeaders == null || responseHeaders.isEmpty()){ + return headers; + } + for (Map.Entry> headerElement : responseHeaders.entrySet()) { + headers.put(headerElement.getKey(), String.join(";", headerElement.getValue())); + if(StringUtils.equalsAny(StringUtils.lowerCase(headerElement.getKey()), "content-type", "contenttype")){ + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setContentType(responseHeaders.getFirst(headerElement.getKey())); + } + } + return headers; + } + public static void processHttpResponseHeaders(Headers headers, HttpResponse securityRequest){ for (String headerKey : headers.keySet()) { String headerFullValue = EMPTY; diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java index 8c3258d10..547d3627e 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java @@ -193,6 +193,11 @@ private void readSkipScan() throws RestrictionModeException { agentMode.getSkipScan().getIastDetectionCategory().setXpathInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_XPATH_INJECTION, false)); agentMode.getSkipScan().getIastDetectionCategory().setSsrfEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SSRF, false)); agentMode.getSkipScan().getIastDetectionCategory().setRxssEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_RXSS, false)); + agentMode.getSkipScan().getIastDetectionCategory().setUnsafeDeserializationEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_UNSAFE_DESERIALIZATION, false)); + agentMode.getSkipScan().getIastDetectionCategory().setInsecureReflectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_UNSAFE_REFLECTION, false)); + if(!agentMode.getSkipScan().getIastDetectionCategory().getRxssEnabled() && !NewRelic.getAgent().getConfig().getValue(REPORT_HTTP_RESPONSE_BODY, true)) { + agentMode.getSkipScan().getIastDetectionCategory().setRxssEnabled(true); + } agentMode.getSkipScan().getIastDetectionCategory().generateDisabledCategoriesCSV(); } catch (ClassCastException | NumberFormatException e){ throw new RestrictionModeException(INVALID_SECURITY_CONFIGURATION + e.getMessage(), e); @@ -313,7 +318,7 @@ private String applyRequiredLogLevel() { if(value instanceof Boolean) { logLevel = IUtilConstants.OFF; } else { - logLevel = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_LOG_LEVEL, IUtilConstants.INFO); + logLevel = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_LOG_LEVEL, LogLevel.FINEST.name()); } try { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java index 1dc26ef1e..c3efba7a3 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java @@ -1,6 +1,9 @@ package com.newrelic.agent.security.instrumentator.dispatcher; +import com.fasterxml.jackson.core.JsonProcessingException; import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import com.newrelic.agent.security.AgentConfig; import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.helper.DynamoDBRequestConverter; @@ -34,6 +37,12 @@ import java.io.File; import java.io.ObjectInputStream; +import java.io.ObjectStreamClass; +import java.io.ObjectStreamField; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicBoolean; @@ -69,6 +78,8 @@ public class Dispatcher implements Callable { public static final String COOKIE_IS_SECURE = "isSecure"; public static final String COOKIE_IS_HTTP_ONLY = "isHttpOnly"; public static final String COOKIE_IS_SAME_SITE_STRICT = "isSameSiteStrict"; + private static final int MAX_DEPTH = 3; + public static final String CLASS_EXTENSION = ".class"; private ExitEventBean exitEventBean; private AbstractOperation operation; private SecurityMetaData securityMetaData; @@ -236,21 +247,28 @@ public Object call() throws Exception { SolrDbOperation solrDbOperation = (SolrDbOperation) operation; eventBean = prepareSolrDbRequestEvent(eventBean, solrDbOperation); break; + case UNSAFE_DESERIALIZATION: + prepareDeserializationEvent(eventBean, (DeserializationOperation) operation); + break; + case REFLECTION: + JavaReflectionOperation javaReflectionOperationalBean = (JavaReflectionOperation) operation; + eventBean = prepareReflectionEvent(eventBean, javaReflectionOperationalBean); + break; default: } - if (!VulnerabilityCaseType.FILE_INTEGRITY.equals(operation.getCaseType())) { - if (VulnerabilityCaseType.FILE_OPERATION.equals(operation.getCaseType()) - && ((FileOperation) operation).isGetBooleanAttributesCall()) { - eventBean = processStackTrace(eventBean, operation.getCaseType(), false); - } else { - eventBean = processStackTrace(eventBean, operation.getCaseType(), true); - } - if (eventBean == null) { - return null; - } - } +// if (!VulnerabilityCaseType.FILE_INTEGRITY.equals(operation.getCaseType())) { +// if (VulnerabilityCaseType.FILE_OPERATION.equals(operation.getCaseType()) +// && ((FileOperation) operation).isGetBooleanAttributesCall()) { +// eventBean = processStackTrace(eventBean, operation.getCaseType(), false); +// } else { +// eventBean = processStackTrace(eventBean, operation.getCaseType(), true); +// } +// if (eventBean == null) { +// return null; +// } +// } EventSendPool.getInstance().sendEvent(eventBean); if (!firstEventSent.get()) { @@ -267,6 +285,28 @@ public Object call() throws Exception { return null; } + private JavaAgentEventBean prepareReflectionEvent(JavaAgentEventBean eventBean, JavaReflectionOperation javaReflectionOperationalBean) { + JSONArray params = new JSONArray(); + JSONObject javaReflection = new JSONObject(); + javaReflection.put("declaringClass", javaReflectionOperationalBean.getDeclaringClass()); + javaReflection.put("method", javaReflectionOperationalBean.getNameOfMethod()); + javaReflection.put("declaredMethods", javaReflectionOperationalBean.getDeclaredMethods()); + try { + JSONArray arguments = new JSONArray(); + for (Object arg : javaReflectionOperationalBean.getArgs()) { + arguments.add(JsonConverter.getObjectMapper().writeValueAsString(arg)); + } + javaReflection.put("args", arguments); + } catch (Exception ignored) {} + try { + javaReflection.put("obj", JsonConverter.getObjectMapper().writeValueAsString(javaReflectionOperationalBean.getObj())); + } catch (JsonProcessingException ignored) { + } + params.add(javaReflection); + eventBean.setParameters(params); + return eventBean; + } + private boolean isReplayEndpointConfirmed() { Map applicationConnectionConfig = NewRelicSecurity.getAgent().getApplicationConnectionConfig(); for (Map.Entry connectionConfig : applicationConnectionConfig.entrySet()) { @@ -336,14 +376,30 @@ public boolean isPrimitiveType(Class clazz) { private JavaAgentEventBean processFileOperationEvent(JavaAgentEventBean eventBean, FileOperation fileOperationalBean) { prepareFileEvent(eventBean, fileOperationalBean); String URL = StringUtils.substringBefore(securityMetaData.getRequest().getUrl(), QUESTION_CHAR); + if(eventBean.getMetaData().isTriggerViaDeserialisation() && isClassLoadingOperation(fileOperationalBean.getFileName())) { + //Class loading event while deserialization, drop it. + logger.log(LogLevel.FINEST, String.format("Class loading event while deserialization, drop it : %s", fileOperationalBean.getFileName()), this.getClass().getName()); + return null; + } + if (!(AgentUtils.getInstance().getAgentPolicy().getVulnerabilityScan().getEnabled() && AgentUtils.getInstance().getAgentPolicy().getVulnerabilityScan().getIastScan().getEnabled()) && allowedExtensionFileIO(eventBean.getParameters(), eventBean.getSourceMethod(), URL)) { // Event is bypassed. Drop it. + logger.log(LogLevel.FINEST, String.format("File Event is bypassed. Drop it : %s", operation), this.getClass().getName()); return null; } return eventBean; } + private boolean isClassLoadingOperation(List fileName) { + for (String file : fileName) { + if (file.endsWith(CLASS_EXTENSION)) { + return true; + } + } + return false; + } + /** * Validate and send if required event for REFLECTED XSS @@ -354,12 +410,12 @@ private void processReflectedXSSEvent(JavaAgentEventBean eventBean) { return; } Set xssConstructs = CallbackUtils.checkForReflectedXSS(securityMetaData.getRequest(), securityMetaData.getResponse()); - if ((!xssConstructs.isEmpty() && !actuallyEmpty(xssConstructs) && StringUtils.isNotBlank(securityMetaData.getResponse().getResponseBody())) || + if ((!xssConstructs.isEmpty() && !actuallyEmpty(xssConstructs) && StringUtils.isNotBlank(securityMetaData.getResponse().getBody())) || (AgentUtils.getInstance().getAgentPolicy().getVulnerabilityScan().getEnabled() && AgentUtils.getInstance().getAgentPolicy().getVulnerabilityScan().getIastScan().getEnabled())) { JSONArray params = new JSONArray(); params.addAll(xssConstructs); - params.add(securityMetaData.getResponse().getResponseBody()); + params.add(securityMetaData.getResponse().getBody()); eventBean.setParameters(params); eventBean.setHttpResponse(securityMetaData.getResponse()); eventBean.setApplicationUUID(AgentInfo.getInstance().getApplicationUUID()); @@ -658,87 +714,164 @@ private static JavaAgentEventBean prepareSSRFEvent(JavaAgentEventBean eventBean, return eventBean; } - private boolean allowedExtensionFileIO(JSONArray params, String sourceString, String url) { - if (JAVA_IO_FILE_INPUTSTREAM_OPEN.equals(sourceString)) { - for (int i = 0; i < params.size(); i++) { - String filePath = params.get(i).toString(); + private static JavaAgentEventBean prepareDeserializationEvent(JavaAgentEventBean eventBean, + DeserializationOperation deserializationOperation) throws JsonProcessingException { + DeserializationInfo rootDeserializationInfo = deserializationOperation.getRootDeserializationInfo(); + JSONArray params = new JSONArray(); + JSONObject deserializationInfo = new JSONObject(); + if(rootDeserializationInfo != null) { + deserializationInfo.put("type", rootDeserializationInfo.getType()); + try { + deserializationInfo.put("value", JsonConverter.getObjectMapper().writeValueAsString(rootDeserializationInfo.getInstance())); + } catch (Exception ignored) { + logger.log(LogLevel.FINEST, String.format("Unable to stringify the Object %s", rootDeserializationInfo.getInstance()), Dispatcher.class.getName()); + } + } + Set fieldTypes = new HashSet<>(); + fieldTypes.addAll(deserializationOperation.getDeserializationInvocation().getEncounteredSerializable().keySet()); + gatherClassDefinitions(deserializationOperation.getDeserializationInvocation().getEncounteredSerializable(), fieldTypes); + deserializationInfo.put("classInfo", deserializationOperation.getDeserializationInvocation().getEncounteredSerializable()); + params.add(deserializationInfo); + eventBean.setParameters(params); + return eventBean; + } - if (StringUtils.containsIgnoreCase(filePath, File.separator)) { - filePath = StringUtils.substringAfterLast(filePath, File.separator); + private static void gatherClassDefinitions(Map encounteredSerializable, Set fieldTypes) { + for (Serializable serializable : encounteredSerializable.values()) { + if(serializable.getDeserializable()) { + ObjectStreamClass osc = ObjectStreamClass.lookup(serializable.getKlass()); + if(osc != null) { + serializable.setClassDefinition(getClassDefinition(osc, serializable.getKlass(), fieldTypes)); } + } + } + } + + private static SerializableClassDefinition getClassDefinition(ObjectStreamClass desc, Class classType, Set fieldTypes) { + List filedDefinitions = new ArrayList<>(); + for (ObjectStreamField field : desc.getFields()) { + String name = field.getName(); + String type = field.getType().getName(); + boolean isPrimitive = field.isPrimitive(); + boolean isTransient = false; + List actualTypeArguments = null; + boolean containsClassOrObject = false; + try { + Field genericField = classType.getDeclaredField(name); + Type genericType = genericField.getGenericType(); + if(genericType instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) genericType; + Type[] typeArguments = parameterizedType.getActualTypeArguments(); + actualTypeArguments = new ArrayList<>(); + for(Type typeArgument : typeArguments) { + actualTypeArguments.add(typeArgument.getTypeName()); + } + + containsClassOrObject = Arrays.stream(typeArguments) + .anyMatch(arg -> arg.getTypeName().equals(Class.class.getName()) || arg.getTypeName().equals(Object.class.getName())); - if (StringUtils.containsIgnoreCase(url, File.separator)) { - url = StringUtils.substringAfterLast(url, File.separator); } - if (StringUtils.equals(url, filePath)) - return true; + Class fieldType = genericField.getType(); + + do { + if (fieldType.isArray()) { + Class componentType = fieldType.getComponentType(); + if (componentType.getName().equals(Class.class.getName()) || componentType.getName().equals(Object.class.getName())) { + containsClassOrObject = true; + } + } + fieldType = fieldType.getComponentType(); + } while (fieldType != null && fieldType.isArray()); + + + isTransient = Modifier.isTransient(genericField.getModifiers()); + } catch (NoSuchFieldException ignored) { + } + boolean isSerializable = true; + FiledDefinition filedDefinition = new FiledDefinition(name, type, isPrimitive, isTransient, isSerializable); + filedDefinition.setParameterizedType(actualTypeArguments); + if(!isPrimitive && !fieldTypes.contains(type)) { + fieldTypes.add(type); + ObjectStreamClass osc = ObjectStreamClass.lookup(field.getType()); + if(osc != null) { + filedDefinition.setClassDefinition(getClassDefinition(osc, field.getType(), fieldTypes)); + } + } + + + if (containsClassOrObject || type.equals(Class.class.getName()) || type.equals(Object.class.getName()) + || (filedDefinition.getClassDefinition() != null && !filedDefinition.getClassDefinition().getFields().isEmpty())) { + filedDefinitions.add(filedDefinition); } } - return false; + SerializableClassDefinition serializableClassDefinition = new SerializableClassDefinition(desc.getName(), classType.isInterface(), filedDefinitions); +// serializableClassDefinition.addAllSuperClasses(getAllInterfaces(classType)); +// serializableClassDefinition.addAllSuperClasses(getAllSuperClasses(classType)); + return serializableClassDefinition; } - private JavaAgentEventBean processStackTrace(JavaAgentEventBean eventBean, - VulnerabilityCaseType vulnerabilityCaseType, boolean deserialisationCheck) { - - String klassName = null; - for (int i = 0; i < operation.getStackTrace().length; i++) { - // TODO : check this sequence. Why this is being set from inside Deserialisation check. - - klassName = operation.getStackTrace()[i].getClassName(); - if (VulnerabilityCaseType.SYSTEM_COMMAND.equals(vulnerabilityCaseType) - || VulnerabilityCaseType.SQL_DB_COMMAND.equals(vulnerabilityCaseType) - || VulnerabilityCaseType.FILE_INTEGRITY.equals(vulnerabilityCaseType) - || VulnerabilityCaseType.NOSQL_DB_COMMAND.equals(vulnerabilityCaseType) - || VulnerabilityCaseType.FILE_OPERATION.equals(vulnerabilityCaseType) - || VulnerabilityCaseType.HTTP_REQUEST.equals(vulnerabilityCaseType) - || VulnerabilityCaseType.SYSTEM_EXIT.equals(vulnerabilityCaseType)) { - xxeTriggerCheck(i, eventBean, klassName); - if (deserialisationCheck) { - deserializationTriggerCheck(i, eventBean, klassName); - } + public static Set getAllInterfaces(Class clazz) { + Set interfaces = new HashSet<>(); + while (clazz != null) { + for (Class iface : clazz.getInterfaces()) { + interfaces.add(iface.getName()); + interfaces.addAll(getAllInterfaces(iface)); } + clazz = clazz.getSuperclass(); } - return eventBean; + return interfaces; } - private void xxeTriggerCheck(int i, JavaAgentEventBean eventBean, String klassName) { + public static List getAllSuperClasses(Class clazz) { + List superClasses = new ArrayList<>(); + Class currentClass = clazz.getSuperclass(); - if ((StringUtils.contains(klassName, XML_DOCUMENT_FRAGMENT_SCANNER_IMPL) - && StringUtils.equals(operation.getStackTrace()[i].getMethodName(), SCAN_DOCUMENT)) - || (StringUtils.contains(klassName, XML_ENTITY_MANAGER) - && StringUtils.equals(operation.getStackTrace()[i].getMethodName(), SETUP_CURRENT_ENTITY))) { - eventBean.getMetaData().setTriggerViaXXE(true); + while (currentClass != null) { + superClasses.add(currentClass.getName()); + currentClass = currentClass.getSuperclass(); } + + return superClasses; } - private void deserializationTriggerCheck(int index, JavaAgentEventBean eventBean, String klassName) { - if (!NewRelic.getAgent().getConfig().getValue(INRSettingsKey.SECURITY_DETECTION_DESERIALIZATION_ENABLED, true)) { - return; - } - if (ObjectInputStream.class.getName().equals(klassName) - && StringUtils.equals(operation.getStackTrace()[index].getMethodName(), READ_OBJECT)) { - eventBean.getMetaData().setTriggerViaDeserialisation(true); + private static JSONArray getUnlinkedChildrenJson(Set unlinkedChildren) { + JSONArray unlinkedChildrenJson = new JSONArray(); + for(DeserializationInfo deserializationInfo : unlinkedChildren) { + try { + JSONObject deserializationInfoJson = new JSONObject(); + deserializationInfoJson.put("type", deserializationInfo.getType()); + deserializationInfoJson.put("value", JsonConverter.getObjectMapper().writeValueAsString(deserializationInfo.getInstance())); + deserializationInfoJson.put("unlinkedChildren", getUnlinkedChildrenJson(deserializationInfo.getUnlinkedChildren())); + unlinkedChildrenJson.add(deserializationInfoJson); + } catch (Throwable e){ + logger.postLogMessageIfNecessary(LogLevel.WARNING, String.format("Unable to stringify the Object %s", deserializationInfo.getInstance()), e, + Dispatcher.class.getName()); + Agent.getInstance().reportIncident(LogLevel.WARNING, String.format("Unable to stringify the Object %s", deserializationInfo.getInstance()), e, + Dispatcher.class.getName()); + } } + return unlinkedChildrenJson; } - private void rciTriggerCheck(int index, JavaAgentEventBean eventBean, String klassName) { - if (!NewRelic.getAgent().getConfig().getValue(INRSettingsKey.SECURITY_DETECTION_RCI_ENABLED, true)) { - return; - } + private boolean allowedExtensionFileIO(JSONArray params, String sourceString, String url) { + if (JAVA_IO_FILE_INPUTSTREAM_OPEN.equals(sourceString)) { + for (int i = 0; i < params.size(); i++) { + String filePath = params.get(i).toString(); - if (operation.getStackTrace()[index].getLineNumber() <= 0 && index > 0 - && operation.getStackTrace()[index - 1].getLineNumber() > 0 && - StringUtils.isNotBlank(operation.getStackTrace()[index - 1].getFileName())) { - eventBean.getMetaData().setTriggerViaRCI(true); - eventBean.getMetaData().getRciMethodsCalls().add(AgentUtils.stackTraceElementToString(operation.getStackTrace()[index])); - eventBean.getMetaData().getRciMethodsCalls().add(AgentUtils.stackTraceElementToString(operation.getStackTrace()[index - 1])); - } - if (StringUtils.contains(klassName, REFLECT_NATIVE_METHOD_ACCESSOR_IMPL) - && StringUtils.equals(operation.getStackTrace()[index].getMethodName(), INVOKE_0) && index > 0) { - eventBean.getMetaData().setTriggerViaRCI(true); - eventBean.getMetaData().getRciMethodsCalls().add(AgentUtils.stackTraceElementToString(operation.getStackTrace()[index - 1])); + if (StringUtils.containsIgnoreCase(filePath, File.separator)) { + filePath = StringUtils.substringAfterLast(filePath, File.separator); + } + + if (StringUtils.containsIgnoreCase(url, File.separator)) { + url = StringUtils.substringAfterLast(url, File.separator); + } + + if (StringUtils.equals(url, filePath)) + return true; + } } + return false; } private JavaAgentEventBean setGenericProperties(AbstractOperation objectBean, JavaAgentEventBean eventBean) { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/CallbackUtils.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/CallbackUtils.java index 9d74d6bbd..a4e52cfcf 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/CallbackUtils.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/CallbackUtils.java @@ -1,6 +1,7 @@ package com.newrelic.agent.security.instrumentator.utils; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; +import com.newrelic.agent.security.intcodeagent.utils.TransactionUtils; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.HttpRequest; @@ -56,6 +57,8 @@ public class CallbackUtils { public static Set checkForReflectedXSS(HttpRequest httpRequest, HttpResponse httpResponse) { Set toReturn = new HashSet<>(); + TransactionUtils.trimResponseBody(httpResponse); + Set combinedRequestData = decodeRequestData(httpRequest); if (combinedRequestData.isEmpty()) { toReturn.add(StringUtils.EMPTY); @@ -251,7 +254,7 @@ public static Set isXSS(Set combinedData) { public static Set decodeResponseData(HttpResponse httpResponse) { Set processedData = new HashSet<>(); String contentType = httpResponse.getResponseContentType(); - String responseBody = httpResponse.getResponseBody().toString(); + String responseBody = httpResponse.getBody().toString(); String processedBody = responseBody; diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/AgentBasicInfo.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/AgentBasicInfo.java index c30926d0f..620e5dc8f 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/AgentBasicInfo.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/AgentBasicInfo.java @@ -31,6 +31,8 @@ public class AgentBasicInfo { public static final String APPLICATION_RUNTIME_ERROR = "application-runtime-error"; + public static final String SEC_HTTP_RESPONSE = "sec-http-response"; + /** * Tool id for Language Agent. */ @@ -120,6 +122,9 @@ public AgentBasicInfo() { } else if (this instanceof ApplicationRuntimeError) { setJsonName(APPLICATION_RUNTIME_ERROR); setEventType(APPLICATION_RUNTIME_ERROR); + } else if (this instanceof HttpResponseEvent) { + setJsonName(SEC_HTTP_RESPONSE); + setEventType(SEC_HTTP_RESPONSE); } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ApplicationRuntimeError.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ApplicationRuntimeError.java index abfc6ef54..25881d623 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ApplicationRuntimeError.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ApplicationRuntimeError.java @@ -87,7 +87,7 @@ public int getResponseCode() { return responseCode; } - public void setResponseCode(int responseCode) { + public void setStatusCode(int responseCode) { this.responseCode = responseCode; } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/HttpResponseEvent.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/HttpResponseEvent.java new file mode 100644 index 000000000..9a109ec59 --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/HttpResponseEvent.java @@ -0,0 +1,71 @@ +package com.newrelic.agent.security.intcodeagent.models.javaagent; + +import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants; +import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; +import com.newrelic.api.agent.security.schema.HttpRequest; +import com.newrelic.api.agent.security.schema.HttpResponse; + +public class HttpResponseEvent extends AgentBasicInfo { + private String traceId; + + private HttpResponse httpResponse; + + private HttpRequest httpRequest; + + private boolean isIastRequest; + + public HttpResponseEvent(HttpResponse httpResponse, boolean isIastRequest) { + super(); + this.httpResponse = new HttpResponse(httpResponse); + this.isIastRequest = isIastRequest; + this.traceId = getLinkingMetadata().get(IAgentConstants.NR_APM_TRACE_ID); + } + + public HttpResponseEvent(HttpResponseEvent httpResponseEvent) { + this.traceId = httpResponseEvent.getTraceId(); + this.httpResponse = new HttpResponse(httpResponseEvent.getHttpResponse()); + this.httpRequest = new HttpRequest(httpResponseEvent.getHttpRequest()); + this.isIastRequest = httpResponseEvent.getIsIASTRequest(); + } + + public String getTraceId() { + return traceId; + } + + public void setTraceId(String traceId) { + this.traceId = traceId; + } + + public HttpResponse getHttpResponse() { + return httpResponse; + } + + public void setHttpResponse(HttpResponse httpResponse) { + this.httpResponse = httpResponse; + } + + public HttpRequest getHttpRequest() { + return httpRequest; + } + + public void setHttpRequest(HttpRequest httpRequest) { + this.httpRequest = httpRequest; + } + + public boolean getIsIASTRequest() { + return isIastRequest; + } + + public void setIsIASTRequest(boolean iastRequest) { + isIastRequest = iastRequest; + } + + public boolean isEmpty() { + return traceId == null || httpResponse == null || httpResponse.getStatusCode() <= 0; + } + + @Override + public String toString() { + return JsonConverter.toJSON(this); + } +} diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/SerializerUtil.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/SerializerUtil.java new file mode 100644 index 000000000..af1d9c553 --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/SerializerUtil.java @@ -0,0 +1,183 @@ +package com.newrelic.agent.security.intcodeagent.utils; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; +import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; +import com.newrelic.api.agent.security.utils.logging.LogLevel; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.util.*; + +/** + * Utility class for serializing and deserializing objects. + */ +public class SerializerUtil { + + private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); + + private static final Map, Object> dummyValues = new HashMap<>(); + + static { + dummyValues.put(int.class, 0); + dummyValues.put(Integer.class, 0); + dummyValues.put(long.class, 0L); + dummyValues.put(Long.class, 0L); + dummyValues.put(double.class, 0.0); + dummyValues.put(Double.class, 0.0); + dummyValues.put(float.class, 0.0f); + dummyValues.put(Float.class, 0.0f); + dummyValues.put(boolean.class, false); + dummyValues.put(Boolean.class, false); + dummyValues.put(String.class, "dummy"); + } + + /** + * Serializes an object to a byte array. + * + * @param obj the object to serialize + * @return the byte array representation of the object, or null if serialization fails + */ + public static byte[] serialize(Object obj) { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(obj); + oos.flush(); + return bos.toByteArray(); + } catch (IOException e) { + logger.log(LogLevel.WARNING, String.format("Unable to serialize object : %s: %s", obj, e.getMessage()), CommonUtils.class.getName()); + logger.postLogMessageIfNecessary(LogLevel.WARNING, String.format("Unable to serialize object : %s", obj), e, CommonUtils.class.getName()); + } + return null; + } + + /** + * Instantiates an object from its JSON string representation. + * + * @param data the JSON string representation of the object + * @param klass the class of the object to instantiate + * @return the instantiated object, or null if instantiation fails + */ + public static Object instantiate(String data, Class klass) { + try { + return JsonConverter.getObjectMapper().readValue(data, klass); + } catch (JsonProcessingException e) { + logger.log(LogLevel.WARNING, String.format("Unable to instantiate object : %s: %s", klass, e.getMessage()), CommonUtils.class.getName()); + logger.postLogMessageIfNecessary(LogLevel.WARNING, String.format("Unable to instantiate object : %s", klass), e, CommonUtils.class.getName()); + } + return null; + } + + /** + * Encodes a byte array to a base64 string. + * + * @param data the byte array to encode + * @return the base64 string representation of the byte array + */ + public static String base64Encode(byte[] data) { + return java.util.Base64.getEncoder().encodeToString(data); + } + + + /** + * Retrieves the Class object associated with the class or interface with the given string name. + * + * @param className the fully qualified name of the desired class + * @return the Class object for the class with the specified name + * @throws ClassNotFoundException if the class cannot be located + */ + public static Class getClassByName(String className) throws ClassNotFoundException { + return Class.forName(className); + } + + /** + * Serializes an object to a byte array, then encodes the byte array to a base64 string. + * + * @param className the fully qualified name of the class of the object to serialize + * @param jsonData the JSON string representation of the object + * @return the base64 string representation of the serialized object, or null if serialization fails + */ + public static String base64SerializedPayload(String className, String jsonData) { + try { + Class clazz = getClassByName(className); + Object obj = instantiate(jsonData, clazz); + byte[] serialized = serialize(obj); + return base64Encode(serialized); + } catch (ClassNotFoundException e) { + logger.log(LogLevel.WARNING, String.format("Unable to base64 serialize object : %s: %s", className, e.getMessage()), CommonUtils.class.getName()); + logger.postLogMessageIfNecessary(LogLevel.WARNING, String.format("Unable to base64 serialize object : %s", className), e, CommonUtils.class.getName()); + } + return null; + } + + public static T createDummyObject(Class clazz, List fields) throws IllegalAccessException, InstantiationException { + T instance = clazz.newInstance(); + for (Field field : clazz.getDeclaredFields()) { + if(fields.contains(field.getName())) { + field.setAccessible(true); + setDummyValue(instance, field); + } + } + return instance; + } + + public static T createDummyObject(Class clazz) throws IllegalAccessException, InstantiationException { + T instance = clazz.newInstance(); + for (Field field : clazz.getDeclaredFields()) { + field.setAccessible(true); + setDummyValue(instance, field); + } + return instance; + } + + private static void setDummyValue(Object instance, Field field) throws IllegalAccessException, InstantiationException { + Class fieldType = field.getType(); + if (dummyValues.containsKey(fieldType)) { + field.set(instance, dummyValues.get(fieldType)); + } else if (List.class.isAssignableFrom(fieldType)) { + List dummyList = new ArrayList<>(); + dummyList.add(Runtime.class); + field.set(instance, dummyList); + } else if (Map.class.isAssignableFrom(fieldType)) { + Map dummyMap = new HashMap<>(); + dummyMap.put("dummyKey", Runtime.class); + field.set(instance, dummyMap); + } else if (Set.class.isAssignableFrom(fieldType)) { + Set dummySet = new HashSet<>(); + dummySet.add(Runtime.class); + field.set(instance, dummySet); + } else if (fieldType.isArray()) { + int dimensions = getArrayDimensions(fieldType); + Object arrayInstance = createArrayInstance(fieldType.getComponentType(), dimensions); + if (dimensions == 1) { + Array.set(arrayInstance, 0, dummyValues.getOrDefault(fieldType.getComponentType(), Runtime.class)); + } + field.set(instance, arrayInstance); + } else if (!fieldType.isPrimitive()) { + field.set(instance, createDummyObject(fieldType)); + } + } + + private static int getArrayDimensions(Class arrayClass) { + int dimensions = 0; + Class currentClass = arrayClass; + while (currentClass.isArray()) { + dimensions++; + currentClass = currentClass.getComponentType(); + } + return dimensions; + } + + private static Object createArrayInstance(Class componentType, int dimensions) { + int[] dimensionSizes = new int[dimensions]; + Arrays.fill(dimensionSizes, 1); // Initialize each dimension with size 1 + return Array.newInstance(componentType, dimensionSizes); + } + + + +} diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/TransactionUtils.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/TransactionUtils.java new file mode 100644 index 000000000..9c1ec9c21 --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/TransactionUtils.java @@ -0,0 +1,74 @@ +package com.newrelic.agent.security.intcodeagent.utils; + +import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants; +import com.newrelic.agent.security.intcodeagent.models.javaagent.HttpResponseEvent; +import com.newrelic.agent.security.intcodeagent.websocket.EventSendPool; +import com.newrelic.api.agent.NewRelic; +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.schema.HttpResponse; +import com.newrelic.api.agent.security.schema.SecurityMetaData; +import com.newrelic.api.agent.security.schema.operation.SecureCookieOperationSet; +import org.apache.commons.lang3.StringUtils; + +public class TransactionUtils { + + public static void reportHttpResponse() { + if(!NewRelicSecurity.isHookProcessingActive()) { + return; + } + if(NewRelic.getAgent().getTransaction().isWebTransaction()) { + SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); + + /* Send response event only when event is generated by phase 2 control command */ + if(securityMetaData != null + && securityMetaData.getFuzzRequestIdentifier().getK2Request() + && StringUtils.equals(securityMetaData.getFuzzRequestIdentifier().getNextStage().getStatus(), IAgentConstants.VULNERABLE) + && !securityMetaData.getResponse().isEmpty()) { + trimResponseBody(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse()); + HttpResponseEvent httpResponseEvent = new HttpResponseEvent(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse(), true); + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + httpResponseEvent.getHttpResponse().setBody(new StringBuilder(StringUtils.EMPTY)); + } + if(!httpResponseEvent.isEmpty()) { + EventSendPool.getInstance().sendEvent(httpResponseEvent); + } + } + } + } + + public static boolean trimResponseBody(HttpResponse response) { + if(response.getBody().length() > HttpResponse.MAX_ALLOWED_RESPONSE_BODY_LENGTH) { + response.setBody(new StringBuilder(response.getBody().substring(0, HttpResponse.MAX_ALLOWED_RESPONSE_BODY_LENGTH))); + response.setBody(new StringBuilder(response.getBody().append("..."))); + response.setDataTruncated(true); + return true; + } + return false; + } + + public static void executeBeforeExitingTransaction() { + Boolean exitLogicPerformed = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("EXIT_RECORDED", Boolean.class); + if(Boolean.TRUE.equals(exitLogicPerformed) || !NewRelicSecurity.isHookProcessingActive()){ + return; + } + + int responseCode = NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getStatusCode(); + if(responseCode >= 500){ + Exception exception = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("ENDMOST_EXCEPTION", Exception.class); + NewRelicSecurity.getAgent().recordExceptions(NewRelicSecurity.getAgent().getSecurityMetaData(), exception); + } + + if(!NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty()){ + NewRelicSecurity.getAgent().getSecurityMetaData().getUnregisteredOperations().forEach(operation -> { + NewRelicSecurity.getAgent().registerOperation(operation); + }); + SecureCookieOperationSet operations = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("SECURE_COOKIE_OPERATION", SecureCookieOperationSet.class); + if(operations != null) { + NewRelicSecurity.getAgent().registerOperation(operations); + NewRelicSecurity.getAgent().getSecurityMetaData().removeCustomAttribute("SECURE_COOKIE_OPERATION"); + } + } + + NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute("EXIT_RECORDED", true); + } +} diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/WSClient.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/WSClient.java index 3735db5aa..d89b8ef5b 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/WSClient.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/WSClient.java @@ -4,6 +4,8 @@ import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.dispatcher.DispatcherPool; import com.newrelic.agent.security.instrumentator.httpclient.RestRequestThreadPool; +import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; +import com.newrelic.agent.security.instrumentator.utils.AgentUtils; import com.newrelic.agent.security.instrumentator.utils.INRSettingsKey; import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessor; import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessorThreadPool; @@ -163,6 +165,7 @@ private WSClient() throws URISyntaxException { if (AgentConfig.getInstance().getScanControllers().getScanInstanceCount() >= 0) { this.addHeader("NR-CSEC-IAST-SCAN-INSTANCE-COUNT", String.valueOf(AgentConfig.getInstance().getScanControllers().getScanInstanceCount())); } + this.addHeader("NR-CSEC-VALIDATOR-HOME-TMP", OsVariablesInstance.getInstance().getOsVariables().getTmpDirectory()); Proxy proxy = proxyManager(); if(proxy != null) { this.setProxy(proxy); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/util/IUtilConstants.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/util/IUtilConstants.java index 2f08b7b74..4c08bb3f9 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/util/IUtilConstants.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/util/IUtilConstants.java @@ -13,6 +13,7 @@ public interface IUtilConstants { String SCAN_TIME_DURATION = "security.scan_schedule.duration"; String SCAN_TIME_COLLECT_SAMPLES = "security.scan_schedule.always_sample_traces"; String SCAN_REQUEST_RATE_LIMIT = "security.scan_controllers.iast_scan_request_rate_limit"; + String REPORT_HTTP_RESPONSE_BODY = "security.scan_controllers.report_http_response_body"; String SKIP_IAST_SCAN = "security.exclude_from_iast_scan"; String SKIP_IAST_SCAN_API = SKIP_IAST_SCAN + ".api"; @@ -31,6 +32,8 @@ public interface IUtilConstants { String SKIP_XPATH_INJECTION = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".xpath_injection"; String SKIP_SSRF = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".ssrf"; String SKIP_RXSS = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".rxss"; + String SKIP_UNSAFE_DESERIALIZATION = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".unsafe_deserialization"; + String SKIP_UNSAFE_REFLECTION = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".unsafe_reflection"; String RESTRICTION_CRITERIA_SCAN_TIME_SCHEDULE = "security.restriction_criteria.scan_time.schedule"; String RESTRICTION_CRITERIA_SCAN_TIME_DURATION = "security.restriction_criteria.scan_time.duration"; diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index 5039317fa..69499dad5 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -20,6 +20,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.*; import com.newrelic.api.agent.security.schema.operation.SecureCookieOperationSet; import com.newrelic.api.agent.security.schema.policy.IastDetectionCategory; +import com.newrelic.api.agent.security.utils.ExecutionIDGenerator; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.logging.HealthCheckScheduleThread; import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants; @@ -40,8 +41,6 @@ import java.io.IOException; import java.lang.instrument.Instrumentation; import java.lang.instrument.UnmodifiableClassException; -import java.net.HttpURLConnection; -import java.net.URL; import java.text.ParseException; import java.time.Instant; import java.time.temporal.ChronoUnit; @@ -368,6 +367,15 @@ private void deactivateSecurityServices(){ @Override public void registerOperation(AbstractOperation operation) { + if(operation instanceof RXSSOperation && NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } + + if(NewRelicSecurity.getAgent().getSecurityMetaData() != null && NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty()) { + NewRelicSecurity.getAgent().getSecurityMetaData().addUnregisteredOperation(operation); + return; + } + AgentInfo.getInstance().getJaHealthCheck().incrementInvokedHookCount(); // added to fetch request/response in case of grpc requests boolean lockAcquired = ThreadLocalLockHelper.acquireLock(); @@ -385,7 +393,7 @@ public void registerOperation(AbstractOperation operation) { if (securityMetaData != null && securityMetaData.getRequest().getIsGrpc()) { securityMetaData.getRequest().setBody( new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_REQUEST_DATA, List.class)))); - securityMetaData.getResponse().setResponseBody( + securityMetaData.getResponse().setBody( new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_RESPONSE_DATA, List.class)))); } @@ -397,27 +405,27 @@ public void registerOperation(AbstractOperation operation) { return; } - String executionId = ExecutionIDGenerator.getExecutionId(); - operation.setExecutionId(executionId); operation.setStartTime(Instant.now().toEpochMilli()); if (securityMetaData != null && securityMetaData.getFuzzRequestIdentifier().getK2Request()) { logger.log(LogLevel.FINEST, String.format("New Event generation with id %s of type %s", operation.getExecutionId(), operation.getClass().getSimpleName()), Agent.class.getName()); } - if (operation instanceof RXSSOperation) { - operation.setStackTrace(securityMetaData.getMetaData().getServiceTrace()); - securityMetaData.addCustomAttribute("RXSS_PROCESSED", true); - } else if (operation instanceof SecureCookieOperationSet) { - operation.setStackTrace(securityMetaData.getMetaData().getServiceTrace()); - } else { - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - operation.setStackTrace(Arrays.copyOfRange(trace, securityMetaData.getMetaData().getFromJumpRequiredInStackTrace(), trace.length)); + if (operation.getStackTrace() == null || operation.getStackTrace().length <= 0) { + if (operation instanceof RXSSOperation) { + operation.setStackTrace(securityMetaData.getMetaData().getServiceTrace()); + securityMetaData.addCustomAttribute("RXSS_PROCESSED", true); + } else if (operation instanceof SecureCookieOperationSet) { + operation.setStackTrace(securityMetaData.getMetaData().getServiceTrace()); + } else { + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + operation.setStackTrace(Arrays.copyOfRange(trace, securityMetaData.getMetaData().getFromJumpRequiredInStackTrace(), trace.length)); + } } // added to fetch request/response in case of grpc requests if (securityMetaData.getRequest().getIsGrpc()) { securityMetaData.getRequest().setBody( new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_REQUEST_DATA, List.class)))); - securityMetaData.getResponse().setResponseBody( + securityMetaData.getResponse().setBody( new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_RESPONSE_DATA, List.class)))); } @@ -451,8 +459,14 @@ public void registerOperation(AbstractOperation operation) { operation.setUserClassEntity(setUserClassEntity(operation, securityMetaData)); } processStackTrace(operation); -// boolean blockNeeded = checkIfBlockingNeeded(operation.getApiID()); -// securityMetaData.getMetaData().setApiBlocked(blockNeeded); + if(securityMetaData.getDeserializationInvocation() != null && securityMetaData.getDeserializationInvocation().getActive()){ + securityMetaData.getMetaData().addLinkedEventId(operation.getExecutionId()); + securityMetaData.getMetaData().setParentEventId(securityMetaData.getDeserializationInvocation().getEid()); + securityMetaData.getMetaData().setTriggerViaDeserialisation(true); + } else { + securityMetaData.getMetaData().setTriggerViaDeserialisation(false); + } + HttpRequest request = securityMetaData.getRequest(); Framework frameWork = Framework.UNKNOWN; if(!securityMetaData.getFuzzRequestIdentifier().getK2Request() && StringUtils.isNotBlank(securityMetaData.getMetaData().getFramework())) { @@ -584,29 +598,34 @@ private void logIfIastScanForFirstTime(K2RequestIdentifier fuzzRequestIdentifier } private static boolean checkIfNRGeneratedEvent(AbstractOperation operation) { - boolean isNettyReactor = false, isNRGeneratedEvent = false; - for (int i = 0, j = -1; i < operation.getStackTrace().length; i++) { - if(StringUtils.equalsAny(operation.getStackTrace()[i].getClassName(), - "com.nr.instrumentation.TokenLinkingSubscriber", - "com.nr.instrumentation.reactor.netty.TokenLinkingSubscriber", - "com.nr.vertx.instrumentation.VertxUtil$1", - "com.nr.vertx.instrumentation.HttpClientRequestPromiseWrapper")){ - isNettyReactor = true; - continue; - } - - // Only remove consecutive top com.newrelic and com.nr. elements from stack. - if (i - 1 == j && StringUtils.startsWithAny(operation.getStackTrace()[i].getClassName(), "com.newrelic.", "com.nr.")) { - j++; - } else if (StringUtils.startsWithAny(operation.getStackTrace()[i].getClassName(), "com.newrelic.", "com.nr.")) { - isNRGeneratedEvent = true; - break; + for (int i = 1; i < operation.getStackTrace().length; i++) { + if(StringUtils.startsWith(operation.getStackTrace()[i].getClassName(), "com.newrelic.")) { + return true; } } - if (isNettyReactor) { - operation.setStackTrace(removeNettyReactorLinkingTraces(operation.getStackTrace())); - } - return isNRGeneratedEvent; + return false; +// boolean isNettyReactor = false, isNRGeneratedEvent = false; +// for (int i = 1, j = 0; i < operation.getStackTrace().length; i++) { +// if(StringUtils.equalsAny(operation.getStackTrace()[i].getClassName(), +// "com.nr.instrumentation.TokenLinkingSubscriber", +// "com.nr.instrumentation.reactor.netty.TokenLinkingSubscriber", +// "com.nr.vertx.instrumentation.VertxUtil$1", +// "com.nr.vertx.instrumentation.HttpClientRequestPromiseWrapper")){ +// isNettyReactor = true; +// continue; +// } +// +// // Only remove consecutive top com.newrelic and com.nr. elements from stack. +// if (i - 1 == j && StringUtils.startsWithAny(operation.getStackTrace()[i].getClassName(), "com.newrelic.", "com.nr.")) { +// j++; +// } else if (StringUtils.startsWithAny(operation.getStackTrace()[i].getClassName(), "com.newrelic.", "com.nr.")) { +// return true; +// } +// } +// if (isNettyReactor) { +// operation.setStackTrace(removeNettyReactorLinkingTraces(operation.getStackTrace())); +// } +// return isNRGeneratedEvent; } private static StackTraceElement[] removeNettyReactorLinkingTraces(StackTraceElement[] stackTrace) { @@ -1066,7 +1085,7 @@ private String generateTraceIdForRuntimeError(SecurityMetaData securityMetaData, @Override public boolean recordExceptions(SecurityMetaData securityMetaData, Throwable exception) { - int responseCode = securityMetaData.getResponse().getResponseCode(); + int responseCode = securityMetaData.getResponse().getStatusCode(); String route = securityMetaData.getRequest().getUrl(); if(StringUtils.isNotBlank(securityMetaData.getRequest().getRoute())){ route = securityMetaData.getRequest().getRoute(); @@ -1085,4 +1104,43 @@ public void reportURLMapping() { SchedulerHelper.getInstance().scheduleURLMappingPosting(AgentUtils::sendApplicationURLMappings); } + @Override + public void dispatcherTransactionStarted() { + try { + Transaction transaction = NewRelic.getAgent().getTransaction(); + if (isInitialised() && NewRelicSecurity.isHookProcessingActive()) { + logger.log(LogLevel.FINEST, "Transaction started with token: " + transaction.getToken().toString(), Agent.class.getName()); + } + } catch (Exception e){ + logger.log(LogLevel.FINEST, "Error while processing transaction started event", e, Agent.class.getName()); + } + } + + @Override + public void dispatcherTransactionCancelled() { + try { + Transaction transaction = NewRelic.getAgent().getTransaction(); + if (isInitialised() && NewRelicSecurity.isHookProcessingActive()) { + logger.log(LogLevel.FINEST, "Transaction cancelled with token: " + transaction.getSecurityMetaData().toString(), Agent.class.getName()); + TransactionUtils.executeBeforeExitingTransaction(); +// TransactionUtils.reportHttpResponse(); + } + } catch (Exception e){ + logger.log(LogLevel.FINEST, "Error while processing transaction cancelled event", e, Agent.class.getName()); + } + } + + @Override + public void dispatcherTransactionFinished() { + try { + if (isInitialised() && NewRelicSecurity.isHookProcessingActive()) { + logger.log(LogLevel.FINEST, "Transaction finished with token: " + NewRelic.getAgent().getTransaction().getSecurityMetaData().toString(), Agent.class.getName()); + TransactionUtils.executeBeforeExitingTransaction(); +// TransactionUtils.reportHttpResponse(); + } + } catch (Exception e){ + logger.log(LogLevel.FINEST, "Error while processing transaction finished event", e, Agent.class.getName()); + } + } + } \ No newline at end of file diff --git a/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java index f6f0e18a9..1c46b4f66 100644 --- a/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -80,12 +80,10 @@ public void registerOperation(AbstractOperation operation) { } } System.out.println("Registering operation : " + operation.hashCode() + " : " + NewRelic.getAgent().getTransaction().hashCode()); - String executionId = "dummy-exec-id"; String apiId = "dummy-api-id"; if(operation instanceof FileIntegrityOperation && ((FileIntegrityOperation) operation).getFileName().endsWith(".new.class")){ return; } - operation.setExecutionId(executionId); operation.setApiID(apiId); operation.setStartTime(Instant.now().toEpochMilli()); StackTraceElement[] trace = Thread.currentThread().getStackTrace(); @@ -233,4 +231,16 @@ public boolean recordExceptions(SecurityMetaData securityMetaData, Throwable exc public void reportURLMapping() { } + + @Override + public void dispatcherTransactionStarted() { + } + + @Override + public void dispatcherTransactionCancelled() { + } + + @Override + public void dispatcherTransactionFinished() { + } } \ No newline at end of file diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/NoOpAgent.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/NoOpAgent.java index 429737aa2..b0be3fafc 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/NoOpAgent.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/NoOpAgent.java @@ -153,4 +153,19 @@ public void reportURLMapping() { } + @Override + public void dispatcherTransactionStarted() { + + } + + @Override + public void dispatcherTransactionCancelled() { + + } + + @Override + public void dispatcherTransactionFinished() { + + } + } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/SecurityAgent.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/SecurityAgent.java index 3d3f9f642..b3476279a 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/SecurityAgent.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/SecurityAgent.java @@ -80,4 +80,10 @@ void reportIASTScanFailure(SecurityMetaData securityMetaData, String apiId, Thro boolean recordExceptions(SecurityMetaData securityMetaData, Throwable exception); void reportURLMapping(); + + void dispatcherTransactionStarted(); + + void dispatcherTransactionCancelled(); + + void dispatcherTransactionFinished(); } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GenericHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GenericHelper.java index ca295a500..fdbc0bdbe 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GenericHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GenericHelper.java @@ -52,7 +52,7 @@ public static boolean isLockAcquired(String nrSecCustomAttrName, int hashCode) { return false; } - private static boolean isLockAcquirePossible(VulnerabilityCaseType caseType) { + public static boolean isLockAcquirePossible(VulnerabilityCaseType caseType) { if (!NewRelicSecurity.isHookProcessingActive()){ return false; } @@ -62,9 +62,9 @@ private static boolean isLockAcquirePossible(VulnerabilityCaseType caseType) { if (caseType.equals(VulnerabilityCaseType.REFLECTED_XSS) && NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isRequestParsed()){ return false; } - if (!caseType.equals(VulnerabilityCaseType.REFLECTED_XSS) && NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty()) { - return false; - } +// if (!caseType.equals(VulnerabilityCaseType.REFLECTED_XSS) && NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty()) { +// return false; +// } boolean enabled = false; switch (caseType) { case SYSTEM_COMMAND: @@ -104,6 +104,12 @@ private static boolean isLockAcquirePossible(VulnerabilityCaseType caseType) { case HASH: enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getInsecureSettingsEnabled(); break; + case UNSAFE_DESERIALIZATION: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getUnsafeDeserializationEnabled(); + break; + case REFLECTION: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getInsecureReflectionEnabled(); + break; default: break; } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/IASTSerialisationVerifier.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/IASTSerialisationVerifier.java new file mode 100644 index 000000000..19632ea5a --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/IASTSerialisationVerifier.java @@ -0,0 +1,35 @@ +package com.newrelic.api.agent.security.instrumentation.helpers; + +import java.io.Serializable; + +public class IASTSerialisationVerifier implements Serializable { + + private static final long serialVersionUID = 522078560470736671L; + + private String type; + private transient String name; + + public IASTSerialisationVerifier() { + } + + public IASTSerialisationVerifier(String type, String name) { + this.type = type; + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/IOStreamHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/IOStreamHelper.java index 9d7555d02..49b0f2ac8 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/IOStreamHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/IOStreamHelper.java @@ -1,10 +1,8 @@ package com.newrelic.api.agent.security.instrumentation.helpers; import com.newrelic.api.agent.security.NewRelicSecurity; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.utils.logging.LogLevel; -import java.util.HashSet; import java.util.Set; public class IOStreamHelper { @@ -66,7 +64,7 @@ public static void preprocessSecurityHook(byte[] dataBuffer, data[y] = (char) dataBuffer[i]; } // System.out.println("Writing from IS 2" + this.hashCode() + " : " + String.valueOf(data)); - NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseBody().append(data); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getBody().append(data); } } catch(Throwable ignored) { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(ERROR_WHILE_READING_STREAM, JAVA_IO_STREAM, ignored.getMessage()), ignored, IOStreamHelper.class.getName()); diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/InstrumentationConstants.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/InstrumentationConstants.java new file mode 100644 index 000000000..cd55aac00 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/InstrumentationConstants.java @@ -0,0 +1,7 @@ +package com.newrelic.api.agent.security.instrumentation.helpers; + +public class InstrumentationConstants { + + + public static final String ACTIVE_DESERIALIZATION = "active-deserialization"; +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java index a6c57384e..0f378a7f5 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java @@ -233,23 +233,5 @@ public static boolean isResponseContentTypeExcluded( String responseContentType) return unsupportedContentType.contains(responseContentType); } - public static void executeBeforeExitingTransaction() { - Boolean exitLogicPerformed = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("EXIT_RECORDED", Boolean.class); - if(Boolean.TRUE.equals(exitLogicPerformed) || !NewRelicSecurity.isHookProcessingActive()){ - return; - } - - int responseCode = NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseCode(); - if(responseCode >= 500){ - Exception exception = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("ENDMOST_EXCEPTION", Exception.class); - NewRelicSecurity.getAgent().recordExceptions(NewRelicSecurity.getAgent().getSecurityMetaData(), exception); - } - SecureCookieOperationSet operations = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("SECURE_COOKIE_OPERATION", SecureCookieOperationSet.class); - if(operations != null) { - NewRelicSecurity.getAgent().registerOperation(operations); - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute("SECURE_COOKIE_OPERATION", null); - } - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute("EXIT_RECORDED", true); - } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/serializer/ObjectInstanceFactory.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/serializer/ObjectInstanceFactory.java new file mode 100644 index 000000000..0220e28af --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/serializer/ObjectInstanceFactory.java @@ -0,0 +1,24 @@ +package com.newrelic.api.agent.security.instrumentation.helpers.serializer; + +import java.io.ObjectStreamClass; +import java.lang.reflect.Constructor; + +public class ObjectInstanceFactory { + + public static Object createInstance(Class clazz) throws Exception { + ObjectStreamClass osc = ObjectStreamClass.lookup(clazz); + if (osc == null) { + throw new IllegalArgumentException("Class not serializable: " + clazz.getName()); + } + + Constructor constructor = clazz.getDeclaredConstructor(); + return constructor.newInstance(); + } + + public static Class getClassByName(String className) throws ClassNotFoundException { + return Class.forName(className); + } + + + +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AbstractOperation.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AbstractOperation.java index c7e1e3cbb..6c1b12e12 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AbstractOperation.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AbstractOperation.java @@ -1,5 +1,7 @@ package com.newrelic.api.agent.security.schema; +import com.newrelic.api.agent.security.utils.ExecutionIDGenerator; + public abstract class AbstractOperation { public static final String EMPTY = ""; @@ -36,9 +38,10 @@ public AbstractOperation() { } public AbstractOperation(String className, String methodName){ - this.className = className; - this.methodName = methodName; - this.blockingEndTime = 0L; + this.className = className; + this.methodName = methodName; + this.blockingEndTime = 0L; + this.executionId = ExecutionIDGenerator.getExecutionId(); } public String getClassName() { diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java index dd35b63b0..2011b696f 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java @@ -49,6 +49,10 @@ public class AgentMetaData { private AppServerInfo appServerInfo; + private Set linkedEventIds; + + private String parentEventId; + public AgentMetaData() { this.rciMethodsCalls = new HashSet<>(); this.ips = new HashSet<>(); @@ -57,6 +61,7 @@ public AgentMetaData() { this.appServerInfo = new AppServerInfo(); this.framework = StringUtils.EMPTY; this.skipScanParameters = new SkipScanParameters(); + this.linkedEventIds = new HashSet<>(); } public AgentMetaData(AgentMetaData agentMetaData) { @@ -79,6 +84,8 @@ public AgentMetaData(AgentMetaData agentMetaData) { this.fromJumpRequiredInStackTrace = agentMetaData.getFromJumpRequiredInStackTrace(); this.framework = agentMetaData.framework; this.skipScanParameters = agentMetaData.skipScanParameters; + this.linkedEventIds = new HashSet<>(agentMetaData.linkedEventIds); + this.parentEventId = agentMetaData.parentEventId; } public boolean isTriggerViaRCI() { @@ -229,4 +236,33 @@ public SkipScanParameters getSkipScanParameters() { public void setSkipScanParameters(SkipScanParameters skipScanParameters) { this.skipScanParameters = skipScanParameters; } + + public Set getLinkedEventIds() { + return linkedEventIds; + } + + public boolean addLinkedEventId(String linkedEventId) { + return linkedEventIds.add(linkedEventId); + } + + public boolean removeLinkedEventId(String linkedEventId) { + return linkedEventIds.remove(linkedEventId); + } + + public void setLinkedEventIds(Set linkedEventIds) { + this.linkedEventIds = linkedEventIds; + } + + public void clearLinkedEventIds() { + linkedEventIds.clear(); + } + + public String getParentEventId() { + return parentEventId; + } + + public void setParentEventId(String parentEventId) { + this.parentEventId = parentEventId; + } + } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/DeserializationInfo.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/DeserializationInfo.java new file mode 100644 index 000000000..a9b93f07a --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/DeserializationInfo.java @@ -0,0 +1,64 @@ +package com.newrelic.api.agent.security.schema; + +import java.util.*; + + +public class DeserializationInfo { + + private String type; + private Set unlinkedChildren = new HashSet<>(); + private Object instance; + + public DeserializationInfo(String type, Object instance) { + this.type = type; + this.instance = instance; + } + + public DeserializationInfo(DeserializationInfo instance) { + if (instance == null) { + return; + } + this.type = instance.type; +// for(DeserializationInfo value: instance.unlinkedChildren){ +// value.computeObjectMap(); +// this.unlinkedChildren.add(new DeserializationInfo(value)); +// } + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Object getInstance() { + return instance; + } + + public void setInstance(Object instance) { + this.instance = instance; + } + + public Set getUnlinkedChildren() { + return unlinkedChildren; + } + + public void setUnlinkedChildren(Set unlinkedChildren) { + this.unlinkedChildren = unlinkedChildren; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof DeserializationInfo)) return false; + DeserializationInfo that = (DeserializationInfo) o; + return Objects.equals(type, that.type) && Objects.equals(instance, that.instance); + } + + @Override + public int hashCode() { + return Objects.hash(type, instance); + } +} \ No newline at end of file diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/DeserializationInvocation.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/DeserializationInvocation.java new file mode 100644 index 000000000..ad88c92c9 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/DeserializationInvocation.java @@ -0,0 +1,78 @@ +package com.newrelic.api.agent.security.schema; + +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; + +public class DeserializationInvocation { + + private Boolean active; + + private String eid; + + private Stack readObjectInAction; + + private Map encounteredSerializable; + + public DeserializationInvocation(boolean active, String executionId) { + this.active = active; + this.eid = executionId; + this.readObjectInAction = new Stack<>(); + encounteredSerializable = new HashMap<>(); + } + + public Boolean getActive() { + return active; + } + + public void setActive(Boolean active) { + this.active = active; + } + + public String getEid() { + return eid; + } + + public void setEid(String eid) { + this.eid = eid; + } + + public Map getEncounteredSerializable() { + return encounteredSerializable; + } + + public void setEncounteredSerializable(Map encounteredSerializable) { + this.encounteredSerializable = encounteredSerializable; + } + + public Serializable addEncounteredSerializable(Serializable serializable) { + return this.encounteredSerializable.put(serializable.getNameOfClass(), serializable); + } + + public Serializable getEncounteredSerializableByName(String nameOfClass) { + return this.encounteredSerializable.get(nameOfClass); + } + + public Stack getReadObjectInAction() { + return readObjectInAction; + } + + public void setReadObjectInAction(Stack readObjectInAction) { + this.readObjectInAction = readObjectInAction; + } + + public void pushReadObjectInAction(String readObjectInAction) { + this.readObjectInAction.push(readObjectInAction); + } + + public String popReadObjectInAction() { + return this.readObjectInAction.pop(); + } + + public String peekReadObjectInAction() { + if(this.readObjectInAction.isEmpty()) { + return null; + } + return this.readObjectInAction.peek(); + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/FiledDefinition.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/FiledDefinition.java new file mode 100644 index 000000000..64229ca81 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/FiledDefinition.java @@ -0,0 +1,92 @@ +package com.newrelic.api.agent.security.schema; + +import com.newrelic.api.agent.security.schema.annotations.JsonIgnore; + +import java.util.List; + +public class FiledDefinition { + + private String name; + + private String type; + + @JsonIgnore + private List parameterizedType; + + @JsonIgnore + private boolean isPrimitive; + + private boolean isTransient; + + @JsonIgnore + private boolean isSerializable; + + private SerializableClassDefinition classDefinition; + + public FiledDefinition() { + } + + public FiledDefinition(String name, String type, boolean isPrimitive, boolean isTransient, boolean isSerializable) { + this.name = name; + this.type = type; + this.isPrimitive = isPrimitive; + this.isTransient = isTransient; + this.isSerializable = isSerializable; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public boolean getIsPrimitive() { + return isPrimitive; + } + + public void setIsPrimitive(boolean primitive) { + isPrimitive = primitive; + } + + public boolean getIsTransient() { + return isTransient; + } + + public void setIsTransient(boolean aTransient) { + isTransient = aTransient; + } + + public boolean getIsSerializable() { + return isSerializable; + } + + public void setIsSerializable(boolean serializable) { + isSerializable = serializable; + } + + public SerializableClassDefinition getClassDefinition() { + return classDefinition; + } + + public void setClassDefinition(SerializableClassDefinition classDefinition) { + this.classDefinition = classDefinition; + } + + public List getParameterizedType() { + return parameterizedType; + } + + public void setParameterizedType(List parameterizedType) { + this.parameterizedType = parameterizedType; + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpResponse.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpResponse.java index 4e00aa4b4..499c454af 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpResponse.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpResponse.java @@ -1,29 +1,38 @@ package com.newrelic.api.agent.security.schema; +import com.newrelic.api.agent.security.schema.annotations.JsonIgnore; + import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class HttpResponse { + @JsonIgnore + public static final int MAX_ALLOWED_RESPONSE_BODY_LENGTH = 500000; + private Map headers; - private StringBuilder responseBody; + private StringBuilder body; private String contentType; - private int responseCode; + private int statusCode; + + private boolean dataTruncated; public HttpResponse() { this.headers = new ConcurrentHashMap<>(); - this.responseBody = new StringBuilder(); + this.body = new StringBuilder(); this.contentType = StringUtils.EMPTY; + this.dataTruncated = false; } public HttpResponse(HttpResponse httpResponse) { this.headers = new ConcurrentHashMap<>(httpResponse.getHeaders()); - this.responseBody = new StringBuilder(httpResponse.responseBody); - this.contentType = new String(httpResponse.contentType.trim()); - this.responseCode = httpResponse.responseCode; + this.body = new StringBuilder(httpResponse.body); + this.contentType = httpResponse.contentType.trim(); + this.statusCode = httpResponse.statusCode; + this.dataTruncated = httpResponse.dataTruncated; } public Map getHeaders() { @@ -34,27 +43,31 @@ public void setHeaders(Map headers) { this.headers = headers; } - public StringBuilder getResponseBody() { - return this.responseBody; + public StringBuilder getBody() { + return this.body; } - public void setResponseBody(StringBuilder responseBody) { - this.responseBody = responseBody; + public void setBody(StringBuilder body) { + this.body = body; } public String getResponseContentType() { return contentType; } - public int getResponseCode() { - return responseCode; + public int getStatusCode() { + return statusCode; + } + + public void setStatusCode(int statusCode) { + this.statusCode = statusCode; } - public void setResponseCode(int responseCode) { - this.responseCode = responseCode; + public String getContentType() { + return contentType; } - public void setResponseContentType(String responseContentType) { + public void setContentType(String responseContentType) { if (StringUtils.isNotBlank(responseContentType)) { this.contentType = StringUtils.substringBefore(responseContentType, ";").trim().toLowerCase(); } else { @@ -62,7 +75,15 @@ public void setResponseContentType(String responseContentType) { } } + public boolean isDataTruncated() { + return dataTruncated; + } + + public void setDataTruncated(boolean dataTruncated) { + this.dataTruncated = dataTruncated; + } + public boolean isEmpty() { - return StringUtils.isAnyBlank(responseBody, contentType); + return StringUtils.isAnyBlank(body, contentType); } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/SecurityMetaData.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/SecurityMetaData.java index aa0a7fab6..d335900d0 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/SecurityMetaData.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/SecurityMetaData.java @@ -3,8 +3,7 @@ import com.newrelic.api.agent.security.schema.operation.FileIntegrityOperation; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** @@ -27,6 +26,10 @@ public class SecurityMetaData { private Map customData; + private Set unregisteredOperations; + + private DeserializationInvocation deserializationInvocation; + public SecurityMetaData() { request = new HttpRequest(); response = new HttpResponse(); @@ -35,6 +38,7 @@ public SecurityMetaData() { fileLocalMap = new HashMap<>(); fuzzRequestIdentifier = new K2RequestIdentifier(); customData = new ConcurrentHashMap<>(); + unregisteredOperations = new HashSet<>(); } public SecurityMetaData(SecurityMetaData securityMetaData) { @@ -45,6 +49,7 @@ public SecurityMetaData(SecurityMetaData securityMetaData) { fileLocalMap = new HashMap<>(securityMetaData.getFileLocalMap()); fuzzRequestIdentifier = new K2RequestIdentifier(securityMetaData.getFuzzRequestIdentifier()); customData = new ConcurrentHashMap<>(securityMetaData.customData); + unregisteredOperations = new HashSet<>(securityMetaData.unregisteredOperations); } public HttpRequest getRequest() { @@ -107,6 +112,14 @@ public T getCustomAttribute(String key, Class klass) { return klass.cast(this.customData.get(key)); } + public Set getUnregisteredOperations() { + return unregisteredOperations; + } + + public void addUnregisteredOperation(AbstractOperation operation) { + this.unregisteredOperations.add(operation); + } + public void removeCustomAttribute(String key) { this.customData.remove(key); } @@ -114,4 +127,31 @@ public void clearCustomAttr(){ customData.clear(); } + public boolean addToDeserializationRoot(DeserializationInfo dinfo) { + if (getCustomAttribute("deserializationRoot", DeserializationInfo.class) == null){ + addCustomAttribute("deserializationRoot", dinfo); + return true; + } else { + DeserializationInfo root = getCustomAttribute("deserializationRoot", DeserializationInfo.class); + root.getUnlinkedChildren().add(dinfo); + return false; + } + } + + public void resetDeserializationRoot() { + this.removeCustomAttribute("deserializationRoot"); + this.metaData.clearLinkedEventIds(); + } + + public DeserializationInfo peekDeserializationRoot() { + return getCustomAttribute("deserializationRoot", DeserializationInfo.class); + } + + public DeserializationInvocation getDeserializationInvocation() { + return deserializationInvocation; + } + + public void setDeserializationInvocation(DeserializationInvocation deserializationInvocation) { + this.deserializationInvocation = deserializationInvocation; + } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/Serializable.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/Serializable.java new file mode 100644 index 000000000..a61716f16 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/Serializable.java @@ -0,0 +1,70 @@ +package com.newrelic.api.agent.security.schema; + +import com.newrelic.api.agent.security.schema.annotations.JsonIgnore; + +import java.util.Objects; + +public class Serializable { + + private String nameOfClass; + + @JsonIgnore + private Class klass; + + private Boolean deserializable; + + private SerializableClassDefinition classDefinition; + + public Serializable() { + } + + public Serializable(String nameOfClass, Boolean deserializable) { + this.nameOfClass = nameOfClass; + this.deserializable = deserializable; + } + + public String getNameOfClass() { + return nameOfClass; + } + + public void setNameOfClass(String nameOfClass) { + this.nameOfClass = nameOfClass; + } + + public Boolean getDeserializable() { + return deserializable; + } + + public void setDeserializable(Boolean deserializable) { + this.deserializable = deserializable; + } + + public SerializableClassDefinition getClassDefinition() { + return classDefinition; + } + + public void setClassDefinition(SerializableClassDefinition classDefinition) { + this.classDefinition = classDefinition; + } + + public Class getKlass() { + return klass; + } + + public void setKlass(Class klass) { + this.klass = klass; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Serializable)) return false; + Serializable that = (Serializable) o; + return Objects.equals(nameOfClass, that.nameOfClass); + } + + @Override + public int hashCode() { + return Objects.hashCode(nameOfClass); + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/SerializableClassDefinition.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/SerializableClassDefinition.java new file mode 100644 index 000000000..6378d05fd --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/SerializableClassDefinition.java @@ -0,0 +1,50 @@ +package com.newrelic.api.agent.security.schema; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class SerializableClassDefinition { + + private String name; + + private boolean isInterface; + + private List fields; + + public SerializableClassDefinition(String name, boolean anInterface, List filedDefinitions) { + this.isInterface = anInterface; + this.name = name; + this.fields = filedDefinitions; + } + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getFields() { + return fields; + } + + public void setFields(List fields) { + this.fields = fields; + } + + public boolean addFields(FiledDefinition field) { + return this.fields.add(field); + } + + public boolean getIsInterface() { + return isInterface; + } + + public void setIsInterface(boolean isInterface) { + this.isInterface = isInterface; + } + +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/VulnerabilityCaseType.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/VulnerabilityCaseType.java index a3d8a31d2..8ab1e5b67 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/VulnerabilityCaseType.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/VulnerabilityCaseType.java @@ -71,7 +71,11 @@ public enum VulnerabilityCaseType { CACHING_DATA_STORE("CACHING_DATA_STORE"), - SOLR_DB_REQUEST("SOLR_DB_REQUEST"); + SOLR_DB_REQUEST("SOLR_DB_REQUEST"), + /** Unsafe Deserialization */ + UNSAFE_DESERIALIZATION("UNSAFE_DESERIALIZATION"), + /** Reflection */ + REFLECTION("REFLECTION"); /** case type. */ diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/DeserializationOperation.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/DeserializationOperation.java new file mode 100644 index 000000000..29792aeff --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/DeserializationOperation.java @@ -0,0 +1,57 @@ +package com.newrelic.api.agent.security.schema.operation; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.schema.*; + +import java.util.Map; + +public class DeserializationOperation extends AbstractOperation { + + private String entityName; + private Map params; + private DeserializationInfo rootDeserializationInfo; + private DeserializationInvocation deserializationInvocation; + + + public DeserializationOperation(String className, String methodName) { + super(className, methodName); + this.setCaseType(VulnerabilityCaseType.UNSAFE_DESERIALIZATION); + } + + @Override + public boolean isEmpty() { + return this.deserializationInvocation == null; + } + + public String getEntityName() { + return entityName; + } + + public void setEntityName(String entityName) { + this.entityName = entityName; + } + + public Map getParams() { + return params; + } + + public void setParams(Map params) { + this.params = params; + } + + public DeserializationInfo getRootDeserializationInfo() { + return rootDeserializationInfo; + } + + public void setRootDeserializationInfo(DeserializationInfo rootDeserializationInfo) { + this.rootDeserializationInfo = rootDeserializationInfo; + } + + public DeserializationInvocation getDeserializationInvocation() { + return deserializationInvocation; + } + + public void setDeserializationInvocation(DeserializationInvocation deserializationInvocation) { + this.deserializationInvocation = deserializationInvocation; + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/JavaReflectionOperation.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/JavaReflectionOperation.java new file mode 100644 index 000000000..4a357c2d7 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/JavaReflectionOperation.java @@ -0,0 +1,73 @@ +package com.newrelic.api.agent.security.schema.operation; + +import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; + +import java.util.List; + +public class JavaReflectionOperation extends AbstractOperation { + + private String declaringClass; + + private String nameOfMethod; + + private Object[] args; + + private Object obj; + + private List declaredMethods; + + public JavaReflectionOperation(String className, String methodName, String declaringClass, String nameOfMethod,Object[] args, Object obj) { + super(className, methodName); + this.setCaseType(VulnerabilityCaseType.REFLECTION); + this.declaringClass = declaringClass; + this.nameOfMethod = nameOfMethod; + this.args = args; + this.obj = obj; + } + + public String getDeclaringClass() { + return declaringClass; + } + + public void setDeclaringClass(String declaringClass) { + this.declaringClass = declaringClass; + } + + public Object getObj() { + return obj; + } + + public void setObj(Object obj) { + this.obj = obj; + } + + public Object[] getArgs() { + return args; + } + + public void setArgs(Object[] args) { + this.args = args; + } + + public String getNameOfMethod() { + return nameOfMethod; + } + + public void setNameOfMethod(String nameOfMethod) { + this.nameOfMethod = nameOfMethod; + } + + public List getDeclaredMethods() { + return declaredMethods; + } + + public void setDeclaredMethods(List declaredMethods) { + this.declaredMethods = declaredMethods; + } + + @Override + public boolean isEmpty() { + return (declaringClass == null || declaringClass.trim().isEmpty()); + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java index 25d0439d4..89497f00d 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java @@ -16,6 +16,8 @@ public class IastDetectionCategory { Boolean javascriptInjectionEnabled = false; Boolean xpathInjectionEnabled = false; Boolean ssrfEnabled = false; + Boolean unsafeDeserializationEnabled = false; + Boolean insecureReflection = false; @JsonIgnore private String disabledCategoriesCSV; @@ -157,6 +159,14 @@ public void generateDisabledCategoriesCSV() { disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.HTTP_REQUEST); disabledCategoriesCSVBuilder.append(STR_COMMA); } + if (unsafeDeserializationEnabled) { + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.UNSAFE_DESERIALIZATION); + disabledCategoriesCSVBuilder.append(STR_COMMA); + } + if (insecureReflection) { + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.REFLECTION); + disabledCategoriesCSVBuilder.append(STR_COMMA); + } if (disabledCategoriesCSVBuilder.length() > 0) { disabledCategoriesCSVBuilder.deleteCharAt(disabledCategoriesCSVBuilder.length() - 1); } @@ -166,4 +176,20 @@ public void generateDisabledCategoriesCSV() { public String getDisabledCategoriesCSV() { return disabledCategoriesCSV; } + + public Boolean getUnsafeDeserializationEnabled() { + return unsafeDeserializationEnabled; + } + + public void setUnsafeDeserializationEnabled(Boolean unsafeDeserializationEnabled) { + this.unsafeDeserializationEnabled = unsafeDeserializationEnabled; + } + + public Boolean getInsecureReflectionEnabled() { + return insecureReflection; + } + + public void setInsecureReflectionEnabled(Boolean insecureReflection) { + this.insecureReflection = insecureReflection; + } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/ExecutionIDGenerator.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/utils/ExecutionIDGenerator.java similarity index 86% rename from newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/ExecutionIDGenerator.java rename to newrelic-security-api/src/main/java/com/newrelic/api/agent/security/utils/ExecutionIDGenerator.java index 50f6b728a..700521681 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/ExecutionIDGenerator.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/utils/ExecutionIDGenerator.java @@ -1,4 +1,4 @@ -package com.newrelic.agent.security.instrumentator.utils; +package com.newrelic.api.agent.security.utils; import java.util.concurrent.atomic.AtomicLong; diff --git a/settings.gradle b/settings.gradle index 3610728a9..4b18dc8a9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -41,6 +41,7 @@ include 'instrumentation:java-lang' include 'instrumentation:java-io-stream' include 'instrumentation:java-io-inputstream-jdk8' include 'instrumentation:java-io-inputstream-jdk9' +include 'instrumentation:deserialisation' include 'instrumentation:file-operation' include 'instrumentation:servlet-2.4' include 'instrumentation:servlet-5.0' @@ -235,4 +236,5 @@ include 'instrumentation:http4s-ember-server-2.13_0.23' include 'instrumentation:http4s-ember-client-2.13_0.23' include 'instrumentation:http4s-ember-client-2.12_0.23' include 'instrumentation:apache-pekko-http-core-2.13_1' -include 'instrumentation:resin-4' \ No newline at end of file +include 'instrumentation:resin-4' +include 'instrumentation:java-reflection' \ No newline at end of file