Web Vulnerabilities
Mainly for convenient copy/paste when writing reports.
Reflected XSS
Description:
Reflected Cross-Site Scripting (XSS) is a common web vulnerability. It happens when an attacker injects a malicious script into an application, and the application reflects it back to the user without proper sanitization or validation. This allows the script to execute in the victim’s browser, potentially leading to cookie theft, session hijacking, page defacement, phishing, etc.
Example (user input is directly concatenated into HTML):
import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;
public class VulnerableServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String userInput = request.getParameter("input"); // Vulnerable to XSS
response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head><title>Reflection XSS Vulnerability Example</title></head>"); out.println("<body>"); out.println("<h1>Hello, " + userInput + "!</h1>"); // Vulnerable to XSS out.println("</body>"); out.println("</html>"); out.close(); }}Recommendations:
- Input validation & sanitization: validate and sanitize all user input before rendering it. Ensure input does not contain HTML/JavaScript or other executable content.
- Output encoding: encode user input when outputting it into HTML so the browser won’t interpret it as executable code (use framework-provided encoding functions/libraries).
- Content Security Policy (CSP): enforce a strict CSP to control which resources (scripts/styles/fonts) may load. Restricting script sources helps mitigate XSS impact.
- Use mature frameworks/libraries: leverage frameworks/libraries with built-in XSS protections (automatic encoding, safer templating, etc.).
Example: HTML-escape user input with StringEscapeUtils.escapeHtml4() (Apache Commons Text) before rendering:
import org.apache.commons.text.StringEscapeUtils; // Using Apache Commons Text library for HTML escaping
public class XSSExample { public static void main(String[] args) { // Simulated user input (potentially malicious) String userInput = "<script>alert('XSS Attack!');</script>";
// Encode user input to prevent XSS String safeOutput = StringEscapeUtils.escapeHtml4(userInput);
// Displaying the safe output System.out.println("Safe Output: " + safeOutput); }}Stored XSS
Description:
Recommendations:
DOM-based XSS
Description:
DOM-based XSS is an attack where malicious code executes in the browser through client-side script (typically JavaScript) manipulating the DOM (Document Object Model). Unlike other XSS types, DOM XSS does not require server-side reflection/storage — it happens when page scripts incorrectly handle untrusted input and inject it into the DOM. This can steal sessions, modify page content, etc.
Recommendations:
- Validate/encode input before DOM insertion: never use untrusted input directly in DOM operations.
- Use safe APIs: prefer APIs that do not parse HTML, e.g.
textContentinstead ofinnerHTML. UseElement.setAttributeinstead of string concatenation. - Use CSP: restrict inline scripts and unauthorized external scripts.
- Use framework protections: modern frameworks (React/Angular/Vue) provide XSS mitigations by default when used correctly.
Directory Traversal
Description:
Directory traversal (path traversal) allows attackers to access files/directories outside the intended directory by supplying paths like ../. This can leak sensitive files (configs/passwords) or allow modification/execution of system files.
Example (attacker controls filePath like "../../etc/passwd"):
public class DirectoryTraversalVulnerable { public byte[] readFile(String filePath) throws IOException { File file = new File(filePath); FileInputStream fis = new FileInputStream(file); byte[] data = new byte[(int) file.length()]; fis.read(data); fis.close(); return data; }}Recommendations:
- Strict input validation: reject/remove traversal sequences like
../. - Use safer file APIs: ensure your file access logic accounts for traversal.
- Use allowlists: maintain an allowlist of permitted paths/files.
- Least privilege: restrict filesystem permissions for the app user.
- Error handling: avoid leaking filesystem structure via errors.
Example: enforce a safe base directory and validate canonical paths:
public class DirectoryTraversalSafe { private final String basePath = "/var/data/appfiles"; // safe base path
public byte[] readFile(String filePath) throws IOException { File file = new File(basePath, filePath); if (!file.getCanonicalPath().startsWith(basePath)) { throw new SecurityException("Attempted directory traversal attack"); } FileInputStream fis = new FileInputStream(file); byte[] data = new byte[(int) file.length()]; fis.read(data); fis.close(); return data; }}SQL Injection
Description:
SQL injection allows attackers to inject malicious SQL into queries, leading to auth bypass, data theft/modification/deletion, etc. It typically occurs when user input is concatenated into SQL without proper parameterization.
Vulnerable example (string concatenation):
public class SqlInjectionVulnerable { public void getUser(String username) { Connection conn = null; Statement stmt = null; try { conn = DriverManager.getConnection("jdbc:mysql://localhost/testdb", "user", "password"); stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM users WHERE username = '" + username + "'"); while (rs.next()) { // handle results } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (stmt != null) stmt.close(); } catch (SQLException e) { } try { if (conn != null) conn.close(); } catch (SQLException e) { } } }}Recommendations:
- Parameterized queries: the most effective protection; prevents SQL structure changes.
- Prepared statements: e.g.
PreparedStatementin Java; separates query structure from data. - Input validation: reduce attack surface by rejecting suspicious input (not sufficient alone).
- Use ORM frameworks: Hibernate/JPA typically use parameterization by default.
- Least privilege: limit DB account permissions so impact is reduced if injection succeeds.
Safe example (prepared statement):
public class SqlInjectionSafe { public void getUser(String username) { Connection conn = null; PreparedStatement pstmt = null; try { conn = DriverManager.getConnection("jdbc:mysql://localhost/testdb", "user", "password"); pstmt = conn.prepareStatement("SELECT * FROM users WHERE username = ?"); pstmt.setString(1, username); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { // handle results } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (pstmt != null) pstmt.close(); } catch (SQLException e) { } try { if (conn != null) conn.close(); } catch (SQLException e) { } } }}SQL Injection (MyBatis)
Description:
In MyBatis, ${} performs string substitution: it directly injects the value into the SQL text (no precompilation/binding like #{}). While ${} can be useful for internal trusted variables, using it with untrusted user input can lead to SQL injection.
Vulnerable mapper (uses ${}):
<mapper namespace="com.example.mapper.UserMapper"> <select id="findUserByUsername" resultType="com.example.model.User"> SELECT * FROM users WHERE username = '${username}' </select></mapper>Recommendations:
- Avoid
${}for user input: only use it for internal trusted values. - Use
#{}parameter binding: uses prepared statements and prevents SQL injection. - Validate/clean inputs: enforce formats/length/range to reduce abuse.
- Use MyBatis dynamic SQL: prefer
<choose>,<if>,<when>,<otherwise>, etc., instead of manual string concatenation.
Safe mapper (uses #{}):
<mapper namespace="com.example.mapper.UserMapper"> <select id="findUserByUsername" parameterType="string" resultType="com.example.model.User"> SELECT * FROM users WHERE username = #{username} </select></mapper>Command Injection
Description:
Command injection occurs when untrusted input is used to build a system command. Attackers can inject extra commands/arguments to achieve arbitrary command execution, leading to data exposure and system compromise. This often happens when using APIs like Runtime.exec() or ProcessBuilder without strict validation.
Recommendations:
- Avoid executing user input directly: validate and sanitize strictly if unavoidable.
- Use safer APIs: keep command and parameters strictly separated (e.g.,
ProcessBuilderwith argument arrays). - Allowlist validation: restrict to known-safe commands/arguments.
- Least privilege: run the app with minimal OS permissions.
- Use existing security libraries/tools: avoid custom parsing/escaping where possible.
Server-Side Request Forgery (SSRF)
Description:
SSRF allows an attacker to make the server send requests to attacker-chosen targets (internal/external). This can access internal services behind firewalls, bypass IP allowlists, scan ports, and abuse trust relationships.
Recommendations:
- Validate and filter URLs: enforce strict format and allowlist allowed schemes/domains.
- Restrict destinations: block private networks/metadata endpoints; restrict ports.
- Use safe URL parsing libraries: avoid hand-rolled parsing.
- Set timeouts/retries: reduce DoS risk.
- Use an egress proxy: centralize filtering/auditing and hide real server IP.
Example: validate host/protocol with an allowlist before fetching:
import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.URL;
public class SsrfSafeExample { public String fetchUrlContent(String urlString) throws Exception { URL url = new URL(urlString);
// Validate URL host/protocol if (!isValidUrl(url)) { throw new IllegalArgumentException("Invalid URL provided"); }
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close();
return response.toString(); }
private boolean isValidUrl(URL url) { // Example allowlist (customize for your app) String host = url.getHost(); String protocol = url.getProtocol(); return "http".equals(protocol) && ("example.com".equals(host) || "api.example.com".equals(host)); }}Code Injection
Description:
Code injection happens when untrusted input is passed into an interpreter/executor (e.g., eval(), Runtime.exec()) and runs as code. Impact ranges from data tampering to full system compromise.
Recommendations:
- Avoid dynamic execution: avoid
eval()/dynamic execution APIs whenever possible. - Validate and sanitize inputs: strict format validation; reject dangerous characters/expressions.
- Parameterize: avoid string concatenation for commands/scripts.
- Least privilege: minimize execution environment permissions.
- Use secure frameworks: rely on frameworks providing safer patterns/mitigations.
Open Redirect
Description:
Open redirect lets attackers craft URLs that redirect users to malicious sites, enabling phishing and other social engineering. It happens when redirect targets are built from unvalidated user input.
Recommendations:
- Strict validation + allowlist: only allow redirects to trusted domains or internal URLs.
- Avoid user-controlled redirect targets: sanitize and validate if unavoidable.
- Use framework-safe redirect helpers: e.g., Spring MVC
RedirectAttributes. - Log/monitor redirects: capture source and destination to detect abuse.
- Security training: ensure the team can recognize and avoid open redirects.
Cryptography
Insecure Cipher Mode
Description:
Block cipher modes describe how to apply a cipher repeatedly over data blocks (ECB/CBC/CFB/CTR/etc).
- ECB is weak because identical plaintext blocks produce identical ciphertext blocks.
- CBC can be vulnerable to padding oracle attacks.
- CTR avoids these specific issues and is generally better.
Example (AES in ECB mode):
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");cipher.init(Cipher.ENCRYPT_MODE, key);Recommendations:
Avoid ECB and (where possible) CBC when encrypting multi-block data. Prefer CCM or (for performance) GCM when available.
Example (GCM mode):
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5Padding", "BC");cipher.init(Cipher.ENCRYPT_MODE, key);Insecure Cipher Algorithm
Description:
Using outdated/weak algorithms (e.g., DES, MD5) can lead to easy cracking and data exposure. As computing power increases, algorithms once considered secure may become weak.
Example (DES):
import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;
public class UnsafeEncryptionExample { public static void main(String[] args) throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance("DES"); SecretKey secretKey = keyGenerator.generateKey();
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey);
String plainText = "Sensitive Information"; byte[] encryptedText = cipher.doFinal(plainText.getBytes()); System.out.println("Encrypted: " + new String(encryptedText)); }}Recommendations:
- Use strong algorithms: e.g. AES with sufficient key length (AES-256).
- Choose secure modes: e.g. CBC/GCM; prefer modes that provide integrity/authentication where applicable.
- Use mature crypto libraries: avoid implementing crypto yourself.
- Regularly review/update crypto: keep up with vulnerabilities and best practices.
Example (AES-GCM with 256-bit key):
import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import javax.crypto.spec.GCMParameterSpec;import java.security.SecureRandom;
public class SecureGcmEncryptionExample { public static void main(String[] args) throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(256); // 256-bit key SecretKey secretKey = keyGenerator.generateKey();
final int GCM_IV_LENGTH = 12; // recommended IV length final int GCM_TAG_LENGTH = 128; // recommended tag length (bits)
byte[] iv = new byte[GCM_IV_LENGTH]; new SecureRandom().nextBytes(iv); GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey, gcmParameterSpec);
String plainText = "Sensitive Information"; byte[] encryptedText = cipher.doFinal(plainText.getBytes()); System.out.println("Encrypted securely with GCM: " + java.util.Base64.getEncoder().encodeToString(encryptedText)); }}Insufficient Key Size (RSA)
Description:
RSA security strongly depends on key size. 1024-bit RSA keys were once considered safe but are now much easier to break as computing power improved. Use 2048-bit or larger keys for stronger security.
Example (1024-bit RSA key pair):
import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.NoSuchAlgorithmException;
public class WeakRsaKeyExample { public static KeyPair generateWeakRSAKeyPair() throws NoSuchAlgorithmException { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(1024); // too short return keyPairGen.generateKeyPair(); }
public static void main(String[] args) throws Exception { KeyPair weakKeyPair = generateWeakRSAKeyPair(); System.out.println("Generated weak RSA key pair with key size: " + weakKeyPair.getPrivate().getEncoded().length * 8 + " bits"); }}Recommendations:
- Use at least 2048-bit RSA keys; for long-term security consider 3072/4096.
- Rotate keys regularly.
- Use strong randomness and vetted libraries for key generation.
Example (2048-bit RSA key pair):
import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.NoSuchAlgorithmException;
public class StrongRsaKeyExample { public static KeyPair generateStrongRSAKeyPair() throws NoSuchAlgorithmException { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(2048); // recommended return keyPairGen.generateKeyPair(); }
public static void main(String[] args) throws Exception { KeyPair strongKeyPair = generateStrongRSAKeyPair(); System.out.println("Generated strong RSA key pair with key size: " + strongKeyPair.getPrivate().getEncoded().length * 8 + " bits"); }}Hardcoded Passwords
Description:
Hardcoded plaintext passwords in source code/config/internal structures are highly insecure. Anyone who can access the code/files (devs, attackers via leaks, etc.) can obtain them. They are also hard to rotate, so a leak can cause long-term impact. This violates best practices.
Recommendations:
Never hardcode passwords. Store secrets outside of code (e.g., environment variables, secret stores) and avoid plaintext storage anywhere in the system.
Hardcoded Encryption Keys
Description:
Hardcoding encryption keys in code/config makes them easy to leak. Rotating keys requires code changes and redeployments, increasing risk and maintenance cost.
Recommendations:
- Store keys in environment variables or external secret stores (KMS/secret manager).
- Implement key rotation and safe decommissioning.
- Encrypt configuration files if keys must be stored there, and manage the encryption key securely.
- Enforce access control and auditing for systems storing keys.
- Use key derivation functions (PBKDF2/Argon2) where appropriate instead of hardcoded keys.
Hardcoded API Credentials
Description:
Hardcoding API keys/passwords/tokens in source code is unsafe and makes rotation hard. Leaks can lead to unauthorized access, data exposure, financial loss, etc.
Recommendations:
- Use environment variables.
- Use config files that are excluded from version control; encrypt in production.
- Use secret management services (AWS Secrets Manager, Azure Key Vault, etc.) with access control/auditing.
- Apply least privilege to the credentials.
- Rotate credentials regularly.
Plaintext Passwords in Configuration Files
Description:
Storing plaintext passwords in config files is a common security issue. Anyone with access can read them, and leaked configs can cause serious incidents. Config files also tend to be synced across environments, increasing exposure.
Recommendations:
- Use environment variables.
- Use secret management systems (AWS Secrets Manager, HashiCorp Vault, etc.).
- Encrypt secrets stored in config files so only the app can decrypt at runtime.
- Use config management tools (Spring Cloud Config, Consul) that support external loading and encryption.
Plaintext Passwords in Test Files
Description:
Hardcoding plaintext passwords in test code/data is unsafe. Test assets might accidentally ship to production, or source repositories might be accessed by unauthorized parties. Test environments are also often weaker than production.
Recommendations:
- Use environment variables for test credentials.
- Encrypt config files if secrets must exist there, and manage keys securely.
- Use secret managers for test environment credentials.
- Avoid real user accounts/passwords; use mocking where possible.
Protocols
Insecure Transport Protocol
Description:
SSL and early TLS versions (SSLv2/SSLv3/TLS 1.0/TLS 1.1) have known vulnerabilities (BEAST/POODLE/CRIME, etc.) and are not considered safe. Modern secure communication should use TLS 1.2 or TLS 1.3.
Example (unsafe SSLv3):
public class InsecureSSLExample { public static void main(String[] args) throws Exception { SSLContext context = SSLContext.getInstance("SSLv3"); context.init(null, null, null); SSLSocketFactory factory = context.getSocketFactory(); SSLSocket socket = (SSLSocket) factory.createSocket("example.com", 443); // insecure connection example }}Recommendations:
- Upgrade to TLS 1.2 or TLS 1.3.
- Disable SSLv2/SSLv3/TLS 1.0/TLS 1.1 on servers and clients.
- Patch OS/app/libs regularly to include the latest SSL/TLS fixes.
- Review and update crypto policies and configs regularly.
- Use secure cipher suites (avoid weak/broken ones).
Example (TLS 1.2):
public class SecureSSLExample { public static void main(String[] args) throws Exception { SSLContext context = SSLContext.getInstance("TLSv1.2"); // TLSv1.2 context.init(null, null, null); SSLSocketFactory factory = context.getSocketFactory(); SSLSocket socket = (SSLSocket) factory.createSocket("example.com", 443); // secure connection example }}Missing Content Security Policy (CSP)
Description:
CSP helps prevent XSS and other injection attacks by allowlisting which resources can be loaded/executed. Without CSP (or with a weak CSP), pages are easier to exploit via injected scripts.
Recommendations:
- Enable and properly configure CSP via the
Content-Security-Policyheader; strictly restrict script/style/img/font/form/resource sources to trusted origins. - Avoid
unsafe-inlineandunsafe-evalwhere possible. - Review and update CSP regularly as the app evolves.
- Use reporting (
report-uri/report-to) to collect violation reports. - Test thoroughly before rollout to avoid breaking legitimate resources.
Server Identity Verification Disabled
Description:
In SSL/TLS connections, verifying server identity is essential. Clients typically validate the certificate chain (trusted CA) and hostname match. If verification is disabled, the client can be vulnerable to MITM attacks.
Example (disables hostname verification):
public class InsecureConnection { public static void main(String[] args) throws Exception { HttpsURLConnection connection = (HttpsURLConnection) new URL("https://example.com").openConnection(); connection.setHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; // insecure: no verification } }); trustAllHttpsCertificates(connection); // assume this makes it trust all certs }
private static void trustAllHttpsCertificates(HttpsURLConnection conn) { // implementation omitted: trusts all certificates (unsafe) }Recommendations:
- Always enable server identity verification.
- Use correctly configured certificates issued by trusted CAs, with correct DNS names.
- Check certificate revocation status (OCSP/CRL) where appropriate.
- Enforce full certificate chain validation.
- Follow best practices and use secure libraries to avoid disabling validation accidentally.
Overly Broad Certificate Trust
Description:
Trusting too many certificates (including self-signed/untrusted ones) weakens security and enables MITM. Common anti-pattern: trusting all certificates.
Example (trust all certificates):
public class InsecureTrustManager { public static void main(String[] args) throws Exception { SSLContext sc = SSLContext.getInstance("TLS"); TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { } } }; sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // insecure: trusts all certificates }}Recommendations:
- Trust only known, reliable CAs (maintain an explicit trust store).
- Validate the full certificate chain (root + intermediates).
- Use certificate pinning when appropriate.
- Do not trust self-signed certs except in controlled environments (e.g., internal testing).
- Keep trust stores updated (add new CAs; remove revoked/unsafe ones).
Example (use system default trust manager):
public class SecureTrustManager { public static void main(String[] args) throws Exception { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, null, new java.security.SecureRandom()); // use system default trust manager HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // default trust manager trusts only certificates issued by trusted CAs }}Other
Weak Randomness
Description:
Using weak RNGs in security contexts (session ids, passwords, keys) can produce predictable values, enabling replay/session hijacking and other attacks. This often happens when using non-cryptographic PRNGs like Random.
Recommendations:
- Use a CSPRNG: e.g. Java
SecureRandom, notRandom. - Reseed when appropriate (especially after security events).
- Avoid custom RNG algorithms; use vetted implementations.
- Combine multiple entropy sources for high-security needs.
- Assess randomness strategy periodically.
Insecure Spring Default Configuration
Description:
In Spring Boot, management.security.enabled controls security for management endpoints. Misconfiguration (e.g. false) can expose sensitive endpoints (metrics, health, info, etc.) to unauthorized users.
Recommendations:
- Enable management endpoint security by default (
management.security.enabled=true). - Use roles/permissions to restrict access (Spring Security).
- Restrict network access (firewalls/security groups; internal-only).
- Use layered defenses (authn/authz/logging/monitoring).
- Review and update configuration regularly.