#java

Rulesets (30)

Semgrep

Default ruleset for Java, curated by Semgrep.

Gitlab

Leverage all Gitlab provided rules with the gitlab rulepack.

Rules (371)

profile photo of returntocorpreturntocorp

DOCTYPE declarations are enabled for this SAXParserFactory. This is vulnerable to XML external entity attacks. Disable this by setting the feature `http://apache.org/xml/features/disallow-doctype-decl` to true. Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. This can be done by setting the features `http://xml.org/sax/features/external-general-entities` and `http://xml.org/sax/features/external-parameter-entities` to false. NOTE - The previous links are not meant to be clicked. They are the literal config key values that are supposed to be used to disable these features. For more information, see https://semgrep.dev/docs/cheat-sheets/java-xxe/#3a-documentbuilderfactory.

profile photo of returntocorpreturntocorp

Detected a method annotated with 'RequestMapping' that does not specify the HTTP method. CSRF protections are not enabled for GET, HEAD, TRACE, or OPTIONS, and by default all HTTP methods are allowed when the HTTP method is not explicitly specified. This means that a method that performs state changes could be vulnerable to CSRF attacks. To mitigate, add the 'method' field and specify the HTTP method (such as 'RequestMethod.POST').

No author info

Insufficient permissions to view rule definition. This rule is only visible to logged in users. Log in to see this rule.

profile photo of MobSFMobSF

The App may use weak IVs like "0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00" or "0x01,0x02,0x03,0x04,0x05,0x06,0x07". Not using a random IV makes the resulting ciphertext much more predictable and susceptible to a dictionary attack.

profile photo of MobSFMobSF

Found object deserialization using ObjectInputStream. Deserializing entire Java objects is dangerous because malicious actors can create Java object streams with unintended consequences. Ensure that the objects being deserialized are not user-controlled. Consider using HMACs to sign the data stream to make sure it is not tampered with, or consider only transmitting object fields and populating a new object.

profile photo of MobSFMobSF

XML external entities are not explicitly disabled for this XMLInputFactory. This could be vulnerable to XML external entity vulnerabilities. Explicitly disable external entities by setting "javax.xml.stream.isSupportingExternalEntities" to false.

profile photo of returntocorpreturntocorp

When using Jackson to marshall/unmarshall JSON to Java objects, enabling default typing is dangerous and can lead to RCE. If an attacker can control `$JSON` it might be possible to provide a malicious JSON which can be used to exploit unsecure deserialization. In order to prevent this issue, avoid to enable default typing (globally or by using "Per-class" annotations) and avoid using `Object` and other dangerous types for member variable declaration which creating classes for Jackson based deserialization.

No author info

Insufficient permissions to view rule definition. This rule is only visible to logged in users. Log in to see this rule.

profile photo of returntocorpreturntocorp

Use of AES with ECB mode detected. ECB doesn't provide message confidentiality and is not semantically secure so should not be used. Instead, use a strong, secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.

profile photo of returntocorpreturntocorp

Use of Blowfish was detected. Blowfish uses a 64-bit block size that makes it vulnerable to birthday attacks, and is therefore considered non-compliant. Instead, use a strong, secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.

profile photo of returntocorpreturntocorp

Use of AES with no settings detected. By default, java.crypto.Cipher uses ECB mode. ECB doesn't provide message confidentiality and is not semantically secure so should not be used. Instead, use a strong, secure cipher: java.crypto.Cipher.getInstance("AES/CBC/PKCS7PADDING"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.

profile photo of returntocorpreturntocorp

Use of RC2 was detected. RC2 is vulnerable to related-key attacks, and is therefore considered non-compliant. Instead, use a strong, secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.

profile photo of returntocorpreturntocorp

Use of RC4 was detected. RC4 is vulnerable to several attacks, including stream cipher attacks and bit flipping attacks. Instead, use a strong, secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.

profile photo of returntocorpreturntocorp

Detected use of the functions `Math.random()` or `java.util.Random()`. These are both not cryptographically strong random number generators (RNGs). If you are using these RNGs to create passwords or secret tokens, use `java.security.SecureRandom` instead.

profile photo of returntocorpreturntocorp

Detected non-constant data passed into an LDAP query. If this data can be controlled by an external user, this is an LDAP injection. Ensure data passed to an LDAP query is not controllable; or properly sanitize the data.

profile photo of returntocorpreturntocorp

It looks like MD5 is used as a password hash. MD5 is not considered a secure password hash because it can be cracked by an attacker in a short amount of time. Use a suitable password hashing function such as PBKDF2 or bcrypt. You can use `javax.crypto.SecretKeyFactory` with `SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")` or, if using Spring, `org.springframework.security.crypto.bcrypt`.

profile photo of returntocorpreturntocorp

Found object deserialization using ObjectInputStream. Deserializing entire Java objects is dangerous because malicious actors can create Java object streams with unintended consequences. Ensure that the objects being deserialized are not user-controlled. If this must be done, consider using HMACs to sign the data stream to make sure it is not tampered with, or consider only transmitting object fields and populating a new object.

profile photo of returntocorpreturntocorp

Detected file permissions that are overly permissive (read, write, and execute). It is generally a bad practices to set overly permissive file permission such as read+write+exec for all users. If the file affected is a configuration, a binary, a script or sensitive data, it can lead to privilege escalation or information leakage. Instead, follow the principle of least privilege and give users only the permissions they need.

profile photo of returntocorpreturntocorp

https://find-sec-bugs.github.io/bugs.htm#PERMISSIVE_CORS Permissive CORS policy will allow a malicious application to communicate with the victim application in an inappropriate way, leading to spoofing, data theft, relay and other attacks.

profile photo of returntocorpreturntocorp

Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.

profile photo of returntocorpreturntocorp

Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.

profile photo of returntocorpreturntocorp

Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.

profile photo of returntocorpreturntocorp

Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.

profile photo of returntocorpreturntocorp

Detected input from a HTTPServletRequest going into a XPath evaluate or compile command. This could lead to xpath injection if variables passed into the evaluate or compile commands are not properly sanitized. Xpath injection could lead to unauthorized access to sensitive information in XML documents. Instead, thoroughly sanitize user input or use parameterized xpath queries if you can.

profile photo of returntocorpreturntocorp

If an attacker can supply values that the application then uses to determine which class to instantiate or which method to invoke, the potential exists for the attacker to create control flow paths through the application that were not intended by the application developers. This attack vector may allow the attacker to bypass authentication or access control checks or otherwise cause the application to behave in an unexpected manner.

profile photo of returntocorpreturntocorp

XMLDecoder should not be used to parse untrusted data. Deserializing user input can lead to arbitrary code execution. Use an alternative and explicitly disable external entities. See https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html for alternatives and vulnerability prevention.

profile photo of returntocorpreturntocorp

It looks like you're using an implementation of XSSRequestWrapper from dzone. (https://www.javacodegeeks.com/2012/07/anti-cross-site-scripting-xss-filter.html) The XSS filtering in this code is not secure and can be bypassed by malicious actors. It is recommended to use a stack that automatically escapes in your view or templates instead of filtering yourself.

profile photo of returntocorpreturntocorp

DOCTYPE declarations are enabled for $DBFACTORY. Without prohibiting external entity declarations, this is vulnerable to XML external entity attacks. Disable this by setting the feature "http://apache.org/xml/features/disallow-doctype-decl" to true. Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. This can be done by setting the features "http://xml.org/sax/features/external-general-entities" and "http://xml.org/sax/features/external-parameter-entities" to false.

profile photo of returntocorpreturntocorp

Detected non-constant data passed into a NoSQL query using the 'where' evaluation operator. If this data can be controlled by an external user, this is a NoSQL injection. Ensure data passed to the NoSQL query is not user controllable, or properly sanitize the data. Ideally, avoid using the 'where' operator at all and instead use the helper methods provided by com.mongodb.client.model.Filters with comparative operators such as eq, ne, lt, gt, etc.

profile photo of returntocorpreturntocorp

This code contains bidirectional (bidi) characters. While this is useful for support of right-to-left languages such as Arabic or Hebrew, it can also be used to trick language parsers into executing code in a manner that is different from how it is displayed in code editing and review tools. If this is not what you were expecting, please review this code in an editor that can reveal hidden Unicode characters.

profile photo of returntocorpreturntocorp

Detected user input flowing into a manually constructed HTML string. You may be accidentally bypassing secure methods of rendering HTML by manually constructing HTML and this could create a cross-site scripting vulnerability, which could let attackers steal sensitive user data. To be sure this is safe, check that the HTML is rendered safely. You can use the OWASP ESAPI encoder if you must render user data.

profile photo of returntocorpreturntocorp

Detected user input entering a method which executes a system command. This could result in a command injection vulnerability, which allows an attacker to inject an arbitrary system command onto the server. The attacker could download malware onto or steal data from the server. Instead, use ProcessBuilder, separating the command into individual arguments, like this: `new ProcessBuilder("ls", "-al", targetDirectory)`. Further, make sure you hardcode or allowlist the actual command so that attackers can't run arbitrary commands.

profile photo of returntocorpreturntocorp

Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.

profile photo of returntocorpreturntocorp

Detected SQL statement that is tainted by `$EVENT` object. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use parameterized SQL queries or properly sanitize user input instead.

profile photo of returntocorpreturntocorp

Detected SHA1 hash algorithm which is considered insecure. SHA1 is not collision resistant and is therefore not suitable as a cryptographic signature. Instead, use PBKDF2 for password hashing or SHA256 or SHA512 for other hash function applications.

profile photo of returntocorpreturntocorp

Marking code as privileged enables a piece of trusted code to temporarily enable access to more resources than are available directly to the code that called it. Be very careful in your use of the privileged construct, and always remember to make the privileged code section as small as possible.

No author info

