From ea19c58eaca414c7f8add1b54ccc78a8079df029 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 23 Apr 2025 15:13:08 +0530 Subject: [PATCH 01/13] Bump agent version to 1.7.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 8be8f55a6..1fe2c6d50 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # The agent version. -agentVersion=1.6.1 +agentVersion=1.7.0 jsonVersion=1.2.11 # Updated exposed NR APM API version. nrAPIVersion=8.12.0 From b4068ff7722f647513833e358c2e82e4ae9caf21 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 23 Apr 2025 16:12:53 +0530 Subject: [PATCH 02/13] create gradle build directory if it does not exists --- newrelic-security-agent/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/newrelic-security-agent/build.gradle b/newrelic-security-agent/build.gradle index ddbfe0edc..f96d9bf14 100644 --- a/newrelic-security-agent/build.gradle +++ b/newrelic-security-agent/build.gradle @@ -203,6 +203,9 @@ tasks.register('generate-sbom') { def parsedJson = new JsonSlurper().parseText(req.getInputStream().getText()) try { + if (!project.buildDir.exists()) { + mkdir project.buildDir; + } def reportsDir = Paths.get("$buildDir", "reports") def sbomFile = new File("$buildDir/reports", "SBOM.json") if (Files.exists(reportsDir) || Files.createDirectory(reportsDir)) { From 4ddcdc2580192e7ffe9c967a592aa6eb874fb251 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 23 Apr 2025 16:52:21 +0530 Subject: [PATCH 03/13] Revert "Log level change for debugging" This reverts commit aaa48a6458b3b02aaa95759aaeb8c1f930507000. --- .../src/main/java/com/newrelic/agent/security/AgentConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 547d3627e..9ab68002f 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 @@ -318,7 +318,7 @@ private String applyRequiredLogLevel() { if(value instanceof Boolean) { logLevel = IUtilConstants.OFF; } else { - logLevel = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_LOG_LEVEL, LogLevel.FINEST.name()); + logLevel = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_LOG_LEVEL, IUtilConstants.INFO); } try { From aa47c6c511aa295eff5b44e438c62935560c2202 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 23 Apr 2025 16:54:16 +0530 Subject: [PATCH 04/13] utilise dummy executionId for unit tests --- .../src/main/java/com/newrelic/api/agent/security/Agent.java | 2 ++ 1 file changed, 2 insertions(+) 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 1c46b4f66..3bbc74aec 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 @@ -85,6 +85,8 @@ public void registerOperation(AbstractOperation operation) { return; } operation.setApiID(apiId); + String executionId = "dummy-exec-id"; + operation.setExecutionId(executionId); operation.setStartTime(Instant.now().toEpochMilli()); StackTraceElement[] trace = Thread.currentThread().getStackTrace(); operation.setStackTrace(Arrays.copyOfRange(trace, 1, trace.length)); From 22ca697b868b7eb9dac65c53f57e2cea1ba45eef Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 23 Apr 2025 18:39:10 +0530 Subject: [PATCH 05/13] fix post-processing in jersey support --- .../jersey2/ContainerResponse_Instrumentation.java | 2 +- .../jersey2/ContainerResponse_Instrumentation.java | 2 +- .../jersey2/ContainerResponse_Instrumentation.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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 ff327152a..4f4263940 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 @@ -44,7 +44,7 @@ public abstract class ContainerResponse_Instrumentation { public void close() { boolean isLockAcquired = false; try { - isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SERVLET_GET_IS_OPERATION_LOCK); + isLockAcquired = GenericHelper.acquireLockIfPossible(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/ContainerResponse_Instrumentation.java b/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java index b31cdb629..a39c776f1 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 @@ -43,7 +43,7 @@ public abstract class ContainerResponse_Instrumentation { public void close() { boolean isLockAcquired = false; try { - isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SERVLET_GET_IS_OPERATION_LOCK); + isLockAcquired = GenericHelper.acquireLockIfPossible(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/ContainerResponse_Instrumentation.java b/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java index b31cdb629..a39c776f1 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 @@ -43,7 +43,7 @@ public abstract class ContainerResponse_Instrumentation { public void close() { boolean isLockAcquired = false; try { - isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SERVLET_GET_IS_OPERATION_LOCK); + isLockAcquired = GenericHelper.acquireLockIfPossible(SERVLET_GET_IS_OPERATION_LOCK); if(isLockAcquired && GenericHelper.isLockAcquired(HttpRequestHelper.getNrSecCustomAttribForPostProcessing())) { HttpRequestHelper.postProcessSecurityHook(this.getClass().getName(), getWrappedMessageContext()); } From 539f04800e6ce53f52d0baa0793b9dd6415cb3dd Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 23 Apr 2025 19:14:54 +0530 Subject: [PATCH 06/13] Fix unit tests failing for secure cookie operation --- .../src/main/java/com/newrelic/api/agent/security/Agent.java | 4 ++++ 1 file changed, 4 insertions(+) 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 3bbc74aec..edfccade7 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 @@ -8,6 +8,7 @@ import com.newrelic.api.agent.security.schema.ServerConnectionConfiguration; import com.newrelic.api.agent.security.schema.operation.FileIntegrityOperation; import com.newrelic.api.agent.security.schema.operation.FileOperation; +import com.newrelic.api.agent.security.schema.operation.SecureCookieOperationSet; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import com.newrelic.api.agent.security.schema.policy.IastDetectionCategory; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -95,6 +96,9 @@ public void registerOperation(AbstractOperation operation) { @Override public void registerExitEvent(AbstractOperation operation) { + if (operation instanceof SecureCookieOperationSet) { + this.getSecurityMetaData().getCustomAttribute(OPERATIONS, List.class).add(operation); + } this.getSecurityMetaData().getCustomAttribute(EXIT_OPERATIONS, List.class).add(operation); } From b8075b0ac3c5d8d9cabf0d1ae33b33432eb87944 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 23 Apr 2025 21:15:49 +0530 Subject: [PATCH 07/13] remove final from weave class to fix FIELD_FINAL_MISMATCH --- .../domain/response/HttpResponseBuilder_Instrumentation.java | 4 ++-- .../domain/response/HttpResponseBuilder_Instrumentation.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 2bd4cb9e0..d82f70731 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 final ResponseStatus responseStatus = Weaver.callOriginal(); - private final HttpEntity body = Weaver.callOriginal(); + private ResponseStatus responseStatus = Weaver.callOriginal(); + private HttpEntity body = Weaver.callOriginal(); public HttpResponse build() { HttpResponse response = Weaver.callOriginal(); 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 ef15c71b3..b660d0e80 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 final ResponseStatus responseStatus = Weaver.callOriginal(); - private final HttpEntity body = Weaver.callOriginal(); + private ResponseStatus responseStatus = Weaver.callOriginal(); + private HttpEntity body = Weaver.callOriginal(); public HttpResponse build() { HttpResponse response = Weaver.callOriginal(); From 1fc40388f240f372553f2d266fbba1b3c3b83653 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 23 Apr 2025 21:53:10 +0530 Subject: [PATCH 08/13] Add exit event registration for secure cookie low severity events --- .../http/HttpServletResponse_Instrumentation.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/http/HttpServletResponse_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/http/HttpServletResponse_Instrumentation.java index 3537ce958..931617e8e 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/http/HttpServletResponse_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/http/HttpServletResponse_Instrumentation.java @@ -37,6 +37,9 @@ public void addCookie(Cookie cookie){ releaseLock(cookie.hashCode()); } } + if (isOwaspHookEnabled) { + registerExitOperation(isLockAcquired, operation); + } } private AbstractOperation preprocessSecurityHook(Cookie cookie, String className, String methodName) { @@ -78,6 +81,17 @@ private AbstractOperation preprocessSecurityHook(Cookie cookie, String className return null; } + private static void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { + try { + if (operation == null || !isProcessingAllowed || !NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty()) { + return; + } + NewRelicSecurity.getAgent().registerExitEvent(operation); + } catch (Throwable e) { + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, HttpServletHelper.SERVLET_2_4, e.getMessage()), e, HttpServletResponse_Instrumentation.class.getName()); + } + } + private void releaseLock(int hashCode) { GenericHelper.releaseLock(ServletHelper.NR_SEC_HTTP_SERVLET_RESPONSE_ATTRIB_NAME, hashCode); } From 65de8072273a70365a0f8230379f59f9acbc5cd9 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 23 Apr 2025 22:00:26 +0530 Subject: [PATCH 09/13] update unit tests assertions --- .../security/instrumentation/servlet24/HttpSessionTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpSessionTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpSessionTest.java index a5fe5e80d..b5f9a3840 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpSessionTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpSessionTest.java @@ -35,7 +35,6 @@ public void testSessionSetAttribute() throws IOException, URISyntaxException { SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); Assert.assertTrue("No operations detected", operations.size() > 0); - Assert.assertTrue("Unexpected operation count detected", operations.size() == 2 || operations.size() == 3); TrustBoundaryOperation targetOperation = null; int i=0; for (AbstractOperation operation : operations) { @@ -65,7 +64,6 @@ public void testSessionPutValue() throws IOException, URISyntaxException { SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); Assert.assertFalse(operations.isEmpty()); - Assert.assertTrue("Unexpected operation count detected", operations.size() == 2 || operations.size() == 3); TrustBoundaryOperation targetOperation = null; for (AbstractOperation operation : operations) { if (operation instanceof TrustBoundaryOperation) @@ -86,7 +84,6 @@ public void testAddCookie() throws IOException, URISyntaxException { SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); Assert.assertTrue("No operations detected", operations.size() > 0); - Assert.assertTrue("Unexpected operation count detected", operations.size() == 1 || operations.size() == 2); SecureCookieOperationSet targetOperation = null; targetOperation = verifySecureCookieOp(operations); From bc52ff90521a2f0af762b71c4da9853abba6c7b4 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 24 Apr 2025 10:03:44 +0530 Subject: [PATCH 10/13] Disable java-reflection & deserialization by default (Please note: it can be enabled via config) --- instrumentation-security/deserialisation/build.gradle | 2 +- instrumentation-security/java-reflection/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/instrumentation-security/deserialisation/build.gradle b/instrumentation-security/deserialisation/build.gradle index 40fb3a3e9..303d8cb11 100644 --- a/instrumentation-security/deserialisation/build.gradle +++ b/instrumentation-security/deserialisation/build.gradle @@ -8,7 +8,7 @@ dependencies { jar { - manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.deserialisation' } + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.deserialisation', 'Enabled': 'false' } } verifyInstrumentation { diff --git a/instrumentation-security/java-reflection/build.gradle b/instrumentation-security/java-reflection/build.gradle index d41d6b414..c62f5cc26 100644 --- a/instrumentation-security/java-reflection/build.gradle +++ b/instrumentation-security/java-reflection/build.gradle @@ -8,7 +8,7 @@ dependencies { jar { - manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.java-reflection' } + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.java-reflection', 'Enabled': 'false' } } verifyInstrumentation { From fb7bcaf07ffa57919d1bf95ad0ded6c9124d2a94 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 24 Apr 2025 21:04:42 +0530 Subject: [PATCH 11/13] fix typo --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 2f50c7c7f..6b8cf1508 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,7 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.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. +- [PR-372](https://github.com/newrelic/csec-java-agent/pull/372) **Repeat IAST Request Replay Commands**: Reconfigured logic to repeat IAST control commands until the endpoint is confirmed. ## [1.6.1] - 2025-3-1 From 87133bc94fa4e4b5fc0a6682bdab54fc1d0f545e Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 25 Apr 2025 17:30:51 +0530 Subject: [PATCH 12/13] Changelogs add note for reflection --- Changelog.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 6b8cf1508..14e7ceda6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,7 +4,7 @@ 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 +## [1.7.0] - 2025-4-25 ### 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. @@ -18,6 +18,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixes - [PR-372](https://github.com/newrelic/csec-java-agent/pull/372) **Repeat IAST Request Replay Commands**: Reconfigured logic to repeat IAST control commands until the endpoint is confirmed. +### Note +- The instrumentation for the module `com.newrelic.instrumentation.security.java-reflection` is disabled by default. This is due to its impact on CPU utilization, which can significantly increase when the module is active. +- **Action Required**: To detect unsafe reflection vulnerabilities effectively, enable the `com.newrelic.instrumentation.security.java-reflection` module. ## [1.6.1] - 2025-3-1 ### Adds From 404a672204c5a3c9871ac0e90b9db41d41b441a8 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 25 Apr 2025 17:37:00 +0530 Subject: [PATCH 13/13] Enable deserialization by default --- instrumentation-security/deserialisation/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation-security/deserialisation/build.gradle b/instrumentation-security/deserialisation/build.gradle index 303d8cb11..40fb3a3e9 100644 --- a/instrumentation-security/deserialisation/build.gradle +++ b/instrumentation-security/deserialisation/build.gradle @@ -8,7 +8,7 @@ dependencies { jar { - manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.deserialisation', 'Enabled': 'false' } + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.deserialisation' } } verifyInstrumentation {