Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions its/ruling/src/test/resources/commons-beanutils/java-S9357.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
{
"commons-beanutils:commons-beanutils:src/main/java/org/apache/commons/beanutils2/BeanMap.java": [
74,
83,
92,
101,
110,
119,
128,
137
],
"commons-beanutils:commons-beanutils:src/test/java/org/apache/commons/beanutils2/bugs/Jira509TestCase.java": [
60
]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"org.eclipse.jetty:jetty-project:jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContextState.java": [
144
],
"org.eclipse.jetty:jetty-project:jetty-server/src/main/java/org/eclipse/jetty/server/LowResourceMonitor.java": [
74
],
"org.eclipse.jetty:jetty-project:jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java": [
297
]
}
12 changes: 12 additions & 0 deletions its/ruling/src/test/resources/eclipse-jetty/java-S9357.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
{
"org.eclipse.jetty:jetty-project:jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContextState.java": [
144
],
"org.eclipse.jetty:jetty-project:jetty-server/src/main/java/org/eclipse/jetty/server/LowResourceMonitor.java": [
74
],
"org.eclipse.jetty:jetty-project:jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java": [
297
],
"org.eclipse.jetty:jetty-project:jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java": [
150,
203,
Expand All @@ -18,6 +27,9 @@
"org.eclipse.jetty:jetty-project:jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java": [
285
],
"org.eclipse.jetty:jetty-project:jetty-util/src/main/java/org/eclipse/jetty/util/MemoryUtils.java": [
37
],
"org.eclipse.jetty:jetty-project:jetty-util/src/test/java/org/eclipse/jetty/util/IteratingCallbackTest.java": [
219,
293,
Expand Down
176 changes: 176 additions & 0 deletions its/ruling/src/test/resources/guava/java-S9357.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
{
"com.google.guava:guava:src/com/google/common/base/Converter.java": [
180
],
"com.google.guava:guava:src/com/google/common/base/Optional.java": [
297
],
"com.google.guava:guava:src/com/google/common/base/Splitter.java": [
148,
179,
230,
294
],
"com.google.guava:guava:src/com/google/common/cache/CacheBuilder.java": [
183
],
"com.google.guava:guava:src/com/google/common/cache/LocalCache.java": [
2327,
3547
],
"com.google.guava:guava:src/com/google/common/cache/LongAddables.java": [
38,
45
],
"com.google.guava:guava:src/com/google/common/cache/RemovalListeners.java": [
45,
48
],
"com.google.guava:guava:src/com/google/common/collect/Collections2.java": [
302
],
"com.google.guava:guava:src/com/google/common/collect/FilteredEntryMultimap.java": [
398
],
"com.google.guava:guava:src/com/google/common/collect/Interners.java": [
46
],
"com.google.guava:guava:src/com/google/common/collect/Iterables.java": [
1014
],
"com.google.guava:guava:src/com/google/common/collect/Iterators.java": [
1296
],
"com.google.guava:guava:src/com/google/common/collect/MapConstraints.java": [
227,
485
],
"com.google.guava:guava:src/com/google/common/collect/Maps.java": [
1863,
1874,
1888,
1922,
3098
],
"com.google.guava:guava:src/com/google/common/collect/Multimaps.java": [
519,
1202,
1702
],
"com.google.guava:guava:src/com/google/common/collect/Multisets.java": [
305
],
"com.google.guava:guava:src/com/google/common/collect/MutableClassToInstanceMap.java": [
64
],
"com.google.guava:guava:src/com/google/common/collect/Range.java": [
117,
129
],
"com.google.guava:guava:src/com/google/common/collect/RegularImmutableTable.java": [
114
],
"com.google.guava:guava:src/com/google/common/collect/StandardTable.java": [
721,
794
],
"com.google.guava:guava:src/com/google/common/collect/Tables.java": [
240,
390,
419,
429,
592
],
"com.google.guava:guava:src/com/google/common/collect/TreeBasedTable.java": [
321
],
"com.google.guava:guava:src/com/google/common/escape/Escaper.java": [
90
],
"com.google.guava:guava:src/com/google/common/eventbus/Subscriber.java": [
76
],
"com.google.guava:guava:src/com/google/common/io/CharSource.java": [
442
],
"com.google.guava:guava:src/com/google/common/net/MediaType.java": [
406,
744
],
"com.google.guava:guava:src/com/google/common/reflect/ClassPath.java": [
64
],
"com.google.guava:guava:src/com/google/common/reflect/MutableTypeToInstanceMap.java": [
124
],
"com.google.guava:guava:src/com/google/common/reflect/TypeToken.java": [
701
],
"com.google.guava:guava:src/com/google/common/reflect/Types.java": [
61
],
"com.google.guava:guava:src/com/google/common/util/concurrent/AbstractExecutionThreadService.java": [
45,
50,
145
],
"com.google.guava:guava:src/com/google/common/util/concurrent/AbstractIdleService.java": [
40,
50,
64,
95
],
"com.google.guava:guava:src/com/google/common/util/concurrent/AbstractScheduledService.java": [
205,
210,
232,
304
],
"com.google.guava:guava:src/com/google/common/util/concurrent/AggregateFuture.java": [
138
],
"com.google.guava:guava:src/com/google/common/util/concurrent/AtomicLongMap.java": [
294
],
"com.google.guava:guava:src/com/google/common/util/concurrent/Callables.java": [
44,
94
],
"com.google.guava:guava:src/com/google/common/util/concurrent/Futures.java": [
1168,
1494,
1569,
1662,
1749
],
"com.google.guava:guava:src/com/google/common/util/concurrent/FuturesGetChecked.java": [
253
],
"com.google.guava:guava:src/com/google/common/util/concurrent/JdkFutureAdapters.java": [
160
],
"com.google.guava:guava:src/com/google/common/util/concurrent/MoreExecutors.java": [
204,
754,
856
],
"com.google.guava:guava:src/com/google/common/util/concurrent/Runnables.java": [
31
],
"com.google.guava:guava:src/com/google/common/util/concurrent/ServiceManager.java": [
598
],
"com.google.guava:guava:src/com/google/common/util/concurrent/Striped.java": [
199,
214,
236,
252,
283
],
"com.google.guava:guava:src/com/google/common/util/concurrent/ThreadFactoryBuilder.java": [
161
],
"com.google.guava:guava:src/com/google/common/util/concurrent/WrappingExecutorService.java": [
67
]
}
6 changes: 6 additions & 0 deletions its/ruling/src/test/resources/mall/java-S9357.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"com.macro.mall:mall:mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPromotionServiceImpl.java": [
177,
211
]
}
7 changes: 7 additions & 0 deletions its/ruling/src/test/resources/sonar-server/java-S9357.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
{
"org.sonarsource.sonarqube:sonar-server:src/main/java/org/sonar/server/computation/task/projectanalysis/issue/NewEffortCalculator.java": [
55
],
"org.sonarsource.sonarqube:sonar-server:src/main/java/org/sonar/server/issue/IssuesFinderSort.java": [
89,
142
],
"org.sonarsource.sonarqube:sonar-server:src/test/java/org/sonar/server/computation/task/container/TaskContainerImplTest.java": [
64
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@ <h2>Why is this an issue?</h2>
<p>For AES, the weakest mode is ECB (Electronic Codebook). Repeated blocks of data are encrypted to the same value, making them easy to identify and
reducing the difficulty of recovering the original cleartext.</p>
<p>For RSA, the weakest algorithms are either using it without padding or using the PKCS1v1.5 padding scheme.</p>
<p>For RSA signatures, the generally recommended good practice is to use RSASSA-PSS.</p>
<h3>What is the potential impact?</h3>
<p>The cleartext of an encrypted message might be recoverable. Additionally, it might be possible to modify the cleartext of an encrypted message.</p>
<p>The cleartext of an encrypted message might be recoverable, modifiable, or a signature might be forged.</p>
<p>Below are some real-world scenarios that illustrate possible impacts of an attacker exploiting the vulnerability.</p>
<h4>Theft of sensitive data</h4>
<p>The encrypted message might contain data that is considered sensitive and should not be known to third parties.</p>
<p>By using a weak algorithm the likelihood that an attacker might be able to recover the cleartext drastically increases.</p>
<h4>Additional attack surface</h4>
<p>By modifying the cleartext of the encrypted message it might be possible for an attacker to trigger other vulnerabilities in the code. Encrypted
values are often considered trusted, since under normal circumstances it would not be possible for a third party to modify them.</p>
<h4>Forged signatures</h4>
<p>A weak signature padding scheme without a security proof might allow an attacker to forge a signature that a flawed verifier implementation accepts
as valid, undermining the trust and integrity guarantees signatures are meant to provide.</p>
<h2>How to fix it in Java Cryptography Extension</h2>
<h3>Code examples</h3>
<h4>Noncompliant code example</h4>
Expand Down Expand Up @@ -104,6 +108,10 @@ <h4>For AES: use authenticated encryption modes</h4>
<h4>For RSA: use the OAEP scheme</h4>
<p>The Optimal Asymmetric Encryption Padding scheme (OAEP) adds randomness and a secure hash function that strengthens the regular inner workings of
RSA.</p>
<h4>For RSA signatures: use the RSASSA-PSS scheme</h4>
<p>The Probabilistic Signature Scheme (RSASSA-PSS) uses a randomized encoding and comes with a security proof, whereas the older PKCS#1 v1.5 signature
scheme (RSASSA-PKCS1-v1_5) has none and has repeatedly enabled signature forgery against flawed verifier implementations.</p>
<p>IETF RFC 8017 therefore requires RSASSA-PSS for new applications, in the interest of increased robustness.</p>
<h2>Resources</h2>
<h3>Articles &amp; blog posts</h3>
<ul>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,51 @@
<p>This is an issue when an object’s initialization code can throw an exception and the class is not protected against attacks through cleanup hooks,
which can execute on partially-constructed objects. Protection mechanisms include preventing inheritance, providing empty cleanup implementations that
cannot be overridden, or using construction patterns that prevent direct instantiation.</p>
<p>In Java, these cleanup hooks are called finalizers, and the protection mechanisms specifically refer to declaring the class as <code>final</code>,
or using the factory pattern. Implementing a <code>final</code> empty <code>finalize()</code> method was also a known solution, but
<code>finalize()</code> has been deprecated since Java 9 and is marked for removal.</p>
<h2>Why is this an issue?</h2>
<p>When a constructor throws an exception, you might expect the object construction to fail completely and no reference to the object to exist. However,
finalization or cleanup mechanisms can be exploited to obtain a reference to a partially-constructed object.</p>
<p>Here's how a Finalizer attack works:</p>
<p>When a constructor throws an exception, you might expect the object construction to fail completely and no reference to the object to exist.
However, finalization or cleanup mechanisms can be exploited to obtain a reference to a partially-constructed object.</p>
<p>Heres how a Finalizer attack works:</p>
<ol>
<li>An attacker creates a malicious derived class that overrides the cleanup/finalization method</li>
<li>An attacker creates a malicious derived class that overrides the cleanup/finalization method (the method automatically called by the runtime
when an object is being destroyed)</li>
<li>The attacker attempts to instantiate this derived class</li>
<li>If the parent constructor throws an exception during initialization, the object is not fully constructed</li>
<li>Despite the exception, the garbage collector will eventually call the finalization method on the partially-constructed object</li>
<li>Despite the exception, the memory management system will eventually call the cleanup/finalization method on the partially-constructed
object</li>
<li>The malicious cleanup method can store a reference to the object being finalized, effectively "resurrecting" the broken object</li>
<li>The attacker now has access to an object that bypassed security checks or validation logic in the constructor</li>
</ol>
<p>This vulnerability is particularly dangerous for security-sensitive classes where the constructor performs authentication or authorization checks,
input validation, resource allocation with security constraints, or initialization of security-critical fields.</p>
<p>This vulnerability is particularly dangerous for security-sensitive classes where the constructor performs:</p>
<ul>
<li>Authentication or authorization checks</li>
<li>Input validation</li>
<li>Resource allocation with security constraints</li>
<li>Initialization of security-critical fields</li>
</ul>
<p>If an attacker can obtain a reference to a partially-constructed instance, they may be able to call methods on an object in an inconsistent state,
potentially bypassing security controls.</p>
<h3>What is the potential impact?</h3>
<p>Attacks exploiting cleanup mechanisms for incompletely initialized objects can lead to serious security vulnerabilities:</p>
<ul>
<li><strong>Security bypass</strong>: Attackers can obtain references to objects that failed security checks in their initialization code</li>
<li><strong>Privilege escalation</strong>: Partially-constructed objects may have elevated privileges without proper authorization</li>
<li><strong>Data corruption</strong>: Methods called on partially-initialized objects can corrupt application state</li>
<li><strong>Unauthorized access</strong>: Security-sensitive resources may be accessed through objects that should never have been created</li>
</ul>
<h2>How to fix it</h2>
<p>The simplest solution is to declare the class as <code>final</code>. This prevents attackers from creating malicious subclasses that override the
<code>finalize()</code> method.</p>
<p>However, some frameworks such as Spring or JPA/Hibernate require non-final classes. In such cases, use a <strong>factory method with a private
constructor</strong> to ensure the object is fully validated before any reference is exposed. Since the constructor is private, no malicious subclass
can be created, achieving the same protection as <code>final</code>.</p>
<h3>Noncompliant code example</h3>
<p>This rule targets classes whose constructors can throw exceptions and that are not protected against finalizer attacks. If the class is internal to
your application and never exposed to untrusted code, or if the constructor cannot actually throw, the risk is lower and the finding may be acceptable
as a won’t-fix. A genuine false positive would occur when the constructor is guaranteed not to throw, making the attack path impossible.</p>
<h3>Code examples</h3>
<h4>Noncompliant code example</h4>
<pre data-diff-id="1" data-diff-type="noncompliant">
public class SecuritySensitiveClass {
private final String credentials;
Expand All @@ -35,7 +62,7 @@ <h3>Noncompliant code example</h3>
}
}
</pre>
<h3>Compliant solution</h3>
<h4>Compliant solution</h4>
<pre data-diff-id="1" data-diff-type="compliant">
public final class SecuritySensitiveClass { // Compliant: class is final
private final String credentials;
Expand All @@ -52,16 +79,39 @@ <h3>Compliant solution</h3>
}
}
</pre>
<p>When the class cannot be <code>final</code> because a framework requires subclassing or proxying, use a factory method with a private
constructor:</p>
<pre>
public class SecuritySensitiveClass { // Compliant: constructor is private, instances are created through factory method
private final String credentials;

private SecuritySensitiveClass(String credentials) {
this.credentials = credentials;
}

public static SecuritySensitiveClass create(String credentials) throws AuthenticationException {
if (!isValid(credentials)) {
throw new AuthenticationException("Invalid credentials");
}
return new SecuritySensitiveClass(credentials);
}

private static boolean isValid(String credentials) {
return credentials != null &amp;&amp; credentials.length() &gt; 10;
}
}
</pre>
<h2>Resources</h2>
<h3>Documentation</h3>
<ul>
<li>Oracle Java Documentation - <a href="https://www.oracle.com/java/technologies/javase/seccodeguide.html">Secure Coding Guidelines for Java
SE</a></li>
<li>Java Language Specification - <a
href="https://docs.oracle.com/javase/specs/jls/se17/html/jls-12.html#jls-12.6">Finalization of Class Instances</a></li>
<li>Java Language Specification - <a href="https://docs.oracle.com/javase/specs/jls/se17/html/jls-12.html#jls-12.6">Finalization of Class
Instances</a></li>
</ul>
<h3>Standards</h3>
<ul>
<li>CERT - <a href="https://wiki.sei.cmu.edu/confluence/display/java/OBJ11-J.+Be+wary+of+letting+constructors+throw+exceptions">CERT-OBJ11-J: Be
wary of letting constructors throw exceptions</a></li>
</ul>

Loading
Loading