HTTP Response Splitting is a vulnerability where Carriage Return (CR `\r`) and Line Feed (LF `\n`) characters are introduced into an HTTP header from user-supplied input. By injecting the `\r\n` character sequence, an adversary could potentially modify how the response is interpreted by the client or any downstream caching services. This could allow an adversary to poison the cache data or execute Cross-Site Scripting (XSS) attacks. Some Java application servers such as [Apache Tomcat](https://tomcat.apache.org/) will disallow `\r\n` characters from being set in cookies. If your application server does not automatically provide this functionality, user-supplied input that is used in cookie keys or values must be validated. Example of validating cookies to only allow valid characters: ``` // throws an IllegalArgumentException if the provided value contains invalid characters public void validateRfc6265CookieValue(String value) throws IllegalArgumentException { char[] chars = value.toCharArray(); // iterate over every character for (int i = 0; i < chars.length; i++) { char c = chars[i]; // check for any characters below 0x21 as well as: '"' ',' ';' '\' and 0x7f. if (c < 0x21 || c == '"' || c == ',' || c == ';' || c == '\\' || c == 0x7f) { throw new IllegalArgumentException("Invalid character in cookie detected: {0}".format(Integer.toString(c))); } } } ``` Alternatively, you could use a string escape package such as [Apache Commons Text](https://commons.apache.org/proper/commons-text/) to escape the input: ``` public String escapeValue(String value) { return StringEscapeUtils.escapeJava(value); } ``` For more information on response splitting attacks see OWASP: https://owasp.org/www-community/attacks/HTTP_Response_Splitting

No author info

HTTP Response Splitting is a vulnerability where Carriage Return (CR `\r`) and Line Feed (LF `\n`) characters are introduced into an HTTP header from user-supplied input. By injecting the `\r\n` character sequence, an adversary could potentially modify how the response is interpreted by the client or any down stream caching services. This could allow an adversary to poison the cache data or execute Cross-Site Scripting (XSS) attacks. Some Java application servers such as [Apache Tomcat](https://tomcat.apache.org/) will automatically encode characters from being set in response headers as a space `0x20` character. If your application server does not automatically provide this functionality, user-supplied input that is used in header keys or values must be validated. Example of validating headers to only allow valid characters: ``` // throws an IllegalArgumentException if the provided value contains invalid characters public void validateHeader(String value) throws IllegalArgumentException { char[] chars = value.toCharArray(); // iterate over every character for (int i = 0; i < chars.length; i++) { char c = chars[i]; // check for any characters below 0x21 as well as: '"' ',' ';' '\' and 0x7f. if (c < 0x21 || c == '"' || c == ',' || c == ';' || c == '\\' || c == 0x7f) { throw new IllegalArgumentException("Invalid character in cookie detected: {0}".format(Integer.toString(c))); } } } ``` Alternatively, you could use a string escape package such as [Apache Commons Text](https://commons.apache.org/proper/commons-text/) to escape the input: ``` public String escapeValue(String value) { return StringEscapeUtils.escapeJava(value); } ``` For more information on response splitting attacks see OWASP: https://owasp.org/www-community/attacks/HTTP_Response_Splitting

No author info

This application potentially allows user-supplied input into the value of the `Access-Control-Allow-Origin` response header. This header is part of the [Cross-Origin Resource Sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) CORS specification. By allowing user input to specify which domains can communicate with this server, an adversary could exploit a weakness in this server to force clients to send credentials (such as session identifiers) to the adversary's server. For the above attack to work, the application would need to suffer from an additional vulnerability, such as Cross-Site Scripting (XSS). To remediate this issue, do not use user-supplied information when calling `HttpServletResponse.setHeader` or `HttpServletResponse.addHeader` for the `Access-Control-Allow-Origin` header's value. Instead, hardcode the allowed domain(s) and reference them in a lookup table: Example allowing dynamic but safe domains in `Access-Control-Allow-Origin`: ``` // this data should be in the class constructor or taken from a trusted datasource Map<String, String> allowedDomains = new HashMap(); allowedDomains.put("sub1", "sub1.example.com"); allowedDomains.put("sub2", "sub2.example.com"); // extract the allowedDomain parameters value as a key to look up which domain to provide via the allowedDomains map // if not found, sets sub1 as the default String headerValue = allowedDomains.getOrDefault(request.getParameter("allowedDomain"), allowedDomains.get("sub1")); // add the header with our trusted sub1.example.com or sub2.example.com domains. response.addHeader("Access-Control-Allow-Origin", headerValue); } ``` For more information on `Access-Control-Allow-Origin` see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin

No author info

The Blowfish encryption algorithm was meant as a drop-in replacement for DES and was created in 1993. Smaller key sizes may make the ciphertext vulnerable to [birthday attacks](https://en.wikipedia.org/wiki/Birthday_attack). While no known attacks against Blowfish exist, it should never be used to encrypt files over 4GB in size. If possible consider using AES as the instance of `KeyGenerator` instead of Blowfish. To remediate the small key size, pass a value such as 256 to the `KeyGenerator.init(keySize)` method. Example setting a larger key size and changing to `KeyGenerator` to AES: ``` public static void aesKeyGenerator() throws java.security.NoSuchAlgorithmException { // Use the AES algorithm for key generation KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); // Set the key size here keyGenerator.init(256); // get the raw bytes of the key byte[] key = keyGenerator.generateKey().getEncoded(); // pass the key bytes to create a SecretKeySpec SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); } ``` Example setting a larger key size for Blowfish: ``` public static void blowFishKeyGenerator() throws java.security.NoSuchAlgorithmException { // Use the Blowfish algorithm for key generation KeyGenerator keyGenerator = KeyGenerator.getInstance("Blowfish"); // Set the key size here keyGenerator.init(256); // get the raw bytes of the key byte[] key = keyGenerator.generateKey().getEncoded(); // pass the key bytes to create a SecretKeySpec SecretKeySpec secretKeySpec = new SecretKeySpec(key, "Blowfish"); } ``` For more information on Java Cryptography see: https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html

No author info

DES, TripleDES and RC2 are all considered broken or insecure cryptographic algorithms. Newer algorithms apply message integrity to validate ciphertext has not been tampered with. Consider using `ChaCha20Poly1305` instead as it is easier and faster than the alternatives such as `AES-256-GCM`. For older applications that don't have support for `ChaCha20Poly1305`, `AES-256-GCM` is recommended, however it has many drawbacks: - Slower than `ChaCha20Poly1305`. - Catastrophic failure if nonce values are reused. Example using `ChaCha20Poly1305`: ``` public encrypt() throws Exception { chaChaEncryption("Secret text to encrypt".getBytes(StandardCharsets.UTF_8)); } public SecureRandom getSecureRandomDRBG() throws NoSuchAlgorithmException { // Use DRBG according to http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf return SecureRandom.getInstance("DRBG", // Security strength in bits (default is 128) DrbgParameters.instantiation(256, // Set prediction resistance and re-seeding DrbgParameters.Capability.PR_AND_RESEED, // Set the personalization string (optional, not necessary) "some_personalization_string".getBytes() ) ); } public Cipher getChaCha20Poly1305(int mode, byte[] ivKey, byte[] secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Get a DRBG random number generator instance SecureRandom random = getSecureRandomDRBG(); // Create a ChaCha20-Poly1305 cipher instance Cipher chaChaCipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); // Create our parameterSpec using our ivKey AlgorithmParameterSpec parameterSpec = new IvParameterSpec(ivKey); // Create a SecretKeySpec using our secretKey SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "ChaCha20"); // Initialize and return the cipher for the provided mode chaChaCipher.init(mode, secretKeySpec, parameterSpec, random); return chaChaCipher; } public void chaChaEncryption(byte[] plainText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Get a DRBG random number generator instance SecureRandom random = getSecureRandomDRBG(); // Create secretKey byte[] secretKey = new byte[32]; random.nextBytes(secretKey); // Create an IV Key byte[] ivKey = new byte[12]; random.nextBytes(ivKey); // Create a chaCha encryption cipher instance Cipher chaChaEncryptor = getChaCha20Poly1305(Cipher.ENCRYPT_MODE, ivKey, secretKey); // Encrypt the text using ChaCha20Poly1305 byte[] cipherText = null; try { cipherText = chaChaEncryptor.doFinal(plainText); } catch (IllegalBlockSizeException | BadPaddingException e) { System.out.println("failed to encrypt text"); return; } System.out.println("encrypted: " + Base64.getEncoder().encodeToString(cipherText)); // Create a chaCha decryption cipher instance Cipher chaChaDecryptor = getChaCha20Poly1305(Cipher.DECRYPT_MODE, ivKey, secretKey); // Decrypt the text byte[] decryptedText = null; try { decryptedText = chaChaDecryptor.doFinal(cipherText); } catch (IllegalBlockSizeException | BadPaddingException e) { System.out.println("failed to decrypt text"); return; } System.out.println("decrypted: " + new String(decryptedText, StandardCharsets.UTF_8)); } ``` For more information on Java Cryptography see: https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html

No author info

DES, TripleDES and RC2 are all considered broken or insecure cryptographic algorithms. Newer algorithms apply message integrity to validate ciphertext has not been tampered with. Consider using `ChaCha20Poly1305` instead as it is easier and faster than the alternatives such as `AES-256-GCM`. For older applications that don't have support for `ChaCha20Poly1305`, `AES-256-GCM` is recommended, however it has many drawbacks: - Slower than `ChaCha20Poly1305`. - Catastrophic failure if nonce values are reused. Example using `ChaCha20Poly1305`: ``` public encrypt() throws Exception { chaChaEncryption("Secret text to encrypt".getBytes(StandardCharsets.UTF_8)); } public SecureRandom getSecureRandomDRBG() throws NoSuchAlgorithmException { // Use DRBG according to http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf return SecureRandom.getInstance("DRBG", // Security strength in bits (default is 128) DrbgParameters.instantiation(256, // Set prediction resistance and re-seeding DrbgParameters.Capability.PR_AND_RESEED, // Set the personalization string (optional, not necessary) "some_personalization_string".getBytes() ) ); } public Cipher getChaCha20Poly1305(int mode, byte[] nonceKey, byte[] secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Get a DRBG random number generator instance SecureRandom random = getSecureRandomDRBG(); // Create a ChaCha20-Poly1305 cipher instance Cipher chaChaCipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); // Create our parameterSpec using our nonceKey AlgorithmParameterSpec parameterSpec = new IvParameterSpec(nonceKey); // Create a SecretKeySpec using our secretKey SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "ChaCha20"); // Initialize and return the cipher for the provided mode chaChaCipher.init(mode, secretKeySpec, parameterSpec, random); return chaChaCipher; } public void chaChaEncryption(byte[] plainText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Get a DRBG random number generator instance SecureRandom random = getSecureRandomDRBG(); // Create secretKey byte[] secretKey = new byte[32]; random.nextBytes(secretKey); // Create an IV nonceKey byte[] nonceKey = new byte[12]; random.nextBytes(nonceKey); // Create a chaCha encryption cipher instance Cipher chaChaEncryptor = getChaCha20Poly1305(Cipher.ENCRYPT_MODE, nonceKey, secretKey); // Encrypt the text using ChaCha20Poly1305 byte[] cipherText = null; try { cipherText = chaChaEncryptor.doFinal(plainText); } catch (IllegalBlockSizeException | BadPaddingException e) { System.out.println("failed to encrypt text"); return; } System.out.println("encrypted: " + Base64.getEncoder().encodeToString(cipherText)); // Create a chaCha decryption cipher instance Cipher chaChaDecryptor = getChaCha20Poly1305(Cipher.DECRYPT_MODE, nonceKey, secretKey); // Decrypt the text byte[] decryptedText = null; try { decryptedText = chaChaDecryptor.doFinal(cipherText); } catch (IllegalBlockSizeException | BadPaddingException e) { System.out.println("failed to decrypt text"); return; } System.out.println("decrypted: " + new String(decryptedText, StandardCharsets.UTF_8)); } ``` For more information on Java Cryptography see: https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html

No author info

Cryptographic algorithms provide many different modes of operation, only some of which provide message integrity. Without message integrity it could be possible for an adversary to attempt to tamper with the ciphertext which could lead to compromising the encryption key. Newer algorithms apply message integrity to validate ciphertext has not been tampered with. Instead of using an algorithm that requires configuring a cipher mode, an algorithm that has built-in message integrity should be used. Consider using `ChaCha20Poly1305` or `AES-256-GCM` instead. For older applications that don't have support for `ChaCha20Poly1305`, `AES-256-GCM` is recommended, however it has many drawbacks: - Slower than `ChaCha20Poly1305`. - Catastrophic failure if nonce values are reused. Example using `ChaCha20Poly1305`: ``` public encrypt() throws Exception { chaChaEncryption("Secret text to encrypt".getBytes(StandardCharsets.UTF_8)); } public SecureRandom getSecureRandomDRBG() throws NoSuchAlgorithmException { // Use DRBG according to http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf return SecureRandom.getInstance("DRBG", // Security strength in bits (default is 128) DrbgParameters.instantiation(256, // Set prediction resistance and re-seeding DrbgParameters.Capability.PR_AND_RESEED, // Set the personalization string (optional, not necessary) "some_personalization_string".getBytes() ) ); } public Cipher getChaCha20Poly1305(int mode, byte[] ivKey, byte[] secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Get a DRBG random number generator instance SecureRandom random = getSecureRandomDRBG(); // Create a ChaCha20-Poly1305 cipher instance Cipher chaChaCipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); // Create our parameterSpec using our ivKey AlgorithmParameterSpec parameterSpec = new IvParameterSpec(ivKey); // Create a SecretKeySpec using our secretKey SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "ChaCha20"); // Initialize and return the cipher for the provided mode chaChaCipher.init(mode, secretKeySpec, parameterSpec, random); return chaChaCipher; } public void chaChaEncryption(byte[] plainText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Get a DRBG random number generator instance SecureRandom random = getSecureRandomDRBG(); // Create secretKey byte[] secretKey = new byte[32]; random.nextBytes(secretKey); // Create an IV Key byte[] ivKey = new byte[12]; random.nextBytes(ivKey); // Create a chaCha encryption cipher instance Cipher chaChaEncryptor = getChaCha20Poly1305(Cipher.ENCRYPT_MODE, ivKey, secretKey); // Encrypt the text using ChaCha20Poly1305 byte[] cipherText = null; try { cipherText = chaChaEncryptor.doFinal(plainText); } catch (IllegalBlockSizeException | BadPaddingException e) { System.out.println("failed to encrypt text"); return; } System.out.println("encrypted: " + Base64.getEncoder().encodeToString(cipherText)); // Create a chaCha decryption cipher instance Cipher chaChaDecryptor = getChaCha20Poly1305(Cipher.DECRYPT_MODE, ivKey, secretKey); // Decrypt the text byte[] decryptedText = null; try { decryptedText = chaChaDecryptor.doFinal(cipherText); } catch (IllegalBlockSizeException | BadPaddingException e) { System.out.println("failed to decrypt text"); return; } System.out.println("decrypted: " + new String(decryptedText, StandardCharsets.UTF_8)); } ``` For more information on Java Cryptography see: https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html

No author info

Cryptographic algorithms provide many different modes of operation, only some of which provide message integrity. Without message integrity it could be possible for an adversary to attempt to tamper with the ciphertext which could lead to compromising the encryption key. Newer algorithms apply message integrity to validate ciphertext has not been tampered with. Instead of using an algorithm that requires configuring a cipher mode, an algorithm that has built-in message integrity should be used. Consider using `ChaCha20Poly1305` or `AES-256-GCM` instead. For older applications that don't have support for `ChaCha20Poly1305`, `AES-256-GCM` is recommended, however it has many drawbacks: - Slower than `ChaCha20Poly1305`. - Catastrophic failure if nonce values are reused. Example using `ChaCha20Poly1305`: ``` public encrypt() throws Exception { chaChaEncryption("Secret text to encrypt".getBytes(StandardCharsets.UTF_8)); } public SecureRandom getSecureRandomDRBG() throws NoSuchAlgorithmException { // Use DRBG according to http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf return SecureRandom.getInstance("DRBG", // Security strength in bits (default is 128) DrbgParameters.instantiation(256, // Set prediction resistance and re-seeding DrbgParameters.Capability.PR_AND_RESEED, // Set the personalization string (optional, not necessary) "some_personalization_string".getBytes() ) ); } public Cipher getChaCha20Poly1305(int mode, byte[] ivKey, byte[] secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Get a DRBG random number generator instance SecureRandom random = getSecureRandomDRBG(); // Create a ChaCha20-Poly1305 cipher instance Cipher chaChaCipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); // Create our parameterSpec using our ivKey AlgorithmParameterSpec parameterSpec = new IvParameterSpec(ivKey); // Create a SecretKeySpec using our secretKey SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "ChaCha20"); // Initialize and return the cipher for the provided mode chaChaCipher.init(mode, secretKeySpec, parameterSpec, random); return chaChaCipher; } public void chaChaEncryption(byte[] plainText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Get a DRBG random number generator instance SecureRandom random = getSecureRandomDRBG(); // Create secretKey byte[] secretKey = new byte[32]; random.nextBytes(secretKey); // Create an IV Key byte[] ivKey = new byte[12]; random.nextBytes(ivKey); // Create a chaCha encryption cipher instance Cipher chaChaEncryptor = getChaCha20Poly1305(Cipher.ENCRYPT_MODE, ivKey, secretKey); // Encrypt the text using ChaCha20Poly1305 byte[] cipherText = null; try { cipherText = chaChaEncryptor.doFinal(plainText); } catch (IllegalBlockSizeException | BadPaddingException e) { System.out.println("failed to encrypt text"); return; } System.out.println("encrypted: " + Base64.getEncoder().encodeToString(cipherText)); // Create a chaCha decryption cipher instance Cipher chaChaDecryptor = getChaCha20Poly1305(Cipher.DECRYPT_MODE, ivKey, secretKey); // Decrypt the text byte[] decryptedText = null; try { decryptedText = chaChaDecryptor.doFinal(cipherText); } catch (IllegalBlockSizeException | BadPaddingException e) { System.out.println("failed to decrypt text"); return; } System.out.println("decrypted: " + new String(decryptedText, StandardCharsets.UTF_8)); } ``` For more information on Java Cryptography see: https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html

No author info

Cryptographic block ciphers can be configured to pad individual blocks if there is not enough input data to match the size of the block. This specific mode of CBC used in combination with PKCS5Padding is susceptible to padding oracle attacks. An adversary could potentially decrypt the message if the system exposed the difference between plaintext with invalid padding or valid padding. The distinction between valid and invalid padding is usually revealed through distinct error messages being returned for each condition. Consider switching to a more secure cipher that doesn't require padding and builds in message authentication integrity directly into the algorithm. Consider using `ChaCha20Poly1305` or `AES-256-GCM` instead. For older applications that don't have support for `ChaCha20Poly1305`, `AES-256-GCM` is recommended, however it has many drawbacks: - Slower than `ChaCha20Poly1305`. - Catastrophic failure if nonce values are reused. Example using `ChaCha20Poly1305`: ``` public encrypt() throws Exception { chaChaEncryption("Secret text to encrypt".getBytes(StandardCharsets.UTF_8)); } public SecureRandom getSecureRandomDRBG() throws NoSuchAlgorithmException { // Use DRBG according to http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf return SecureRandom.getInstance("DRBG", // Security strength in bits (default is 128) DrbgParameters.instantiation(256, // Set prediction resistance and re-seeding DrbgParameters.Capability.PR_AND_RESEED, // Set the personalization string (optional, not necessary) "some_personalization_string".getBytes() ) ); } public Cipher getChaCha20Poly1305(int mode, byte[] ivKey, byte[] secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Get a DRBG random number generator instance SecureRandom random = getSecureRandomDRBG(); // Create a ChaCha20-Poly1305 cipher instance Cipher chaChaCipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); // Create our parameterSpec using our ivKey AlgorithmParameterSpec parameterSpec = new IvParameterSpec(ivKey); // Create a SecretKeySpec using our secretKey SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "ChaCha20"); // Initialize and return the cipher for the provided mode chaChaCipher.init(mode, secretKeySpec, parameterSpec, random); return chaChaCipher; } public void chaChaEncryption(byte[] plainText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Get a DRBG random number generator instance SecureRandom random = getSecureRandomDRBG(); // Create secretKey byte[] secretKey = new byte[32]; random.nextBytes(secretKey); // Create an IV Key byte[] ivKey = new byte[12]; random.nextBytes(ivKey); // Create a chaCha encryption cipher instance Cipher chaChaEncryptor = getChaCha20Poly1305(Cipher.ENCRYPT_MODE, ivKey, secretKey); // Encrypt the text using ChaCha20Poly1305 byte[] cipherText = null; try { cipherText = chaChaEncryptor.doFinal(plainText); } catch (IllegalBlockSizeException | BadPaddingException e) { System.out.println("failed to encrypt text"); return; } System.out.println("encrypted: " + Base64.getEncoder().encodeToString(cipherText)); // Create a chaCha decryption cipher instance Cipher chaChaDecryptor = getChaCha20Poly1305(Cipher.DECRYPT_MODE, ivKey, secretKey); // Decrypt the text byte[] decryptedText = null; try { decryptedText = chaChaDecryptor.doFinal(cipherText); } catch (IllegalBlockSizeException | BadPaddingException e) { System.out.println("failed to decrypt text"); return; } System.out.println("decrypted: " + new String(decryptedText, StandardCharsets.UTF_8)); } ``` For more information on padding oracle attacks see: https://en.wikipedia.org/wiki/Padding_oracle_attack For more information on Java Cryptography see: https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html

No author info

The application was found implementing a custom `java.security.MessageDigest`. It is strongly recommended that a standard Digest algorithm be chosen instead as implementing a digest by hand is error-prone. The National Institute of Standards and Technology (NIST) recommends the use of SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, or SHA-512/256. Example of creating a SHA-384 hash: ``` // Create a MessageDigest using the SHA-384 algorithm MessageDigest sha384Digest = MessageDigest.getInstance("SHA-384"); // Call update with your data sha384Digest.update(input); // Only call digest once all data has been fed into the update sha384digest instance byte[] output = sha384Digest.digest(); // output base64 encoded version of the hash System.out.println("hash: " + Base64.getEncoder().encodeToString(output)); ```

No author info

The network communications for Hazelcast is configured to use a deprecated symmetric cipher. Consider using TLS/SSL when establishing communications across the Hazelcast cluster. For more information on configuring TLS/SSL for Hazelcast see: https://docs.hazelcast.com/imdg/4.2/security/tls-ssl

No author info

The application is generating an RSA key that is less than the recommended 2048 bits. The National Institute of Standards and Technology (NIST) deprecated signing Digital Certificates that contained RSA Public Keys of 1024 bits in December 2010. While 1024-bit RSA keys have not been factored yet, advances in compute may make it possible in the near future. Consider upgrading to the newer asymmetric algorithm such as `Ed25519` which handles the complexities of generating key pairs and choosing correct key sizes for you: ``` public static KeyPair generateEd25519() throws NoSuchAlgorithmException { // Choose Ed25519 for KeyPairGenerator Instance KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("Ed25519"); // Generate a KeyPair and return return keyPairGenerator.generateKeyPair(); } ``` Otherwise use a key size greater than 2048 when generating RSA keys: ``` public static KeyPair generateRSA() throws NoSuchAlgorithmException { // Choose RSA for KeyPairGenerator Instance KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); // Initialize with 2048 key size keyPairGenerator.initialize(2048); // Generate a KeyPair and return return keyPairGenerator.generateKeyPair(); } ``` For more information on Ed25519 see: http://ed25519.cr.yp.to/ For more information on Java Cryptography see: https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html

No author info

The application was found creating a `NullCipher` instance. `NullCipher` implements the `Cipher` interface by returning ciphertext identical to the supplied plaintext. This means any data passed to the `doFinal(...)` or `update(...)` methods will not actually encrypt the input. Remove the NullCipher reference and replace with a legitimate `Cipher` instance such as `ChaCha20-Poly1305` Example using `ChaCha20Poly1305`: ``` public encrypt() throws Exception { chaChaEncryption("Secret text to encrypt".getBytes(StandardCharsets.UTF_8)); } public SecureRandom getSecureRandomDRBG() throws NoSuchAlgorithmException { // Use DRBG according to http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf return SecureRandom.getInstance("DRBG", // Security strength in bits (default is 128) DrbgParameters.instantiation(256, // Set prediction resistance and re-seeding DrbgParameters.Capability.PR_AND_RESEED, // Set the personalization string (optional, not necessary) "some_personalization_string".getBytes() ) ); } public Cipher getChaCha20Poly1305(int mode, byte[] ivKey, byte[] secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Get a DRBG random number generator instance SecureRandom random = getSecureRandomDRBG(); // Create a ChaCha20-Poly1305 cipher instance Cipher chaChaCipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); // Create our parameterSpec using our ivKey AlgorithmParameterSpec parameterSpec = new IvParameterSpec(ivKey); // Create a SecretKeySpec using our secretKey SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "ChaCha20"); // Initialize and return the cipher for the provided mode chaChaCipher.init(mode, secretKeySpec, parameterSpec, random); return chaChaCipher; } public void chaChaEncryption(byte[] plainText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Get a DRBG random number generator instance SecureRandom random = getSecureRandomDRBG(); // Create secretKey byte[] secretKey = new byte[32]; random.nextBytes(secretKey); // Create an IV Key byte[] ivKey = new byte[12]; random.nextBytes(ivKey); // Create a chaCha encryption cipher instance Cipher chaChaEncryptor = getChaCha20Poly1305(Cipher.ENCRYPT_MODE, ivKey, secretKey); // Encrypt the text using ChaCha20Poly1305 byte[] cipherText = null; try { cipherText = chaChaEncryptor.doFinal(plainText); } catch (IllegalBlockSizeException | BadPaddingException e) { System.out.println("failed to encrypt text"); return; } System.out.println("encrypted: " + Base64.getEncoder().encodeToString(cipherText)); // Create a chaCha decryption cipher instance Cipher chaChaDecryptor = getChaCha20Poly1305(Cipher.DECRYPT_MODE, ivKey, secretKey); // Decrypt the text byte[] decryptedText = null; try { decryptedText = chaChaDecryptor.doFinal(cipherText); } catch (IllegalBlockSizeException | BadPaddingException e) { System.out.println("failed to decrypt text"); return; } System.out.println("decrypted: " + new String(decryptedText, StandardCharsets.UTF_8)); } ``` For more information on Java Cryptography see: https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html

No author info

The software uses the RSA algorithm but does not incorporate Optimal Asymmetric Encryption Padding (OAEP). By not enabling padding, the algorithm maybe vulnerable to [chosen plaintext attacks](https://en.wikipedia.org/wiki/Chosen-plaintext_attack). To enable OAEP mode, pass `RSA/ECB/OAEPWithSHA-256AndMGF1Padding` to the `Cipher.getInstance` method. Example encrypting and decrypting a message using RSA with OAEP: ``` public static void encryptWithRSA() throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { // Generate an RSA Public and Private Key Pair KeyPair keyPair = generateRSAKeys(); // Create a Cipher instance using RSA, ECB with OAEP Cipher rsaEncryptor = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); // Initialize to ENCRYPT_MODE with the public key rsaEncryptor.init(Cipher.ENCRYPT_MODE, keyPair.getPublic()); // Encrypt our secret message byte[] cipherText = rsaEncryptor.doFinal("Some secret message".getBytes(StandardCharsets.UTF_8)); // Create a Cipher instance using RSA, ECB with OAEP Cipher rsaDecryptor = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); // Initialize to DECRYPT_MODE with the private key rsaDecryptor.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); // Decrypt the secret message byte[] plainText = rsaDecryptor.doFinal(cipherText); // Debug output System.out.println(new String(plainText)); } ``` More information on Optimal asymmetric encryption padding: https://en.wikipedia.org/wiki/Optimal_asymmetric_encryption_padding For more information on Java Cryptography see: https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html

No author info

The application was found using an insecure or risky digest or signature algorithm. Both MD5 and SHA1 hash algorithms have been found to be vulnerable to producing collisions. This means that two different values, when hashed, can lead to the same hash value. If the application is trying to use these hash methods for storing passwords, then it is recommended to switch to a password hashing algorithm such as Argon2id or PBKDF2. strongly recommended that a standard Digest algorithm be chosen instead as implementing a digest by hand is error-prone. Example of creating a SHA-384 hash: ``` // Create a MessageDigest using the SHA-384 algorithm MessageDigest sha384Digest = MessageDigest.getInstance("SHA-384"); // Call update with your data sha384Digest.update(input); // Only call digest once all data has been fed into the update sha384digest instance byte[] output = sha384Digest.digest(); // output base64 encoded version of the hash System.out.println("hash: " + Base64.getEncoder().encodeToString(output)); ``` For more information on secure password storage see OWASP: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html

No author info

The `org.apache.http.impl.client.DefaultHttpClient` and `javax.net.ssl.SSLContext.getInstance` object instances do not verify the hostnames upon connection. This allows for an adversary who is in between the application and the target host to intercept potentially sensitive information or transmit malicious data. Do not use the `org.apache.http.impl.client.DefaultHttpClient();` as it is deprecated. Instead use the new `java.net.http.HttpClient` that was introduced in Java 9. Example connecting to a host that will automatically do TLS validation: ``` // Create a new java.net.http.HttpClient HttpClient httpClient = HttpClient.newHttpClient(); // Create a HttpRequest builder HttpRequest request = HttpRequest.newBuilder() // Create a URI for a website which requires TLS .uri(URI.create("https://www.example.com/")) // Build the request .build(); // Use the httpClient to send the request and use an HttpResponse.BodyHandlers String type HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); // Debug print System.out.println(response); ```

No author info

The application was found enabling insecure TLS protocol versions. When enabling protocol versions for an `SSLContext`, only the following versions should be allowed: - TLSv1.2 - TLSv1.3 - DTLSv1.2 - DTLSv1.3 To mitigate potential security risks, it is strongly advised to enforce TLS 1.2 as the minimum protocol version and disallow older versions such as TLS 1.0. Do note that newer versions of Java do not even support TLS 1.0 and will throw `NoSuchAlgorithmException`. Versions of TLS prior to 1.2 could expose the connection to downgrade attacks, where an adversary intercepts the connection and alters the requested protocol version to be a less secure one. In many scenarios, relying on the default system configuration does not meet compliance standards. This is due to the application being deployed across diverse systems with varying configurations and Java versions. While the default value may be secure on modern and up-to-date systems, it may not hold true for older systems. Consequently, it is highly recommended to explicitly define a secure configuration in all cases. Example configuring an SSLContext with TLSv1.2: ``` // Create an SSLContext with TLSv1.2 explicitly SSLContext tlsContext = SSLContext.getInstance("TLSv1.2"); // or TLSv1.3, DTLSv1.2, DTLSv1.3 // Alternatively, set the enabled protocols SSLContext serverSslContext = SSLContext.getInstance("TLS"); SSLEngine serverEngine = serverSslContext.createSSLEngine(); // Calling setEnabledProtocols will override the original context's configured protocol version serverEngine.setEnabledProtocols(new String[]{ "TLSv1.2" }); ``` For more information on `SSLContext` see: - https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/net/ssl/SSLContext.html For more information on MiTM attacks see: - https://owasp.org/www-community/attacks/Manipulator-in-the-middle_attack

No author info

The application fails to protect against Cross-Site Request Forgery (CSRF) due to disabling Spring's CSRF protection features. The vulnerability can be exploited by an adversary creating a link or form on a third party site and tricking an authenticated victim to access them. To remediate this issue, remove the call to `HttpSecurity.csrf().disable()` or remove the custom `CsrfConfigurer`. For more information on CSRF protection in Spring see: https://docs.spring.io/spring-security/reference/servlet/exploits/csrf.html#servlet-csrf Additionally, consider setting all session cookies to have the `SameSite=Strict` attribute. It should be noted that this may impact usability when sharing links across other mediums. It is recommended that a two cookie based approach is taken, as outlined in the [Top level navigations](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-08#section-8.8.2) section of the SameSite RFC. For more information on CSRF see OWASP's guide: https://owasp.org/www-community/attacks/csrf

No author info

A potential hard-coded password was identified in a hard-coded string. Passwords should not be stored directly in code but loaded from secure locations such as a Key Management System (KMS). The purpose of using a Key Management System is so access can be audited and keys easily rotated in the event of a breach. By hardcoding passwords, it will be extremely difficult to determine when or if, a key is compromised. The recommendation on which KMS to use depends on the environment the application is running in: - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) - For on premise or other alternatives to cloud providers, consider [Hashicorp's Vault](https://www.vaultproject.io/) - For other cloud providers, please see their documentation

No author info

Either the `HostnameVerifier` has been set to always return `true` or the `X509TrustManager` has been configured to return null, or both. This effectively disables the validation of server or client certificates. This allows for an adversary who is in between the application and the target host to intercept potentially sensitive information or transmit malicious data. It is recommended to not override the default `HostnameVerifiers`. Consider using the default `TrustManager` instead of implementing a custom one. If you must override the default verification process, implement proper TrustManager verification for `checkServerTrusted` and `checkClientTrusted` by throwing `CertificateException` if the certificate is invalid. Example using the built in `TrustManagerFactory` to manage validating certificate chains: ``` // Use the default TrustManagerFactory TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); // Use default system KeyStore, alternatively pass in your own keystore. trustManagerFactory.init((KeyStore) null); // Create SSLContext for TLS connections SSLContext tlsContext = SSLContext.getInstance("TLS"); // Initialize the tlsContext with our trust manager and a SecureRandom number generator. tlsContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom()); ``` For more information on TLS security see OWASP: https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html

No author info

The filename provided by the FileUpload API can be tampered with by the client to reference unauthorized files. The provided filename should be properly validated to ensure it's properly structured, contains no unauthorized path characters (e.g., / \), and refers to an authorized file.

No author info

A file is opened to read its content. The filename comes from an input parameter. If an unfiltered parameter is passed to this file API, files from an arbitrary filesystem location could be read.

No author info

The application was found to take data from user input and output it into a logger method. When data from an untrusted source is sent to a logger without validation, an attacker could forge log entries or include malicious content. If the log file is processed automatically, the attacker can render the file unusable by corrupting the format of the file or injecting unexpected characters. An attacker may also inject code or other commands into the log file and take advantage of a vulnerability in the log processing utility (e.g. command injection or XSS). To mitigate this issue, encode values that come from user input with a package such as [Apache Commons Text](https://commons.apache.org/proper/commons-text/) to escape the input: ``` public String escapeValue(String value) { return StringEscapeUtils.escapeJava(value); } ``` For more information on log injection see OWASP: https://owasp.org/www-community/attacks/Log_Injection

No author info

OS command injection is a critical vulnerability that can lead to a full system compromise as it may allow an adversary to pass in arbitrary commands or arguments to be executed. User input should never be used in constructing commands or command arguments to functions which execute OS commands. This includes filenames supplied by user uploads or downloads. Ensure your application does not: - Use user-supplied information in the process name to execute. - Use user-supplied information in an OS command execution function which does not escape shell meta-characters. - Use user-supplied information in arguments to OS commands. The application should have a hardcoded set of arguments that are to be passed to OS commands. If filenames are being passed to these functions, it is recommended that a hash of the filename be used instead, or some other unique identifier. It is strongly recommended that a native library that implements the same functionality be used instead of using OS system commands, due to the risk of unknown attacks against third party commands. When specifying the OS command, ensure the application uses the full path information, otherwise the OS may attempt to look up which process to execute and could be vulnerable to untrusted search path vulnerabilities (CWE-426). Example of safely executing an OS command: ``` public static void executeCommand(String userFileData) throws java.io.IOException { // Generate a random filename, do not use user input String fileName = UUID.randomUUID().toString(); // Create a Buffered/FileWriter BufferedWriter writer = new BufferedWriter(new FileWriter(fileName)); // Write the user content to our random file writer.write(userFileData); // Close the file to flush contents writer.close(); // Create the process builder with a hardcoded path to the binary, and our randomly generated filename ProcessBuilder processBuilder = new ProcessBuilder("/opt/app/path", fileName); // Start the process Process process = processBuilder.start(); // Handle/redirect output of process here // ... } ``` For more information on OS command injection, see OWASP's guide: https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html

No author info

SQL Injection is a critical vulnerability that can lead to data or system compromise. By dynamically generating SQL query strings, user input may be able to influence the logic of the SQL statement. This could lead to an adversary accessing information they should not have access to, or in some circumstances, being able to execute OS functionality or code. Replace all dynamically generated SQL queries with parameterized queries. In situations where dynamic queries must be created, never use direct user input, but instead use a map or dictionary of valid values and resolve them using a user-supplied key. For example, some database drivers do not allow parameterized queries for `>` or `<` comparison operators. In these cases, do not use a user supplied `>` or `<` value, but rather have the user supply a `gt` or `lt` value. The alphabetical values are then used to look up the `>` and `<` values to be used in the construction of the dynamic query. The same goes for other queries where column or table names are required but cannot be parameterized. Example using `PreparedStatement` queries: ``` // Some userInput String userInput = "someUserInput"; // Your connection string String url = "..."; // Get a connection from the DB via the DriverManager Connection conn = DriverManager.getConnection(url); // Create a prepared statement PreparedStatement st = conn.prepareStatement("SELECT name FROM table where name=?"); // Set each parameters value by the index (starting from 1) st.setString(1, userInput); // Execute query and get the result set ResultSet rs = st.executeQuery(); // Iterate over results while (rs.next()) { // Get result for this row at the provided column number (starting from 1) String result = rs.getString(1); // ... } // Close the ResultSet rs.close(); // Close the PreparedStatement st.close(); ``` For more information on SQL Injection see OWASP: https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html

No author info

An expression is built with a dynamic value. The source of the value(s) should be verified to avoid that unfiltered values fall into this risky code evaluation.

No author info

The `org.springframework.web.servlet.ModelAndView` class and `HttpRequest.getRequestDispatcher()`'s `include` and `forward` methods may potentially allow access to restricted files if called with user-supplied input. For Spring MVC, the ModelAndView class looks up a view by name to resolve a `.jsp` file. If this view name comes from user-supplied input, it could be abused to attempt to return a JSP view that the user should not have access to. The `HttpRequest.getRequestDispatcher()`'s `include` and `forward` methods will return any file that is resolvable within the web application context. This includes the `web.xml` file, any compiled classes, `jsp` files, and additional JAR or WAR libraries that are accessible. Never pass user-supplied input directly to any of these methods. Use a lookup table or hardcode which views or paths the user should be directed to. Another option is to use a simple HTTP redirect by returning an empty response body with a 301 status code and a `Location` redirect header. In Java servlets, this can be done by using the `response.sendRedirect(...)` method. Example using a lookup table to resolve a view from a Spring MVC application: ``` @RequestMapping(value="/mvc", method=RequestMethod.GET) public ModelAndView mvc(HttpServletRequest request, HttpServletResponse response, Model model) { // Create a look up table or pull from a data source HashMap<String, String> lookupTable = new HashMap<>(); lookupTable.put("key1", "view1"); lookupTable.put("key2", "view2"); // Get user input String userInput = request.getParameter("key"); // Look up view from the user input String viewValue = lookupTable.getOrDefault(userInput, userInput); // return the new model and view return new ModelAndView(viewValue); } ``` Example using a redirect instead of a `RequestDispatcher`: ``` // Create a look up table or pull from a data source HashMap<String, String> lookupTable = new HashMap<>(); lookupTable.put("key1", "/Resource1"); lookupTable.put("key2", "/Resource2"); // Get user input String userInput = request.getParameter("key"); // Look up resource to redirect to from the user input String redirectValue = lookupTable.getOrDefault(userInput, "/Resource1"); // Redirect the user response.sendRedirect(redirectValue); ```

No author info

The application was found including unvalidated user input into a URL, which could lead to HTTP Parameter Pollution (HPP) or worse, Server Side Request Forgery (SSRF). This could allow an adversary to override the value of a URL or a request parameter. HTTP Parameter Pollution (HPP) attacks consist of injecting encoded query string delimiters into other existing parameters. If a web application does not properly sanitize the user input, an adversary may modify the logic of these requests to other applications. To remediate this issue, never allow user input directly into creation of a URL or URL parameter. Consider using a map to look up user-supplied information and return exact values to be used in the generation of requests. Example using a map to look up a key to be used in a HTTP request: ``` HashMap<String, String> lookupTable = new HashMap<>(); lookupTable.put("key1", "value1"); lookupTable.put("key2", "value2"); String userInput = request.getParameter("key"); // Create a CloseableHttpClient, ideally any requests issued should be done // out-of-band from the servlet request itself (such as using a separate thread/scheduler system) try (final CloseableHttpClient httpClient = HttpClients.createDefault()) { // Lookup the value from our user input from our lookupTable String value = lookupTable.getOrDefault(userInput, "value1"); // Construct the url, with the hardcoded url and only pass in the value from the lookupTable, // not direct user input final HttpGet httpget = new HttpGet("https://example.com/getId?key="+value); // Execute the request CloseableHttpResponse clientResponse = httpClient.execute(httpget); // Read the response byte[] responseData = clientResponse.getEntity().getContent().readAllBytes(); // Handle the response // ... } ``` If using a map is not possible, the user-supplied input must be encoded prior to use, and never allow full URLs: ``` // Get user input String userInput = request.getParameter("key"); // Encode the string using java.net.URLEncoder with the UTF-8 character set String encodedString = java.net.URLEncoder.encode(userInput, StandardCharsets.UTF_8); // Create a CloseableHttpClient, ideally any requests issued should be done // out-of-band from the servlet request itself (such as using a separate thread/scheduler system) try (final CloseableHttpClient httpClient = HttpClients.createDefault()) { // Construct the url, with the hardcoded url and only pass in the encoded value, never a full URL final HttpGet httpget = new HttpGet("https://example.com/getId?key="+encodedString); // Execute the request CloseableHttpResponse clientResponse = httpClient.execute(httpget); // Read the response byte[] responseData = clientResponse.getEntity().getContent().readAllBytes(); // handle the response } ``` For more information on SSRF see OWASP: https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html For more information on HTTP Parameter Pollution see: https://en.wikipedia.org/wiki/HTTP_parameter_pollution

No author info

LDAP injection attacks exploit LDAP queries to influence how data is returned by the LDAP server. Later versions of Java's `InitialDirContext.search` introduced a four argument method, one of which is the `filterArg` parameter. The `filterArg` will be automatically encoded when querying the LDAP server. If this method signature is not available, the application must encode the LDAP strings manually. More details on the four argument `search` method can be found here: https://docs.oracle.com/en/java/javase/20/docs/api/java.naming/javax/naming/directory/InitialDirContext.html#search(javax.naming.Name,java.lang.String,java.lang.Object[],javax.naming.directory.SearchControls) To encode the string manually, it is recommended that all input passed to LDAP querying systems encode the following values: - Any occurrence of the null character must be escaped as “\00”. - Any occurrence of the open parenthesis character must be escaped as “\28”. - Any occurrence of the close parenthesis character must be escaped as “\29”. - Any occurrence of the asterisk character must be escaped as “\2a”. - Any occurrence of the backslash character must be escaped as “\5c”. Example function that safely encodes user-supplied input to be used in an LDAP query. ``` public static String encodeLDAPString(String input) { // Note the \ character is replaced first CharSequence[] chars = new CharSequence[] { "\\", "\0", "(", ")", "*" }; CharSequence[] encoded = new CharSequence[] { "\\5c", "\\00", "\\28", "\\29", "\\2a" }; // Iterate over each character sequence, replacing the raw value with an encoded version of it for (int i = 0; i < chars.length; i++) { // re-assign to input input = input.replace(chars[i], encoded[i]); } // return our modified input string return input; } ``` Example code that using the `filterArgs` parameter which automatically encodes for us: ``` // Create a properties to hold the ldap connection details Properties props = new Properties(); // Use the com.sun.jndi.ldap.LdapCtxFactory factory provider props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); // The LDAP server URL props.put(Context.PROVIDER_URL, "ldap://ldap.example.org:3889"); // User details for the connection props.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=example,dc=org"); // LDAP account password String ldapAccountPassword = getAccountPasswordFromSecureStoreOrKMS(); // Pass in the LDAP password props.put(Context.SECURITY_CREDENTIALS, ldapAccountPassword); // Create the LDAPContext InitialDirContext ldapContext = new InitialDirContext(props); // Example using SUBTREE_SCOPE SearchControls SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); // Get user input for query String userQuery = someUserInput; // Use searchArguments to hold the user-supplied input Object[] searchArguments = new Object[]{userQuery}; // Hardcode the BaseDN, use the {0} format specifier to use the searchArguments array value, and pass in the search controls. // searchArguments automatically encode NamingEnumeration answer = ldapContext.search("dc=example,dc=org", "(cn={0})", searchArguments, searchControls); // Process the response answer while (answer.hasMoreElements()) { ... } ``` For more information on LDAP Injection see OWASP: https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html

No author info

The Object Graph Navigation Language (OGNL) is an expression language that allows access to Java objects and properties stored in an ActionContext. Usage of these low-level functions is discouraged because they can effectively execute strings as code, leading to remote code execution vulnerabilities. Consider using struts tags when processing user-supplied input and templates. Much like the Struts security guide recommending to not use raw `${}` EL expressions, do not call or use the following OGNL packages with user-supplied input: - `com.opensymphony.xwork2.ognl` - `com.opensymphony.xwork2.util` - `com.opensymphony.xwork2.util.reflection` - `org.apache.struts2.util.StrutsUtil` For more information on Struts2 security see: https://struts.apache.org/security/#do-not-use-incoming-untrusted-user-input-in-forced-expression-evaluation

No author info

SQL Injection is a critical vulnerability that can lead to data or system compromise. By dynamically generating SQL query strings, user input may be able to influence the logic of the SQL statement. This could lead to an adversary accessing information they should not have access to, or in some circumstances, being able to execute OS functionality or code. Replace all dynamically generated SQL queries with parameterized queries. In situations where dynamic queries must be created, never use direct user input, but instead use a map or dictionary of valid values and resolve them using a user supplied key. For example, some database drivers do not allow parameterized queries for `>` or `<` comparison operators. In these cases, do not use a user supplied `>` or `<` value, but rather have the user supply a `gt` or `lt` value. The alphabetical values are then used to look up the `>` and `<` values to be used in the construction of the dynamic query. The same goes for other queries where column or table names are required but cannot be parameterized. Example using `PreparedStatement` queries: ``` // Some userInput String userInput = "someUserInput"; // Your connection string String url = "..."; // Get a connection from the DB via the DriverManager Connection conn = DriverManager.getConnection(url); // Create a prepared statement PreparedStatement st = conn.prepareStatement("SELECT name FROM table where name=?"); // Set each parameters value by the index (starting from 1) st.setString(1, userInput); // Execute query and get the result set ResultSet rs = st.executeQuery(); // Iterate over results while (rs.next()) { // Get result for this row at the provided column number (starting from 1) String result = rs.getString(1); // ... } // Close the ResultSet rs.close(); // Close the PreparedStatement st.close(); ``` For more information on SQL Injection see OWASP: https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html

No author info

The application does not provide authentication when communicating an LDAP server. It is strongly recommended that the LDAP server be configured with authentication and restrict what queries users can execute. Example code that authenticates with a remote LDAP server and encodes any user-supplied input: ``` // Create a properties to hold the ldap connection details Properties props = new Properties(); // Use the com.sun.jndi.ldap.LdapCtxFactory factory provider props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); // The LDAP server URL props.put(Context.PROVIDER_URL, "ldap://ldap.example.org:3889"); // User details for the connection props.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=example,dc=org"); // LDAP account password String ldapAccountPassword = getAccountPasswordFromSecureStoreOrKMS(); // Pass in the LDAP password props.put(Context.SECURITY_CREDENTIALS, ldapAccountPassword); // Create the LDAPContext InitialDirContext ldapContext = new InitialDirContext(props); // Example using SUBTREE_SCOPE SearchControls SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); // Get user input for query String userQuery = someUserInput; // Use searchArguments to hold the user-supplied input Object[] searchArguments = new Object[]{userQuery}; // Hardcode the BaseDN, use the {0} format specifier to use the searchArguments array value, and pass in the search controls. // searchArguments automatically encode NamingEnumeration answer = ldapContext.search("dc=example,dc=org", "(cn={0})", searchArguments, searchControls); // Process the response answer while (answer.hasMoreElements()) { ... } ``` For information on enabling authentication, please see your LDAP server's documentation. For more information on LDAP Injection see OWASP: https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html

No author info

A potential hard-coded password was identified in a database connection string. Passwords should not be stored directly in code but loaded from secure locations such as a Key Management System (KMS). The purpose of using a Key Management System is so access can be audited and keys easily rotated in the event of a breach. By hardcoding passwords, it will be extremely difficult to determine when or if, a key is compromised. The recommendation on which KMS to use depends on the environment the application is running in: - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) - For on premise or other alternatives to cloud providers, consider [Hashicorp's Vault](https://www.vaultproject.io/) - For other cloud providers, please see their documentation

No author info

The application does not provide authentication when communicating a database server. It is strongly recommended that the database server be configured with authentication and restrict what queries users can execute. Please see your database server's documentation on how to configure a password. Additionally, passwords should not be stored directly in code but loaded from secure locations such as a Key Management System (KMS). The purpose of using a Key Management System is so access can be audited and keys easily rotated in the event of a breach. By hardcoding passwords, it will be extremely difficult to determine when or if, a key is compromised. The recommendation on which KMS to use depends on the environment the application is running in: - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) - For on premise or other alternatives to cloud providers, consider [Hashicorp's Vault](https://www.vaultproject.io/) - For other cloud providers, please see their documentation

No author info

The application was found to permit the `RuntimePermission` of `createClassLoader`, `ReflectPermission` of `suppressAccessChecks`, or both. By granting the `RuntimePermission` of `createClassLoader`, a compromised application could instantiate their own class loaders and load arbitrary classes. By granting the `ReflectPermission` of `suppressAccessChecks` an application will no longer check Java language access checks on fields and methods of a class. This will effectively grant access to protected and private members. For more information on `RuntimePermission` see: https://docs.oracle.com/javase/8/docs/api/java/lang/RuntimePermission.html For more information on `ReflectPermission` see: https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/ReflectPermission.html

No author info

The application was found setting file permissions to overly permissive values. Consider using the following values if the application user is the only process to access the file: - `r--` - read only access to the file - `w--` - write only access to the file - `rw-` - read/write access to the file Example setting read/write permissions for only the owner of a `Path`: ``` // Get a reference to the path Path path = Paths.get("/tmp/somefile"); // Create a PosixFilePermission set from java.nio.file.attribute Set<PosixFilePermission> permissions = java.nio.file.attribute.PosixFilePermissions.fromString("rw-------"); // Set the permissions java.nio.file.Files.setPosixFilePermissions(path, permissions); ``` For all other values please see: https://en.wikipedia.org/wiki/File-system_permissions#Symbolic_notation

No author info

Depending on the context, generating weak random numbers may expose cryptographic functions which rely on these numbers, to be exploitable. When generating numbers for sensitive values such as tokens, nonces, and cryptographic keys, it is recommended that the `DRBG` instance of `SecureRandom` be used. Example using `DRBG` with `SecureRandom`: ``` public SecureRandom getSecureRandomDRBG() throws NoSuchAlgorithmException { // Use DRBG according to http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf return SecureRandom.getInstance("DRBG", // Security strength in bits (default is 128) DrbgParameters.instantiation(256, // Set prediction resistance and re-seeding DrbgParameters.Capability.PR_AND_RESEED, // Set the personalization string (optional, not necessary) "some_personalization_string".getBytes() ) ); } ``` For more information on Java Cryptography see: https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html

No author info

The application executes an argument using a `ScriptEngine`'s `eval` method. This may allow for direct OS commands to be executed as it's possible to pass in strings such as `java.lang.Runtime.getRuntime().exec('/bin/sh ...');`. Never pass user-supplied input directly to the `eval` function. If possible hardcode all JavasScript code or use a lookup table to resolve user input to known values. If none of these techniques are possible, use `javax.script.Bindings` to pass input to the script engine. Example using `Binding` to safely pass in string values: ``` // Get ECMAScript engine ScriptEngine engine = new ScriptEngineManager().getEngineByName("ECMAScript"); // User input, consisting of first and last name String userFirstName = "John"; String userLastName = "Snow"; // Create bindings to pass into our script, forcing the values to be String. Bindings bindings = engine.createBindings(); bindings.put("fname", new String(userFirstName)); bindings.put("lname", new String(userLastName)); // Example script that concatenates a greeting with the user-supplied input first/last name String script = "var greeting='Hello ';" + // fname and lname variables will be resolved by our bindings defined above "greeting += fname + ' ' + lname;" + // prints greeting "greeting"; try { // Execute the script, passing in the bindings Object bindingsResult = engine.eval(script, bindings); // Work with result // ... } catch (ScriptException e) { // Handle exception e.printStackTrace(); } ```

No author info

The application was found calling SpringFramework's `SpelExpressionParser.parseExpression`. Calling this method directly with user-supplied input may allow an adversary to execute arbitrary Java code including OS system commands. Never call `parseExpression` or `parseRaw` directly with user-supplied input. Consider alternate methods such as a lookup table to take user input and resolve hardcoded values. Later versions of SpringFramework introduced a `SimpleEvaluationContext` which can be used to access bound data when calling the `getValue` result of `parseExpression`. This `SimpleEvaluationContext` has a reduced set of functionality and can restrict data binding to read-only or read-write contexts. An adversary could still access public properties or fields on custom types that have been provided to the evaluation context. Use with caution. Example using `SimpleEvaluationContext` with a read-write data binding context: ``` @RequestMapping(value="/spel", method=RequestMethod.POST) public String spel(@Validated User user, Model model) { // Create the Expression Parser SpelExpressionParser parser = new SpelExpressionParser(); // Parse the expression Expression parsedExpression = parser.parseExpression(model.getPossiblyUnsafeData()); // Create the read-write data binding context SimpleEvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build(); // Execute the expression, passing in the read-write context Object result = parsedExpression.getValue(context); // work with the result // ... return "user"; } ``` For more information on SimpleEvaluationContext see: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/expression/spel/support/SimpleEvaluationContext.html

No author info

The Apache commons mail client by default does not enable TLS server identity. This allows for an adversary who is in between the application and the target host to intercept potentially sensitive information or transmit malicious data. Enable checking server identity by calling `Email.setSSLCheckServerIdentity(true)` Example email client that enables TLS and server identity: ``` // Create an email client Email email = new SimpleEmail(); // Configure the email hostname email.setHostName("smtp.mail.example.com"); // Set the port email.setSmtpPort(465); // Securely retrieve username and password values String username = getUserNameFromKMSorSecretStore(); String password = getPasswordFromKMSorSecretStore(); // Configure the Authenticator DefaultAuthenticator auth = new DefaultAuthenticator(username, password); // Set the authenticator email.setAuthenticator(auth); // Ensure we use SSL on connect email.setSSLOnConnect(true); // Ensure we validate server identity email.setSSLCheckServerIdentity(true); // configure the rest of the email email.setFrom("x@example.com"); email.setSubject("TestMail"); email.setMsg("This is a test mail ... :-)"); email.addTo("y@example.com"); email.send(); ```

No author info

The application was found calling `MimeMessage` methods without encoding new line characters. Much like HTTP, Simple Mail Transfer Protocol (SMTP) is a text based protocol that uses headers to convey additional directives for how email messages should be treated. An adversary could potentially cause email messages to be sent to unintended recipients by abusing the CC or BCC headers if they were able to inject them. To mitigate this issue, `\r\n` (CRLF) character sequences must be escaped or encoded prior to being used in any of the `MimeMessage` methods. Example that escapes values that come from user input with [Apache Commons Text](https://commons.apache.org/proper/commons-text/): ``` // Create a MimeMessage with a javax.mail.Session Message message = new MimeMessage(session); // Set the from address message.setFrom(new InternetAddress("source@example.com")); // Set the to address message.setRecipients(Message.RecipientType.TO,new InternetAddress[] {new InternetAddress("destination@example.com")}); // Example user input String subject = "potentially malicious data"; String headerValue = "potentially malicious data"; // Use Apache Commons Text StringEscapeUtils.escapeJava to encode \r\n to \\r\\n. message.setSubject(StringEscapeUtils.escapeJava(subject)); // Use Apache Commons Text StringEscapeUtils.escapeJava to encode \r\n to \\r\\n. message.addHeader("HeaderName", StringEscapeUtils.escapeJava(header)); // Use Apache Commons Text StringEscapeUtils.escapeJava to encode \r\n to \\r\\n. message.setDescription(StringEscapeUtils.escapeJava("some description")); // Use Apache Commons Text StringEscapeUtils.escapeJava to encode \r\n to \\r\\n. message.setDisposition(StringEscapeUtils.escapeJava("some disposition")); // Set the mail body text message.setText("Some email content."); // Send the message ```

No author info

Server-Side-Request-Forgery (SSRF) exploits backend systems that initiate requests to third parties. If user input is used in constructing or sending these requests, an attacker could supply malicious data to force the request to other systems or modify request data to cause unwanted actions. Ensure user input is not used directly in constructing URLs or URIs when initiating requests to third party systems from back end systems. Care must also be taken when constructing payloads using user input. Where possible restrict to known URIs or payloads. Consider using a server-side map where keys are used to return URLs such as `https://site/goto?key=1` where `{key: 1, url: 'http://some.url/', key: 2, url: 'http://...'}`. If you must use user-supplied input for requesting URLs, it is strongly recommended that the HTTP client chosen allows you to customize and block certain IP ranges at the network level. By blocking RFC 1918 addresses or other network address ranges, you can limit the severity of a successful SSRF attack. Care must also be taken to block certain protocol or address formatting such as IPv6. If you cannot block address ranges at the client level, you may want to run the HTTP client as a protected user, or in a protected network where you can apply IP Table or firewall rules to block access to dangerous addresses. Finally, if none of the above protections are available, you could also run a custom HTTP proxy and force all requests through it to handle blocking dangerous addresses. Example using a map to look up a key to be used in a HTTP request: ``` HashMap<String, String> lookupTable = new HashMap<>(); lookupTable.put("key1", "https://example.com/"); lookupTable.put("key2", "https://safeurl.com/"); String userInput = request.getParameter("key"); // Create a CloseableHttpClient, ideally any requests issued should be done // out-of-band from the servlet request itself (such as using a separate thread/scheduler system) try (final CloseableHttpClient httpClient = HttpClients.createDefault()) { // Lookup the value from our user input from our lookupTable String value = lookupTable.getOrDefault(userInput, "https://example.com/"); // Construct the url, with the hardcoded url and only pass in the value from the lookupTable, // not direct user input final HttpGet httpget = new HttpGet(value); // Execute the request CloseableHttpResponse clientResponse = httpClient.execute(httpget); // Read the response byte[] responseData = clientResponse.getEntity().getContent().readAllBytes(); // Handle the response // ... } ``` If using a map is not possible, the user-supplied input must be encoded prior to use, and never allow full URLs: ``` // Get user input String userInput = request.getParameter("key"); // Encode the string using java.net.URLEncoder with the UTF-8 character set String encodedString = java.net.URLEncoder.encode(userInput, StandardCharsets.UTF_8); // Create a CloseableHttpClient, ideally any requests issued should be done // out-of-band from the servlet request itself (such as using a separate thread/scheduler system) try (final CloseableHttpClient httpClient = HttpClients.createDefault()) { // Construct the url, with the hardcoded url and only pass in the encoded value, never a full URL final HttpGet httpget = new HttpGet("https://example.com/getId?key="+encodedString); // Execute the request CloseableHttpResponse clientResponse = httpClient.execute(httpget); // Read the response byte[] responseData = clientResponse.getEntity().getContent().readAllBytes(); // handle the response } ``` For more information on SSRF see OWASP: https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html

No author info

The application is using `Integer.toHexString` on a digest array buffer which may lead to an incorrect version of values. Consider using the `HexFormat` object introduced in Java 17. For older Java applications consider using the `javax.xml.bind.DatatypeConverter`. Example using `HexFormat` to create a human-readable string: ``` // Create a MessageDigest using the SHA-384 algorithm MessageDigest sha384Digest = MessageDigest.getInstance("SHA-384"); // Call update with your data sha384Digest.update("some input".getBytes(StandardCharsets.UTF_8)); // Only call digest once all data has been fed into the update sha384digest instance byte[] output = sha384Digest.digest(); // Create a JDK 17 HexFormat object HexFormat hex = HexFormat.of(); // Use formatHex on the byte array to create a string (note that alphabet characters are lowercase) String hexString = hex.formatHex(output); ``` For more information on DatatypeConverter see: https://docs.oracle.com/javase/9/docs/api/javax/xml/bind/DatatypeConverter.html#printHexBinary-byte:A-

No author info

External XML entities are a feature of XML parsers that allow documents to contain references to other documents or data. This feature can be abused to read files, communicate with external hosts, exfiltrate data, or cause a Denial of Service (DoS). It is recommended that the `SAXParser` is configured to disable DTD doctypes as this protects against the majority of XXE attacks. Example creating a SAXParser with disallowing the doctypes feature enabled: ``` // Create a SAXParserFactory SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); // Enable the feature which disallows <!DOCTYPE declarations which includes referencing external entities. saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // Create a new parser from this factory SAXParser parser = saxParserFactory.newSAXParser(); // Parse the XML file, passing in a DefaultHandler (which also includes an empty entityResolve method) parser.parse(new FileInputStream(new File("bad.xml")), new DefaultHandler()); ``` For more information on XML security see OWASP's guide: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java

No author info

External XML entities are a feature of XML parsers that allow documents to contain references to other documents or data. This feature can be abused to read files, communicate with external hosts, exfiltrate data, or cause a Denial of Service (DoS). The XMLReaderFactory has been deprecated. It is recommended that [SAXParserFactory](https://docs.oracle.com/javase/9/docs/api/javax/xml/parsers/SAXParserFactory.html) be used instead. Additionally when using the SAXParser it must be configured to disallow doctypes, which will protect against the majority of XXE attacks. Example creating a SAXParser with disallowing the doctypes feature enabled: ``` // Create a SAXParserFactory SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); // Enable the feature which disallows <!DOCTYPE declarations which includes referencing external entities. saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // Create a new parser from this factory SAXParser parser = saxParserFactory.newSAXParser(); // Parse the XML file, passing in a DefaultHandler (which also includes an empty entityResolve method) parser.parse(new FileInputStream(new File("bad.xml")), new DefaultHandler()); ``` For more information on XML security see OWASP's guide: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java

No author info

External XML entities are a feature of XML parsers that allow documents to contain references to other documents or data. This feature can be abused to read files, communicate with external hosts, exfiltrate data, or cause a Denial of Service (DoS). In most XML parsers, the recommendation to protect against XXE is to disable the doctype feature. Unfortunately use of the `XMLInputFactory` requires that the doctypes feature be enabled. Instead the application can set the `ACCESS_EXTERNAL_DTD` to an empty string and disable `javax.xml.stream.isSupportingExternalEntities`. Creates an `XMLInputFactory` stream parser, but disables accessing external DTD or entities: ``` // Create an XMLInputFactory XMLInputFactory factory = XMLInputFactory.newFactory(); // Set the ACCESS_EXTERNAL_DTD property to an empty string so it won't access // entities using protocols // (ref: https://docs.oracle.com/javase/8/docs/api/javax/xml/XMLConstants.html#ACCESS_EXTERNAL_DTD) factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Additionally, disable support for resolving external entities factory.setProperty("javax.xml.stream.isSupportingExternalEntities", false); // Continue to work with the factory/stream parser ``` For more information on XML security see OWASP's guide: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java

No author info

The application is disabling Wicket's string escaping functionality by calling `setEscapeModelStrings(false)`. This could lead to Cross Site Scripting (XSS) if used with user-supplied input. XSS is an attack which exploits a web application or system to treat user input as markup or script code. It is important to encode the data depending on the specific context it is used in. There are at least six context types: - Inside HTML tags `<div>context 1</div>` - Inside attributes: `<div class="context 2"></div>` - Inside event attributes `<button onclick="context 3">button</button>` - Inside script blocks: `<script>var x = "context 4"</script>` - Unsafe element HTML assignment: `element.innerHTML = "context 5"` - Inside URLs: `<iframe src="context 6"></iframe><a href="context 6">link</a>` Script blocks alone have multiple ways they need to be encoded. Extra care must be taken if user input is ever output inside of script tags. User input that is displayed within the application must be encoded, sanitized or validated to ensure it cannot be treated as HTML or executed as JavaScript code. Care must also be taken to not mix server-side templating with client-side templating, as the server-side templating will not encode things like {{ 7*7 }} which may execute client-side templating features. It is _NOT_ advised to encode user input prior to inserting into a data store. The data will need to be encoded depending on context of where it is output. It is much safer to force the displaying system to handle the encoding and not attempt to guess how it should be encoded. Use Wicket's built in escaping feature by calling `Component.setEscapeModelStrings(true);` For more information on Wicket components see: - https://nightlies.apache.org/wicket/apidocs/9.x/org/apache/wicket/Component.html For more information on XSS see OWASP: - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html

No author info

The application is returning user-supplied data from an HTTP request to an HTTP response's `sendError` method. This could lead to Cross Site Scripting (XSS) if the input were malicious script code and the application server is not properly validating the output. Note that Apache Tomcat 9 and above automatically encode the output and are not vulnerable. XSS is an attack which exploits a web application or system to treat user input as markup or script code. It is important to encode the data depending on the specific context it is used in. There are at least six context types: - Inside HTML tags `<div>context 1</div>` - Inside attributes: `<div class="context 2"></div>` - Inside event attributes `<button onclick="context 3">button</button>` - Inside script blocks: `<script>var x = "context 4"</script>` - Unsafe element HTML assignment: `element.innerHTML = "context 5"` - Inside URLs: `<iframe src="context 6"></iframe><a href="context 6">link</a>` Script blocks alone have multiple ways they need to be encoded. Extra care must be taken if user input is ever output inside of script tags. User input that is displayed within the application must be encoded, sanitized or validated to ensure it cannot be treated as HTML or executed as Javascript code. Care must also be taken to not mix server-side templating with client-side templating, as the server-side templating will not encode things like {{ 7*7 }} which may execute client-side templating features. It is _NOT_ advised to encode user input prior to inserting into a data store. The data will need to be encoded depending on context of where it is output. It is much safer to force the displaying system to handle the encoding and not attempt to guess how it should be encoded. If possible do not use user input directly in the output to the `sendError` message parameter. Regardless if the application server handles output encoding, consider encoding any user-supplied input that is used in the sendError method: Example using [Apache Commons Text](https://commons.apache.org/proper/commons-text/) `StringEscapeUtils.escapeHtml4`: ``` // Get user input String userInput = request.getParameter("key"); // Encode the input using the Html4 encoder String encoded = StringEscapeUtils.escapeHtml4(userInput); // Respond with the error code and value response.sendError(401, encoded); ``` For more information on XSS see OWASP: - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html

No author info

The application is returning user-supplied data from an HTTP request directly into an HTTP response output writer. This could lead to Cross Site Scripting (XSS) if the input were malicious script code and the application server is not properly validating the output. XSS is an attack which exploits a web application or system to treat user input as markup or script code. It is important to encode the data depending on the specific context it is used in. There are at least six context types: - Inside HTML tags `<div>context 1</div>` - Inside attributes: `<div class="context 2"></div>` - Inside event attributes `<button onclick="context 3">button</button>` - Inside script blocks: `<script>var x = "context 4"</script>` - Unsafe element HTML assignment: `element.innerHTML = "context 5"` - Inside URLs: `<iframe src="context 6"></iframe><a href="context 6">link</a>` Script blocks alone have multiple ways they need to be encoded. Extra care must be taken if user input is ever output inside of script tags. User input that is displayed within the application must be encoded, sanitized or validated to ensure it cannot be treated as HTML or executed as Javascript code. Care must also be taken to not mix server-side templating with client-side templating, as the server-side templating will not encode things like {{ 7*7 }} which may execute client-side templating features. It is _NOT_ advised to encode user input prior to inserting into a data store. The data will need to be encoded depending on context of where it is output. It is much safer to force the displaying system to handle the encoding and not attempt to guess how it should be encoded. If possible do not use user input directly in the output to the response writer. If the application must output user-supplied input, it will need to encode the data depending on the output context. Consider using [Apache Commons Text](https://commons.apache.org/proper/commons-text/) `StringEscapeUtils` methods for various context. Please note there is no way to safely output script code in most circumstances, regardless of encoding. If calling the HTTP response writer directly, ensure that the `Content-Type` is set to `text/plain` so it will not be accidentally interpreted by HTML by modern browsers. ``` // Get user input String htmlInput = request.getParameter("userInput"); // Encode the input using the Html4 encoder String htmlEncoded = StringEscapeUtils.escapeHtml4(htmlInput); // Force the HTTP response to be content type of text/plain so it is not interpreted as HTML response.setContentType("text/plain"); // Ensure UTF-8 response.setCharacterEncoding("UTF-8"); // Write response response.getWriter().write(htmlEncoded); ``` For more information on XSS see OWASP: - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html

No author info

The `HttpOnly` attribute when set to `true` protects the cookie value from being accessed by client side JavaScript such as reading the `document.cookie` values. By enabling this protection, a website that is vulnerable to Cross-Site Scripting (XSS) will be able to block malicious scripts from accessing the cookie value from JavaScript. Example of protecting a `Cookie`: ``` // Create an HttpOnly cookie. Cookie someCookie = new Cookie("SomeCookieName", "SomeValue"); // Set HttpOnly flag to true someCookie.setHttpOnly(true); ``` For more information see: https://jakarta.ee/specifications/servlet/4.0/apidocs/javax/servlet/http/cookie#setHttpOnly-boolean- Session cookies should be configured with the following security directives: - [HTTPOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) - [Secure](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) - [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite)

No author info

The `Secure` attribute when set to `true` protects the cookie value from being being transmitted over clear text communication paths such as HTTP. By enabling this protection, the cookie will only be sent over HTTPS. Example of protecting a `Cookie`: ``` // Create an Secure cookie. Cookie someCookie = new Cookie("SomeCookieName", "SomeValue"); // Set Secure flag to true someCookie.setSecure(true); ``` For more information see: https://jakarta.ee/specifications/servlet/4.0/apidocs/javax/servlet/http/cookie#setSecure-boolean- Session cookies should be configured with the following security directives: - [HTTPOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) - [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) - [Secure](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)

No author info

Prior to HTML5, Web browsers enforced the Same Origin Policy which ensures that in order for JavaScript to access the contents of a Web page, both the JavaScript and the Web page must originate from the same domain. Without the Same Origin Policy, a malicious website could serve up JavaScript that loads sensitive information from other websites using a client's credentials, cull through it, and communicate it back to the attacker. HTML5 makes it possible for JavaScript to access data across domains if a new HTTP header called Access-Control-Allow-Origin is defined. With this header, a Web server defines which other domains are allowed to access its domain using cross-origin requests. However, caution should be taken when defining the header because an overly permissive CORS policy will allow a malicious application to communicate with the victim application in an inappropriate way, leading to spoofing, data theft, relay and other attacks.

No author info

It is possible to attach malicious behavior to those style sheets. Therefore, if an attacker can control the content or the source of the style sheet, he might be able to trigger remote code execution.

profile photo of returntocorpreturntocorp

`$X == $X` or `$X != $X` is always true. (Unless the value compared is a float or double). To test if `$X` is not-a-number, use `Double.isNaN($X)`.

profile photo of returntocorpreturntocorp

Detected use of the 'none' algorithm in a JWT token. The 'none' algorithm assumes the integrity of the token has already been verified. This would allow a malicious actor to forge a JWT token that will automatically be verified. Do not explicitly use the 'none' algorithm. Instead, use an algorithm such as 'HS256'.

profile photo of returntocorpreturntocorp

When a Restful webservice endpoint is configured to use wildcard mediaType {*/*} as a value for the @Consumes annotation, an attacker could abuse the SerializableProvider by sending a HTTP Request with a Content-Type of application/x-java-serialized-object. The body of that request would be processed by the SerializationProvider and could contain a malicious payload, which may lead to arbitrary code execution when calling the $Y.getObject method.

profile photo of returntocorpreturntocorp

When a Restful webservice endpoint isn't configured with a @Consumes annotation, an attacker could abuse the SerializableProvider by sending a HTTP Request with a Content-Type of application/x-java-serialized-object. The body of that request would be processed by the SerializationProvider and could contain a malicious payload, which may lead to arbitrary code execution. Instead, add a @Consumes annotation to the function or class.

profile photo of returntocorpreturntocorp

Detected use of the 'none' algorithm in a JWT token. The 'none' algorithm assumes the integrity of the token has already been verified. This would allow a malicious actor to forge a JWT token that will automatically be verified. Do not explicitly use the 'none' algorithm. Instead, use an algorithm such as 'HS256'.

profile photo of returntocorpreturntocorp

A hard-coded credential was detected. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module).

profile photo of returntocorpreturntocorp

Cipher in ECB mode is detected. ECB mode produces the same output for the same input each time which allows an attacker to intercept and replay the data. Further, ECB mode does not provide any integrity checking. See https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY.

profile photo of returntocorpreturntocorp

NullCipher was detected. This will not encrypt anything; the cipher text will be the same as the plain text. Use a valid, secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.

profile photo of returntocorpreturntocorp

Detected a string argument from a public method contract in a raw SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.

profile photo of returntocorpreturntocorp

Detected a potential path traversal. A malicious actor could control the location of this file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path.

profile photo of returntocorpreturntocorp

Using CBC with PKCS5Padding is susceptible to padding oracle attacks. A malicious actor could discern the difference between plaintext with valid or invalid padding. Further, CBC mode does not include any integrity checks. Use 'AES/GCM/NoPadding' instead.

profile photo of returntocorpreturntocorp

Detected a potential path traversal. A malicious actor could control the location of this file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path.

profile photo of returntocorpreturntocorp

JMS Object messages depend on Java Serialization for marshalling/unmarshalling of the message payload when ObjectMessage.getObject() is called. Deserialization of untrusted data can lead to security flaws; a remote attacker could via a crafted JMS ObjectMessage to execute arbitrary code with the permissions of the application listening/consuming JMS Messages. In this case, the JMS MessageListener consume an ObjectMessage type received inside the onMessage method, which may lead to arbitrary code execution when calling the $Y.getObject method.

profile photo of returntocorpreturntocorp

Detected input from a HTTPServletRequest going into a session command, like `setAttribute`. User input into such a command could lead to an attacker inputting malicious code into your session parameters, blurring the line between what's trusted and untrusted, and therefore leading to a trust boundary violation. This could lead to programmers trusting unvalidated data. Instead, thoroughly sanitize user input before passing it into such function calls.

profile photo of returntocorpreturntocorp

Detected a request with potential user-input going into a OutputStream or Writer object. This bypasses any view or template environments, including HTML escaping, which may expose this application to cross-site scripting (XSS) vulnerabilities. Consider using a view technology such as JavaServer Faces (JSFs) which automatically escapes HTML views.

profile photo of returntocorpreturntocorp

Detected user input controlling a file path. An attacker could control the location of this file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path.

profile photo of returntocorpreturntocorp

User data flows into this manually-constructed SQL string. User data can be safely inserted into SQL strings using prepared statements or an object-relational mapper (ORM). Manually-constructed SQL strings is a possible indicator of SQL injection, which could let an attacker steal or manipulate data from the database. Instead, use prepared statements (`connection.PreparedStatement`) or a safe library.

profile photo of returntocorpreturntocorp

User data flows into the host portion of this manually-constructed URL. This could allow an attacker to send data to their own server, potentially exposing sensitive data such as cookies or authorization information sent with this request. They could also probe internal servers or other resources that the server runnig this code can access. (This is called server-side request forgery, or SSRF.) Do not allow arbitrary hosts. Instead, create an allowlist for approved hosts hardcode the correct host, or ensure that the user data can only affect the path or parameters.

profile photo of returntocorpreturntocorp

Detected user input used to manually construct a SQL string. This is usually bad practice because manual construction could accidentally result in a SQL injection. An attacker could use a SQL injection to steal or modify contents of the database. Instead, use a parameterized query which is available by default in most database engines. Alternatively, consider using an object-relational mapper (ORM) such as Sequelize which will protect your queries.

profile photo of returntocorpreturntocorp

DOCTYPE declarations are enabled for this DocumentBuilderFactory. This is vulnerable to XML external entity attacks. Disable this by setting the feature "http://apache.org/xml/features/disallow-doctype-decl" to true. Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. This can be done by setting the features "http://xml.org/sax/features/external-general-entities" and "http://xml.org/sax/features/external-parameter-entities" to false.

profile photo of returntocorpreturntocorp

Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.

profile photo of returntocorpreturntocorp

Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.

profile photo of returntocorpreturntocorp

Seam Logging API support an expression language to introduce bean property to log messages. The expression language can also be the source to unwanted code execution. In this context, an expression is built with a dynamic value. The source of the value(s) should be verified to avoid that unfiltered values fall into this risky code evaluation.

No author info

The application dynamically constructs file or path information. If the path information comes from user input, it could be abused to read sensitive files, access other users' data, or aid in exploitation to gain further system access. User input should never be used in constructing paths or files for interacting with the filesystem. This includes filenames supplied by user uploads or downloads. If possible, consider hashing user input or replacing it with unique values and use `Path.resolve` to resolve and validate the path information prior to processing any file functionality. Example using `Path.resolve` and not allowing direct user input: ``` // Class to store our user data along with a randomly generated file name public static class UserData { private String userFileNameUnsafe; private String fileName; public UserData(String userFileName) { this.userFileNameUnsafe = userFileName; // Generate a random ID for the filename this.fileName = UUID.randomUUID().toString(); } public String getUserFileNameUnsafe() { return userFileNameUnsafe; }; public String getFileName() { return fileName; }; } public static void main(String[] args) throws Exception { // User input, saved only as a reference UserData userData = new UserData("..\\test.txt"); // Restrict all file processing to this directory only String base = "/var/app/restricted"; Path basePath = Paths.get(base); // Resolve the full path, but only use our random generated filename Path fullPath = basePath.resolve(userData.getFileName()); // verify the path is contained within our basePath if (!fullPath.startsWith(base)) { throw new Exception("Invalid path specified!"); } // process / work with file } ``` For more information on path traversal issues see OWASP: https://owasp.org/www-community/attacks/Path_Traversal

No author info

Cryptographic keys should not be kept in the source code. The source code can be widely shared in an enterprise environment, and is certainly shared in open source. To be managed safely, passwords and secret keys should be stored in separate configuration files or keystores.

No author info

Cryptographic keys should not be kept in the source code. The source code can be widely shared in an enterprise environment, and is certainly shared in open source. To be managed safely, passwords and secret keys should be stored in separate configuration files or keystores.

No author info

Cryptographic keys should not be kept in the source code. The source code can be widely shared in an enterprise environment, and is certainly shared in open source. To be managed safely, passwords and secret keys should be stored in separate configuration files or keystores.

No author info

Cryptographic keys should not be kept in the source code. The source code can be widely shared in an enterprise environment, and is certainly shared in open source. To be managed safely, passwords and secret keys should be stored in separate configuration files or keystores.

No author info

The application allows user input to control format string parameters. By passing invalid format string specifiers an adversary could cause the application to throw exceptions or possibly leak internal information depending on application logic. Never allow user-supplied input to be used to create a format string. Replace all format string arguments with hardcoded format strings containing the necessary specifiers. Example of using `String.format` safely: ``` // Get untrusted user input String userInput = request.getParameter("someInput"); // Ensure that user input is not included in the first argument to String.format String.format("Hardcoded string expecting a string: %s", userInput); // ... ```

No author info

The application was found matching a variable during a regular expression pattern match, and then calling string modification functions after validation has occurred. This is usually indicative of a poor input validation strategy as an adversary may attempt to exploit the removal of characters. For example a common mistake in attempting to remove path characters to protect against path traversal is to match '../' and then remove any matches. However, if an adversary were to include in their input: '....//' then the `replace` method would replace the first `../` but cause the leading `..` and trailing `/` to join into the final string of `../`, effectively bypassing the check. To remediate this issue always perform string modifications before any validation of a string. It is strongly recommended that strings be encoded instead of replaced or removed prior to validation. Example replaces `..` before validation. Do note this is still not a recommended method for protecting against directory traversal, always use randomly generated IDs or filenames instead: ``` // This is ONLY for demonstration purpose, never use untrusted input // in paths, always use randomly generated filenames or IDs. String input = "test../....//dir"; // Use replaceAll _not_ replace input = input.replaceAll("\\.\\.", ""); // Input would be test///dir at this point // Create a pattern to match on Pattern pattern = Pattern.compile("\\.\\."); // Create a matcher Matcher match = pattern.matcher(input); // Call find to see if .. is still in our string if (match.find()) { throw new Exception(".. detected"); } // Use the input (but do not modify the string) System.out.println(input + " safe"); ``` For more information see Carnegie Mellon University's Secure Coding Guide: https://wiki.sei.cmu.edu/confluence/display/java/IDS11-J.+Perform+any+string+modifications+before+validation

No author info

The application was found matching a variable during a regular expression pattern match, and then calling a Unicode normalize function after validation has occurred. This is usually indicative of a poor input validation strategy as an adversary may attempt to exploit the normalization process. To remediate this issue, always perform Unicode normalization before any validation of a string. Example of normalizing a string before validation: ``` // User input possibly containing malicious unicode String userInput = "\uFE64" + "tag" + "\uFE65"; // Normalize the input userInput = Normalizer.normalize(userInput, Normalizer.Form.NFKC); // Compile our regex pattern looking for < or > charcters Pattern pattern = Pattern.compile("[<>]"); // Create a matcher from the userInput Matcher matcher = pattern.matcher(userInput); // See if the matcher matches if (matcher.find()) { // It did so throw an error throw new Exception("found banned characters in input"); } ``` For more information see Carnegie Mellon University's Secure Coding Guide: https://wiki.sei.cmu.edu/confluence/display/java/IDS01-J.+Normalize+strings+before+validating+them

No author info

The application may allow control over a template string. Providing user input directly in the template by dynamically creating template strings may allow an adversary to execute arbitrary Java code, including OS system commands. For Velocity, never call `evaluate` with user-supplied input in the template string. Use a `VelocityContext` object instead to data-bind user-supplied information as it will be treated as an underlying data type and not template code. Example using Apache Velocity's `VelocityContext` and escape tools to pass in user-supplied data to a template: ``` // Create a tool manager ToolManager manager = new ToolManager(true); // Create a context from the tool manager Context context = manager.createContext(); // For demonstration purposes, alternatively configure from a properties file context.put("esc", new EscapeTool()); // For demonstration purposes, create an output buffer StringWriter stringWriter = new StringWriter(); // Get userInput String userInput = "potentially malicious data"; // Use the context to pass in the userInput value context.put("userInput", userInput); // Pass in the context, the output buffer, a logtag (demo), and the template with userInput // making sure to escape it if in the context of HTML. Velocity.evaluate(context, stringWriter, "demo", "Hello $esc.html($userInput)"); // Work with the output buffer // ... ``` For other templating engines, please see your framework's documentation.

No author info

The application was found using user-supplied input in a `java.sql.Connection`'s `setCatalog` call. This could allow an adversary to supply a different database for the lifetime of the connection. Allowing external control of system settings can disrupt service or cause an application to behave in unexpected, and potentially malicious ways. Most likely this would only cause an error by providing a nonexistent catalog name. It is recommended to not use user-supplied input when selecting the database for an applications database connection.

No author info

SAML parses attestations as an XML document. By processing XML comments, comment fields can end up modifying the interpretation of input fields. This could allow an adversary to insert an XML comment to break up the attestation's username or other fields, allowing an attacker to bypass authorization or authentication checks. To remediate this issue, when using `org.opensaml.xml.parse.BasicParserPool` ensure `setIgnoreComments(true)` is called. For more information on how this issue can be exploited see: https://developer.okta.com/blog/2018/02/27/a-breakdown-of-the-new-saml-authentication-bypass-vulnerability For more information on SAML security see OWASP: https://cheatsheetseries.owasp.org/cheatsheets/SAML_Security_Cheat_Sheet.html

No author info

Deserialization attacks exploit the process of reading serialized data and turning it back into an object. By constructing malicious objects and serializing them, an adversary may attempt to: - Inject code that is executed upon object construction, which occurs during the deserialization process. - Exploit mass assignment by including fields that are not normally a part of the serialized data but are read in during deserialization. Consider safer alternatives such as serializing data in the JSON format. Ensure any format chosen allows the application to specify exactly which object types are allowed to be deserialized. Additionally, when deserializing, never deserialize to base object types like `Object` and only cast to the exact object type that is expected. To protect against mass assignment, only allow deserialization of the specific fields that are required. If this is not easily done, consider creating an intermediary type that can be serialized with only the necessary fields exposed. Do note that `XMLEncoder` and `XMLDecoder` are not recommended. If the application must use this serialization method, use a custom ClassLoader to prevent loading of arbitrary classes: ``` XMLDecoder decoder = new XMLDecoder(inputStream, null, null, new ClassLoader() { @Override protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { if (!name.equals(NameOfBeanHere.class.getName()) && !name.equals(XMLDecoder.class.getName())) { throw new RuntimeException("Unauthorized deserialization attempt: " + name); } throw new ClassNotFoundException(name); } }); ``` For more information on XML security see OWASP's guide: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java For more details on deserialization attacks in general, see OWASP's guide: https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html It should be noted that [tools exist](https://github.com/frohoff/ysoserial) to automatically create exploit code for these vulnerabilities.

No author info

The application performs XSLT translation with potentially malicious input. An adversary who is able to influence the loaded XSL document could call XSL functions or exploit External XML Entity (XXE) attacks that allow file retrieval or force the parser to connect to arbitrary servers to exfiltrate files. It is strongly recommended that an alternative approach is used to work with XML data. For increased security, never process user-supplied XSL style sheets. If XSLT processing is absolutely necessary, ensure that `FEATURE_SECURE_PROCESSING` is enabled prior to processing the XSLT file: ``` // Create a new TransformerFactory instance TransformerFactory transformerFactory = TransformerFactory.newInstance(); // Enable the FEATURE_SECURE_PROCESSING feature transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); // Read in the XML Source Source xmlSource = new StreamSource(new FileInputStream("hardcoded.xml")); // Read in the XSL template file Source xslSource = new StreamSource(new FileInputStream("hardcoded.xsl")); /// Create the transformer object to do the transformation Transformer transformer = transformerFactory.newTransformer(xslSource); // Create a Result object for output Result result = new StreamResult(System.out); // Execute the transformation process transformer.transform(xmlSource, result); ``` For more information on XML security see OWASP's guide: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java For more information on the secure processing feature see: - https://xml.apache.org/xalan-j/features.html#secureprocessing

No author info

The application processes `XPath` queries with potentially malicious input. An adversary who is able to control the XPath query could potentially influence the logic of how data is retrieved, processed or even bypass protections. To protect against XPath injection, user input should be parameterized using a variable resolver. By creating a class that implements the `XPathVariableResolver` the application can ensure that the xpath query and user-supplied input are treated separately. Example implementation of an XPathVariableResolver: ``` // Create a class which implements the XPathVariableResolver interface public static class SimpleXPathVariableResolver implements XPathVariableResolver { // Use a map or lookup table to store variables for resolution private HashMap<QName, String> variables = new HashMap<>(); // Allow caller to set variables public void setVariable(QName name, String value) { variables.put(name, value); } // Implement the resolveVariable to return the value @Override public Object resolveVariable(QName name) { return variables.getOrDefault(name, ""); } } public static void xpathQuery(String userInput) throws ParseException, ParserConfigurationException, SAXException, IOException, XPathExpressionException { // Create our DocumentFactory DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); // Enable namespace awareness domFactory.setNamespaceAware(true); // Enable secure processing domFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); // Create our DocumentBuilder DocumentBuilder builder = domFactory.newDocumentBuilder(); // Parse our XML document Document doc = builder.parse("inventory.xml"); // Create a new instance of an XPath object XPath xpathProcessor = XPathFactory.newInstance().newXPath(); // Create our XPathVariableResolver SimpleXPathVariableResolver resolver = new SimpleXPathVariableResolver(); // Add user input as a variable value resolver.setVariable(new QName("author"), userInput); // Configure the processor to use our variable resolver xpathProcessor.setXPathVariableResolver(resolver); // Evaluate the XPath query String result = xpathProcessor.compile("//author[contains(., $author)]").evaluate(doc); // Work with the result // ... } ``` For more information on XPath Injection see: - https://owasp.org/www-community/attacks/XPATH_Injection

profile photo of returntocorpreturntocorp

GCM detected, please check that IV/nonce is not reused, an Initialization Vector (IV) is a nonce used to randomize the encryption, so that even if multiple messages with identical plaintext are encrypted, the generated corresponding ciphertexts are different. Unlike the Key, the IV usually does not need to be secret, rather it is important that it is random and unique. Certain encryption schemes the IV is exchanged in public as part of the ciphertext. Reusing same Initialization Vector with the same Key to encrypt multiple plaintext blocks allows an attacker to compare the ciphertexts and then, with some assumptions on the content of the messages, to gain important information about the data being encrypted.