Prerequisite: Java 21, basic web application development Required tools: JDK 21, Maven, IntelliJ IDEA (or VS Code / Eclipse), Postman
Table of Contents
- Overview
- Broken Access Control
- Cryptographic Failures
- Injection
- Insecure Design
- Security Misconfiguration
- Vulnerable and Outdated Components
- Identification and Authentication Failures
- Software and Data Integrity Failures
- Security Logging and Monitoring Failures
- Server-Side Request Forgery (SSRF)
- Summary
- Overview
- Whitelisting
- Boundary Checking
- Character Escaping
- Numeric Validation
- Checking Null Bytes
- Checking newline characters
- Checking path corruption characters
- Checking extended UTF-8 attacks
- Summary
- Overview
- Secure session generation
- JSON Web Tokens (JWT)
- Management of concurrent connections
- Summary
- Overview
- Custom error pages
- Classification and exception handling
- Secure exception propagation
- Defining security policies for error handling
- Using framework-specific features
- Testing error handling
- Summary
1. Course Overview
This course focuses on secure coding in Java. Common misconceptions about cybercriminals: We often imagine individuals in dystopian environments, but in reality, the average age of a hacker is 17 years old. No application is too small or too insignificant to attract attackers — on the contrary, they are perfecting their techniques on smaller targets.
Main topics covered
- Cross-site scripting (XSS)
- Input validation
- OWASP Top 10
Objectives
At the end of this course, the developer will be able to secure their Java applications as if they were critical national infrastructure, applying military-grade security principles. The course combines practical demonstrations and theoretical knowledge to counter common security pitfalls.
Prerequisites
- Mastering Java 21
- Basic web application development
2. Top 10 OWASP vulnerabilities
2.1 Overview
The OWASP Top 10 is the collective wisdom on what makes web applications secure. It is the recommended starting point for adopting secure coding practices. Recognized worldwide by developers, it is strongly recommended that companies integrate it into their software development practices, in order to transform their development culture into one focused on security.
Paul Mooney shares his journey from breaking into some of the world’s largest e-commerce platforms to securing one of the world’s leading travel sites. He has collaborated with some of the most ingenious minds and faced the wrath of very disgruntled legal teams.
2.2 Broken Access Control
Position in the 2021 ranking: #1 (formerly #5 in 2017)
Statistics:
- 94% of apps tested for this issue
- Average incidence rate: 3.8%
- More than 318,000 occurrences in OWASP dataset
Highlighted weaknesses:
- Exposure of Sensitive Information to Unauthorized Parties
- Mismanagement of sensitive data and communications
- Vulnerabilities to Cross-Site Request Forgery (CSRF) attacks
Description: Broken Access Control is about ensuring that users stay within their permissions without exceeding them. If failed, this may lead to unauthorized access or alteration of data, or to the execution of actions beyond the scope of a user’s permissions.
Common errors:
- Ignoring least privilege or deny by default, leading to unnecessary access
- Manipulation of URLs, internal application states or API calls to bypass security controls
- Exploitation of Insecure Direct Object References (Insecure Direct Object References) to access another user’s account
- Access to APIs without the necessary controls to modify data
- Impersonation of users or administrators without proper credentials
- Manipulation of metadata, such as JWT, for unauthorized access
- Misconfiguration of CORS to allow access from untrusted origins
- Accessing pages requiring authentication without being authenticated
2.3 Cryptographic Failures
Position in 2021 ranking: #2 (formerly titled “Sensitive Data Exposure”)
Description: This category falls into the realm where cryptography — or lack thereof — plays the role of villain, often leaving sensitive data exposed to prying eyes. This is a gaping vulnerability in data protection.
Common Weaknesses:
- Using hard-coded passwords
- Reliance on fragile or risky cryptographic algorithms
- Insufficient Entropy
Sensitive data affected: Passwords, credit card numbers, medical records, personal information, trade secrets — subject to strict regulations like EU GDPR or PCI DSS for financial data.
Specific vulnerabilities:
- Data traveling unencrypted over networks (interception possible)
- Obsolete or weak cryptographic methods still present in the code
- Key management errors: default or weak keys, lack of rotation, keys committed to public repositories
- HTTP security directives and missing headers
- Failing server certificate validation
- Incorrect use of initialization vectors
- Insecure encryption modes (e.g. ECB)
- Using passwords as cryptographic keys without key derivation functions
- Improperly initialized cryptographic functions lacking unpredictability
- Deprecated hash functions (MD5, SHA-1) still in use – Crypto padding methods from a bygone era
- Oracle padding attacks exploiting error messages or side channels
2.4 Injection
Position in the 2021 ranking: #3
Statistics:
- 94% of applications tested for various injection risks
- Maximum incidence rate: 19%, average: 3%
- 274,000 documented cases
Notorious vulnerabilities:
- Cross-Site Scripting (XSS)
- SQL injection
- External check of file name or path
Description: At the heart of injection vulnerabilities is the mishandling of user-provided data. When applications fail to adequately validate, filter, or sanitize incoming data, they open the door to attacks.
Risk factors:
- Using dynamic queries or unparameterized calls that skip context escaping
- Hostile data infiltrating ORM search parameters to extract sensitive records
- Integration into SQL commands or stored procedures via concatenation or direct use
Injection types:
- SQL injection
- NoSQL injection
- OS command injection
- And many others, each exploiting the same fundamental flaw on different interpreters
Defense strategy:
- Rigorous code review to identify vulnerabilities that automated scans might miss
- Automated tests on all conceivable inputs: parameters, headers, URLs, cookies, etc.
- Integration of application security testing tools (SAST, DAST, IAST) into CI/CD pipelines
2.5 Insecure Design
Position in the 2021 ranking: #4 (new category)
Description: This new category for 2021 highlights the risks inherent in design and architectural flaws, urging deeper integration of threat modeling, secure design patterns, and reference architectures into the development process. It is a call to action to extend the shift left approach from coding practices to pre-code activities.
Highlighted weaknesses:
- Unintentional disclosure of sensitive information via error messages
- Unprotected storage of credentials
- Trust boundaries violations (trust boundaries)
- Credentials insufficiently protected
Crucial distinction: A secure design can still be plagued by implementation flaws. However, an inherently insecure design cannot be rectified through flawless implementation — if it omits essential security controls against specific threats.
Recommended approach:
- Collection and negotiation of business and protection requirements, taking into account confidentiality, integrity, availability and authenticity of data
- Assessment of the exposure level of the application and the need for tenant segregation
- Budget planning for all phases: design, build, test and operations
- Integration of threat modeling in the development cycle
- Using the OWASP Application Security Verification Standard (ASVS) to structure and improve secure software development efforts
Security as culture: Secure design transcends a simple addition or tool. It is a culture and methodology focused on constantly assessing threats and creating code that is inherently resistant to known attack vectors.
2.6 Security Misconfiguration
Position in the 2021 ranking: #5 (formerly #6)
Statistics: – Affects 90% of applications
- Average incidence rate: 4.4%
- Over 208,000 occurrences of relevant CWE (Common Weakness Enumerations)
Highlighted weaknesses:
- Incorrect configurations
- Incorrect restriction of XML external entity references (XXE)
Common sources of vulnerabilities:
- Lack of complete security hardening across the entire application stack
- Permissions incorrectly configured on cloud services
- Presence of unnecessary features: redundant ports, services, pages, accounts or privileges
- Default accounts with unchanged passwords
- Revealing stack traces or detailed error messages to users
- Disabling or insecure configuration of security features in updated systems
- Sub-optimal configurations of application servers, frameworks (Spring), libraries and databases
- Failure to send security headers or insecure values
- Use of outdated or vulnerable software components
Solution: Establish a deliberate and repeatable process for configuring application security. Without it, systems remain dangerously exposed to attacks.
2.7 Vulnerable and Outdated Components
Position in the 2021 ranking: #6
Special feature: This category does not have CVE (Common Vulnerabilities and Exposures) directly associated with it. It has a default impact weight of 5.0. It highlights the testing and risk assessment challenges of using outdated or unmaintained third-party components.
Susceptibility conditions:
- Ignoring versions of all components used (client side and server side), including direct dependencies
- Use of vulnerable, unmaintained or obsolete software (OS, web or application servers, DBMS, APIs, execution environments, libraries)
- Lack of regular vulnerability scanning or monitoring of security bulletins for the components used
- Delays in addressing or updating critical platform, framework, and dependency vulnerabilities due to infrequent patching schedules
- Developers unaware of the need to test compatibility of updated or patched libraries
- Insecure configurations of these components, related to the broader security misconfigurations issue
Corrective measures:
- Know the exact versions used
- Stay up to date with software and security updates
- Ensuring compatibility and secure configurations
2.8 Identification and Authentication Failures
Position in the 2021 ranking: #7
Description: Applications may be vulnerable if they allow automated attacks like credential stuffing (where attackers use known valid credentials to gain unauthorized access).
Common vulnerabilities:
- Lack of adequate defense against brute-force attacks
- Acceptance of default, weak or common passwords (e.g.
password1,admin/admin) - Fragile or ineffective mechanisms for recovering forgotten credentials and passwords
- Storing passwords in plaintext or using weak encryption or hashing methods
- Lack of robust multi-factor authentication (MFA)
- Exposure of session identifiers in URLs
- Post-login session credential reuse
- Non-invalidation of session IDs or authentication tokens, particularly in the context of SSO (Single Sign-On) systems when disconnecting or after periods of inactivity
Mitigation strategy: Multi-faceted approach incorporating strong password policies, secure credential storage, efficient user authentication processes and rigorous session management practices.
2.9 Software and Data Integrity Failures
Position in the 2021 ranking: #8 (new category)
Description: This new 2021 category highlights perilous assumptions about the integrity of software updates, critical data, and CI/CD pipelines without necessary verifications. Coming from CVSS (Common Vulnerability Scoring System) data, it presents one of the highest weighted impacts.
Key vulnerabilities:
- Dependency on plugins, libraries or external modules from untrusted entities (repositories and CDN) not sufficiently protecting against integrity violations
- Security lapses in the CI/CD pipeline that could lead to unauthorized access, introduction of malicious code, or complete system compromise
- Automatic update functionality proceeds without thorough update integrity checking
- Insecure deserialization: objects or data serialized in a format that can be observed and manipulated by an attacker pose a substantial risk
2.10 Security Logging and Monitoring Failures
Position in the 2021 ranking: #9 (formerly in last position in 2017)
Description: Raised to a more prominent status following feedback from the OWASP community. Although difficult to test (often relying on interviews or detecting attacks during penetration testing), this category highlights the indispensable role of diligent logging and monitoring in detecting and responding to breaches.
Impact on:
- Accountability
- Visibility
- Incident Alerts
- Forensic analysis
Scope expansion: The category now addresses not only insufficient logging, but also:
- Incorrect neutralization of log outputs
- Omission of security-relevant information
- Inserting sensitive data into log files
Manifestations of insufficiency:
- Do not log significant events (connections, connection failures, key transactions)
- Generate inadequate or unclear warnings and errors
- Do not monitor application and API logs for suspicious activity
- Local storage of logs without centralized analysis
- Lack of effective alert thresholds and response processes
- Penetration testing tools (DAST) unable to trigger alerts
- Failure to detect, escalate, or alert on active attacks in real-time or near real-time
Additional risk: Information leaked via logging and alerting mechanisms, linking this issue to Broken Access Control issues.
2.11 Server-Side Request Forgery (SSRF)
2021 Ranking Position: #10 (community powered)
Description: SSRF vulnerabilities occur when a web application makes a request to a remote resource without properly validating the user-supplied URL. This negligence allows attackers to manipulate the application to send requests to unintended destinations, bypassing firewalls, VPN and ACL network access control.
Increase factors: The rise of SSRF vulnerabilities is linked to the functional evolution of modern web applications which increasingly retrieve URLs to provide rich functionality to end users. The growing adoption of cloud services and the complexity of architectures are expanding the attack surface.
Potential implications: Access to or manipulation of internal systems and sensitive data, posing a direct threat to the security of web applications and their underlying infrastructure.
Significance of entry in OWASP Top 10: Call to action for developers and security professionals to prioritize validation of user-provided data, including URLs.
2.12 Summary
The OWASP Top 10 is not just a set of guidelines, but a cornerstone of secure coding practices. The goal is to transform the organizational culture toward one that prioritizes security above all else, in order to protect web applications against the most widespread risks.
3. Input Validation
3.1 Overview
Input validation in Java is a key concept underlying secure coding practices. It acts as a critical filter ensuring that only well-formed data passes through the application workflow. Critical step to maintain data integrity and prevent malfunction of downstream components.
Demo application: A simple application for healthcare administrators to manage patient data. The application uses:
- JDK 21
- Maven
- IntelliJ IDEA
- H2 database for data persistence
- Postman to test endpoints
Demo format:
- Open the code in IntelliJ
- Select the appropriate branch (named according to their associated section, e.g. boundary-checking, whitelisting, etc.)
- Run the code
- Once the server is launched, test with Postman
Why validate entries from the start? Simply to detect potential problems at the root. By validating data as it enters a system from external sources, the risk of downstream problems is significantly reduced.
3.2 Whitelisting
Definition: Whitelisting in the context of Java and web security is a defensive coding strategy recommended by OWASP to ensure that only pre-approved data, operations, or interactions are permitted within an application.
Principle: deny-by-default — anything not explicitly allowed is prohibited.
Contrast with blacklisting: Unlike blacklisting (where known bad entities are blocked, but unknown threats can still get through), whitelisting embodies the deny-by-default principle.
Application areas of whitelisting in Java:
-
Input Validation: Validate any input against a set of authorized characters or patterns (eg: only numeric characters in a field expecting an integer). Crucial for preventing injection attacks.
-
File operations: Whitelist of file extensions for uploads (eg: only allow
.jpgand.pngfor an image upload). -
Class Loading: Whitelist of classes or packages that can be loaded dynamically, preventing the execution of untrusted code.
-
API Interactions and External Services: Limit the external APIs and services that the application can interact with, reducing the attack surface.
Implementation — example of the addNotes function:
// Liste des patterns autorisés
List<String> whitelist = Arrays.asList("Admitted", "Reviewed", "Discharged");
// Vérification si le paramètre 'notes' contient un des patterns de la whitelist
boolean isValid = whitelist.stream()
.anyMatch(pattern -> {
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(notes);
return m.find();
});
if (!isValid) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body("Invalid input: notes must contain an approved term.");
}
// Si valide, on ajoute les notes
patientRepository.addNotes(id, notes);
return ResponseEntity.ok().build();
Explanation of code:
whitelist.stream(): converts the whitelist into a stream for functional operationsanyMatch: terminal operation checking if elements of the stream match a predicate- If no pattern matches,
isValidisfalseand a400 Bad Requestresponse is returned - If input passes validation, notes are added with a
200 OKreturn
Postman demo — steps:
- Launch IntelliJ and open the project
- Open Postman and create a new POST request
- URL:
http://localhost:8080/patients/{id}/notes(replace{id}with a real patient ID) - Add a
Content-Type: text/plainheader - Select raw for body
- Test with compliant text (
200 OKresponse) and non-compliant text (400 Bad Requestresponse) - Check the H2 database to confirm that only compliant notes have been added
Best practices:
- Regularly update whitelists to reflect application functional changes
- Apply whitelists comprehensively to all potential attack vectors
- Maintaining a balance between security and application performance
3.3 Boundary Checking
Definition: Boundary checking is a fundamental security and reliability practice in Java development ensuring that data operations remain within the defined limits of allocated memory or data structures.
Objectives:
- Prevent buffer overflow attacks
- Avoiding ArrayIndexOutOfBoundsException errors
- Ensuring data integrity
Built-in Java protections:
Java provides a level of protection against bounds issues via exceptions like ArrayIndexOutOfBoundsException. However, relying solely on these mechanisms is insufficient for security-sensitive applications.
Application of boundary checking in Java:
- Array access: Always check the length of arrays before accessing them with an index
- Java Collections: Be careful with indexes or keys, use methods like
size() - Buffers: Check the capacity and current position of a buffer before reading/writing
- Strings: Ensure that the start and end indexes are within the bounds of the string length
Implementation — validation by length in addNotes:
@PostMapping("/patients/{id}/notes")
public ResponseEntity<?> addNotes(@PathVariable String id, @RequestBody String notes) {
int minLength = 10;
int maxLength = 500;
if (notes.length() < minLength || notes.length() > maxLength) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body("Notes must be between " + minLength + " and " + maxLength + " characters.");
}
patientRepository.addNotes(id, notes);
return ResponseEntity.ok().build();
}
Protection against:
- Buffer overflow attacks (excessively long entries to exploit vulnerabilities)
- Injection attacks (which can use inputs of specific lengths or patterns to manipulate operations)
Postman Demo:
- Entries with length outside limits → response
400 Bad Request - Valid entries → response
200 OK
Best practices:
- Perform boundary checks as early as possible before using the data
- Implement and reuse a centralized validation mechanism
- Leverage Java’s built-in methods and libraries that inherently perform boundary checks
- Implement robust error handling to gracefully handle boundary violations, logging without exposing sensitive information
- Integrate boundary checking into security testing practices (unit tests, fuzz testing, penetration tests)
3.4 Character Escaping
Definition: character escaping is an essential security technique in Java and web development aimed at preventing injection attacks and ensuring the secure handling of data that can be interpreted by a parser or interpreter.
Principle: Escaping involves substituting special characters with a sequence of characters that the interpreter recognizes as a literal representation rather than as part of a control syntax.
Application contexts:
-
HTML and XML escaping: When dynamically generating HTML or XML content with user-supplied data, use Java libraries like the OWASP Java Encoder to prevent XSS attacks
-
SQL: Use prepared statements and parameterized queries provided by JDBC rather than manual string concatenation. If dynamic SQL generation is unavoidable, apply appropriate escaping via library support
-
JavaScript: When inserting user-controlled data into JavaScript code blocks, escape characters interpreted as controls (quotes, backslashes)
-
URL encoding: When constructing URLs with user-provided data, encode characters with special meanings in URLs
Implementation — sanitization with StringEscapeUtils:
@PostMapping("/patients/{id}/notes")
public ResponseEntity<?> addNotes(@PathVariable String id, @RequestBody String notes) {
// Sanitisation des notes par échappement des caractères spéciaux JSON
String sanitizedNotes = StringEscapeUtils.escapeJson(notes);
patientRepository.addNotes(id, sanitizedNotes);
return ResponseEntity.ok().build();
}
The escapeJson method:
Iterates through the input string and replaces characters with special meaning in JSON context with their escaped versions. For example, a double quote is replaced with \", making it safe to include in a JSON string.
Best practices:
- Use context escaping — policy must match context (HTML, SQL, JavaScript)
- Leverage well-established libraries and frameworks that automatically handle character escaping
- Complete escaping with input validation
- Apply escaping evenly throughout the application
- Keep libraries and frameworks up to date
- Understanding the difference between escaping and encoding
3.5 Numeric Validation
Definition: numeric validation is a critical aspect of input validation in Java ensuring that data processed or entered into an application meets specific numerical constraints.
Vital for:
- Maintain data integrity
- Prevent application errors
- Avoid security vulnerabilities (numeric overflow attacks, SQL injection, logic flaws)
Key practices:
- Ensure data is of the correct numeric type (integers, floating point numbers, etc.)
- Validate that numeric values fall within the expected range (e.g. a person’s age between 1 and 120)
- Check precision and scale (especially for financial applications)
- Implement checks to prevent overflows and underflows
- Choose appropriate Java data types (
BigInteger,BigDecimalfor large numbers or high precision)
Implementation — integer validation in addNotes:
@PostMapping("/patients/{id}/notes")
public ResponseEntity<?> addNotes(@PathVariable String id, @RequestBody String notes) {
// Vérifier si notes est un entier valide
try {
Integer.parseInt(notes);
} catch (NumberFormatException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body("Invalid input: notes must be an integer value.");
}
patientRepository.addNotes(id, notes);
return ResponseEntity.ok().build();
}
Recommended libraries:
- Apache Commons Validator
- Hibernate Validator
Advanced considerations:
- Understand the context in which digital data is used (e.g. digital IDs may require uniqueness checks)
- Implement comprehensive error handling without exposing sensitive details
- Take into account internationalization problems (decimal separators, grouping of numbers)
3.6 Checking Null Bytes
Definition: Checking null bytes is an essential data security and integrity practice. Null bytes can be used in a variety of attacks, including null byte injection, where attackers exploit the null byte to bypass security checks, manipulate file operations, or prematurely terminate strings.
Risks: In many programming languages and environments, the null byte signifies the end of a string. Attackers can exploit this characteristic to manipulate software behavior.
Mitigation strategies:
- Validate all incoming data to ensure it does not contain null bytes, especially data passed to file systems, databases or external systems
- Use regular expressions or explicit checks to filter or replace null bytes
- Implement sanitization routines checking and removing null bytes before processing
- Perform boundary checks to ensure that null bytes in data buffers do not lead to incorrect termination of the data stream
Implementation — null byte check in addNotes:
@PostMapping("/patients/{id}/notes")
public ResponseEntity<?> addNotes(@PathVariable String id, @RequestBody String notes) {
// Vérification de la présence d'un null byte
if (notes.contains("\0")) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body("Invalid input: notes must not contain null bytes.");
}
patientRepository.addNotes(id, notes);
return ResponseEntity.ok().build();
}
Tests with Postman: Testing null bytes directly in Postman can be complex. Use automated tests or alternative tools capable of including null bytes in requests.
Additional vigilance: Be particularly careful when Java applications must interact with native code or systems where the handling of null bytes differs significantly from the Java string model.
3.7 Checking newline characters
Context:
Newline characters (\n, \r\n), although seemingly harmless, can be exploited in various security attacks.
Specific risks:
-
Log injection (Log forging): If user input containing newline characters is logged as is, this can lead to log tampering where malicious entries are indistinguishable from legitimate logs.
-
HTTP response splitting: Newline characters inserted in headers can allow attackers to add arbitrary headers or control the response body.
Implementation — rejecting newlines in addNotes:
@PostMapping("/patients/{id}/notes")
public ResponseEntity<?> addNotes(@PathVariable String id, @RequestBody String notes) {
// Vérification des caractères de nouvelle ligne
if (notes.contains("\n") || notes.contains("\r")) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body("Invalid input: notes must not contain newline characters.");
}
patientRepository.addNotes(id, notes);
return ResponseEntity.ok().build();
}
Best practices:
- Rigorously validate all user input to detect and mitigate unwanted newline characters
- Sanitization must aim to remove or escape newline characters, particularly in sensitive contexts such as logging or setting HTTP headers
- Use logging libraries that automatically sanitize log messages
- In web applications, apply content security policies (CSP) that mitigate the impact of newline characters in headers and HTTP responses
- Integrate automated tools into the CI/CD pipeline capable of detecting incorrect processing of newline characters
3.8 Checking Path Alteration Characters
Context:
path alteration characters such as .. (parent directory access), / (slash) and \ (backslash) can be exploited to access unauthorized files and directories in path traversal attacks.
Risk: Applications that dynamically construct file paths based on user input are particularly vulnerable. This may lead to unauthorized access, disclosure of sensitive information, or execution of malicious files.
Advanced strategies:
- Canonical resolution: Resolve paths to their canonical form with
File.getCanonicalPath()to neutralize directory traversal attempts - Whitelist of paths: Define a list of authorized paths and reject any path that does not match (positive security model, much more effective than the blacklist)
- Principle of least privilege: Run the application with the minimum necessary rights, limiting the impact of a successful path traversal attack
Implementation — silent sanitization of path alteration characters:
@PostMapping("/patients/{id}/notes")
public ResponseEntity<?> addNotes(@PathVariable String id, @RequestBody String notes) {
// Suppression des caractères d'altération de chemin (., \, /)
String sanitizedNotes = notes.replaceAll("[.\\\\/ ]", "");
patientRepository.addNotes(id, sanitizedNotes);
return ResponseEntity.ok().build();
}
Special behavior:
Unlike the previous examples, this function silently removes characters rather than returning an error. All calls return 200 OK except in the event of a system error (eg: database offline). Path corruption characters are simply discarded before storage.
Best practices:
- Configure servers, frameworks and libraries with secure default configurations that inherently mitigate path traversal vulnerabilities
- Perform periodic audits and code reviews focused on identifying incorrect handling of path alteration characters
- Integrate automated security testing tools into the development pipeline
3.9 Checking extended UTF-8 attacks
Context: extended UTF-8 attacks exploit the way applications handle, validate, or sanitize UTF-8 encoded input. These attacks exploit the complexity of UTF-8 encoding to bypass security mechanisms or cause unexpected behavior.
UTF-8: Variable-width character encoding system that can encode all 1,112,064 valid Unicode code points using 1 to 4 1-byte (8-bit) code units.
Extended UTF-8 attack types:
- Overlong encodings: Encoding a character in more bytes than necessary
- Invisible characters: Invisible characters bypassing visual filters
- Context-dependent interpretation: Characters handled differently by different components or layers of an application
Potential vulnerabilities:
- SQL injection
- Cross-Site Scripting (XSS)
- Bypass validation filters
Implementation — ASCII character filtering:
@PostMapping("/patients/{id}/notes")
public ResponseEntity<?> addNotes(@PathVariable String id, @RequestBody String notes) {
// Ne conserver que les caractères ASCII (code <= 127)
String sanitizedNotes = notes.chars()
.filter(c -> c <= 127)
.collect(StringBuilder::new,
StringBuilder::appendCodePoint,
StringBuilder::append)
.toString();
if (sanitizedNotes.length() != notes.length()) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body("Invalid input: only ASCII characters are allowed.");
}
patientRepository.addNotes(id, sanitizedNotes);
return ResponseEntity.ok().build();
}
Strategy: Filter the input to include only ASCII characters (0 to 127 inclusive) — standard English letters, numbers, and control characters.
Best practices:
- Beyond validation, filter inputs to remove or escape unwanted characters
- When using regular expressions for validation or filtering, ensure they are designed to handle UTF-8 securely
- Maintain consistent character encoding across application (no mixing of encodings)
- Keep the development team informed of potential risks associated with extended UTF-8 characters
- Implement detailed validation failure logging
- Ensure that legitimate use of extended UTF-8 characters (such as those required for internationalization) is not negatively affected
3.10 Summary
Securing Java applications through input validation is a comprehensive, robust and adaptable defensive strategy:
- Whitelisting: First level of defense allowing only known secure interactions, minimizing potential attack vectors
- Boundary checking: Strengthens the fortress by ensuring that data does not exceed its predefined limits, essential to thwart buffer overflow attacks
- Character escaping: Transforms special characters into non-executable sequences, particularly effective against injection attacks
- Numeric validation: Key role in ensuring that numeric inputs remain within expected limits, preventing errors and vulnerabilities
- Null bytes and newline characters: Specialized practices to counter specific exploitation techniques
- Path alteration characters: Vital for preventing directory traversal attacks
- Extended UTF-8 attacks: Against character encoding complexities to bypass validation mechanisms
4. Applying Encoding
4.1 Overview
This module covers the critical concept of encoding and sanitization, the cornerstone of developing secure web applications.
Encoding purpose: Protect against injection attacks, including Cross-Site Scripting (XSS). These attacks exploit unencoded user input to execute malicious scripts in users’ browsers.
Module content:
- Output encoding mechanics
- Practical application in demo Java application
- Java libraries and frameworks with built-in output encoding functions – Contextual encoding and its importance
- OWASP Best Practices
- Protection against SQL injection via parameterized queries
4.2 Encoding mechanics
Problematic characters:
Angle brackets (<, >) and quotation marks (", ') are not simple textual elements — they are the syntax that web documents rely on. Their misuse via user input can turn innocent data into vectors for XSS attacks.
HTML entity encoding: Converts special characters to a format that browsers interpret as simple text, not executable code.
| Character | HTML Entity |
|---|---|
< | < |
> | > |
" | " |
' | ' |
& | & |
Stored XSS attack — demonstration:
Attack scenario:
- An attacker submits the following JavaScript code as a patient note:
<script>alert('XSS')</script> - Without sanitization, this code is stored in the database
- When a doctor or nurse views the patient’s data, the malicious script is picked up and executed in the browser
Why the script may run: The critical vulnerability lies in dynamically adding notes to a script tag and attaching it to the document body. If the notes contain JavaScript code, it will be executed immediately.
Reflected XSS attack: The malicious script is not stored, it is reflected by the web server as part of an immediate response triggered by the user’s request. Often achieved via a URL which, once visited, sends a request to the server with the script in the query string. Note: Most modern browsers have built-in protection against this.
Implementation — sanitization with OWASP Java HTML Sanitizer:
@PostMapping("/patients/{id}/notes")
public ResponseEntity<?> addNotes(@PathVariable String id, @RequestBody String notes) {
// Création d'une politique de sanitisation
PolicyFactory sanitizer = Sanitizers.FORMATTING.and(Sanitizers.LINKS);
// Application de la politique aux notes
String sanitizedNotes = sanitizer.sanitize(notes);
// Stockage des notes sanitisées uniquement
patientRepository.addNotes(id, sanitizedNotes);
return ResponseEntity.ok().build();
}
Explanation:
Sanitizers.FORMATTING: allows basic formatting tagsSanitizers.LINKS: allows links- The
sanitizeexamines the note string and removes or neutralizes any potentially harmful elements that do not match the defined safe content - Potentially dangerous original entry never reaches database
Result:
If an attacker tries to inject a <script> tag or any other malicious content, the sanitizer deletes or neutralizes this content. When the notes are later displayed on a web page, there is no malicious script to execute.
4.3 SQL Injection
Definition: SQL injection is an attack technique where an attacker skillfully manipulates SQL queries to gain unauthorized access to the database.
Classic example:
On a login page, instead of a username, we enter 'OR '1'='1. If the application does not properly protect its queries, this entry can break the intended SQL command and fool the database:
-- Requête normale attendue
SELECT * FROM users WHERE username = 'alice' AND password = 'secret';
-- Requête avec injection
SELECT * FROM users WHERE username = '' OR '1'='1' -- ' AND password = 'anything';
This condition is always true, potentially giving access to an attacker without a valid password.
Dangers of SQL injection: Not only spy on data, but also manipulate or destroy it. An attacker can access personal information, alter records, or even delete entire tables.
Solution: Prepared Statements
// Mauvaise pratique — vulnérable à la SQL injection
String query = "UPDATE patients SET notes = '" + notes + "' WHERE id = '" + id + "'";
statement.execute(query);
// Bonne pratique — requête paramétrée
private static final String ADD_NOTES =
"UPDATE patients SET notes = ? WHERE id = ?";
public void addNotes(String id, String notes) {
try (PreparedStatement stmt = connection.prepareStatement(ADD_NOTES)) {
stmt.setString(1, notes); // Traitement comme DONNÉE, pas comme code SQL
stmt.setString(2, id);
stmt.executeUpdate();
}
}
How prepared statements work:
- SQL string
ADD_NOTESdefines an SQL command with?as placeholders for parameters - A
PreparedStatementis created from theconnectionobject with the request as a template - The
setStringmethod assigns values to placeholders — input is treated strictly as a value, eliminating the risk of execution as part of the SQL command - Even if an attacker tries to inject malicious SQL code into
notesorid, the database will treat it as simple text
Basic principle:
Never trust user input.
4.4 Summary
This module covered two major aspects of application security:
- Output Encoding / Cross-Site Scripting:
- Output encoding is the critical role of web security
- Unsanitized input may lead to script execution in other user browsers
- Implementing proper encoding practices to transform input data into secure display
- SQL Injection:
- Parameterized queries are pivotal in preventing SQL injection attacks
- By using placeholders and treating input strictly as data, we protect Java applications against malicious SQL injections
- Alignment with OWASP recommendations:
- Using OWASP Java HTML Sanitizer for Sanitization Policies
- Using prepared statements to secure interactions with the database
5. Authentication and password management
5.1 Overview
This module is designed to provide the knowledge and skills necessary to implement robust authentication and secure password management practices in Java applications.
Contents:
- Authentication mechanisms supported by Java
- Basic authentication up to advanced SSO protocols
- Best practices for password storage and management
- Cryptographic hashing and salting
- Strong Password Policies
5.2 Communication of authentication data
Encrypted channels
Secure transmission of authentication data relies on the use of encrypted channels. When a user connects to a Java application, their credentials must pass through the network securely. The use of Transport Layer Security (TLS) ensures that this data is encrypted, making it indecipherable to eavesdroppers. It is also crucial to validate security certificates to prevent man-in-the-middle attacks.
Logging Risks
A subtle but significant risk in transmitting authentication data is its unintentional logging. HTTP logs, if not properly sanitized, can store sensitive information. Implement rigorous logging policies to ensure that authentication data (passwords, security tokens) is either encrypted or completely omitted from the logs.
Authentication Validation
Validating authentication in Java goes beyond simple username/password matching verification:
- Implement secure hashing algorithms: bcrypt or PBKDF2 (designed to be computationally intensive, thwarting brute-force attacks)
- The validation process must be resilient against injection attacks (prepared statements and appropriate input sanitization)
Balanced error messages
Create error messages that provide enough information for real users to correct their errors without offering clues to attackers:
- Too vague: “Login Failed” → frustrating for the user
- Too specific: “Username Not Found” → helps attackers
- Recommended: A generic message like “Invalid identifiers” without specifying which one
Monitoring login attempts
Applications must have mechanisms to log and analyze connection attempts, identifying patterns that could indicate an attack (rapid attempts, connections from geographically disparate locations).
Timing Attacks
Timing attacks are a class of side-channel attacks where the attacker determines information based on the execution time of cryptographic operations. To mitigate: use constant temporal comparison functions that offer no clues via temporal analysis.
5.3 Validation and storage of authentication data
Secure Hash
Hash is a one-way function transforming a password into a unique string of characters. Unlike encryption (designed to be reversible), hashing is irreversible.
Recommended algorithms for storing passwords:
- bcrypt — resistant to brute-force attacks
- PBKDF2 (Password-Based Key Derivation Function 2) — recognized and recommended
- Scrypt — designed to be resistant to brute-force hardware attacks
Avoid for storing passwords:
- SHA-256, SHA-3 (too fast to be secure as password hashing algorithms)
Salting
A salt is a unique random string added to each password before it hashes. Purpose: to ensure that identical passwords do not produce the same hash, thwarting rainbow table attacks.
In Java, salts can be generated with the SecureRandom class, guaranteeing the uniqueness of each password hash.
Implementation with bcrypt
// Création de l'encodeur bcrypt
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String originalPassword = "securePassword";
// Hachage du mot de passe (salt inclus automatiquement)
String hashedPassword = passwordEncoder.encode(originalPassword);
System.out.println("Original: " + originalPassword);
System.out.println("Hashed: " + hashedPassword);
// Vérification du mot de passe
boolean matches = passwordEncoder.matches("securePassword", hashedPassword);
The BCryptPasswordEncoder class handles both hashing and salting, abstracting the complexities. In practice, never log the original password — this is a security risk.
Implementation with PBKDF2
public String hashPassword(String password) throws Exception {
byte[] salt = getSalt();
PBEKeySpec spec = new PBEKeySpec(
password.toCharArray(),
salt,
65536, // Nombre d'itérations — plus élevé = plus sécurisé
256 // Longueur de la clé en bits
);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] hash = factory.generateSecret(spec).getEncoded();
// Retourner : itérations:salt:hash (en hexadécimal)
return 65536 + ":" + toHex(salt) + ":" + toHex(hash);
}
private byte[] getSalt() throws Exception {
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
byte[] salt = new byte[16];
sr.nextBytes(salt);
return salt;
}
Key factor of PBKDF2: The number of iterations — higher = more calculation time required, making brute-force attacks exponentially more difficult.
Implementation with Scrypt
// Scrypt avec la bibliothèque Bouncy Castle
public String hashPasswordScrypt(String password, byte[] salt) {
int N = 16384; // CPU/memory cost
int r = 8; // Block size
int p = 1; // Parallelization
int dkLen = 32; // Hash length
byte[] hash = SCrypt.generate(
password.getBytes(), salt, N, r, p, dkLen
);
return toHex(hash);
}
Advantage of Scrypt: Not only increases calculation time, but also requires a significant amount of memory, making large-scale hardware attacks more difficult.
Note: Java does not provide built-in support for Scrypt in its standard library — use third-party libraries like Bouncy Castle or the Scrypt package.
Password complexity validation
public boolean isPasswordComplex(String password) {
// Doit contenir : chiffres, majuscules, minuscules,
// caractères spéciaux, longueur 8-20
String pattern = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,20}$";
return password.matches(pattern);
}
Token management
tokens are randomly generated strings used to manage sessions or password resets. Features:
- Short life
- Easily invalidated
- Generated with
SecureRandomto prevent predictability
5.4 Summary
This module made it possible to acquire:
- An in-depth understanding of various authentication mechanisms in Java
- Using TLS for secure data transmission
- Protection against man-in-the-middle attacks
- Critical aspects of password management: cryptographic hashing, salting (bcrypt, PBKDF2, Scrypt)
- The importance of strong password policies
- How to prevent sensitive data from appearing in HTTP logs
- Monitoring suspicious login activities
- Mitigation of timing attacks
6. Session Management
6.1 Overview
Secure session management is the cornerstone of securing user interactions on the web. A compromised session can open the door to data breaches and identity theft, putting users and businesses at risk.
Module content:
- Secure session generation, management and termination
- Session identifiers: preventing session hijacking and session fixing
- Managing JSON Web Tokens (JWT) for stateless authentication
- Concurrent Sessions and Robust Disconnect
- Rate limiting
6.2 Secure session generation
Basic Properties of Session ID
A Session ID must be:
- Unique for each session
- Unpredictable to prevent unauthorized access by session hijacking (stealing a session ID to impersonate) or session fixation (tricking a user into using a known session ID)
Generation with SecureRandom
// Génération d'un session ID cryptographiquement sécurisé
public String generateSessionId() throws Exception {
SecureRandom secureRandom = new SecureRandom();
byte[] bytes = new byte[16]; // 16 octets = 128 bits
secureRandom.nextBytes(bytes);
// Encodage en base64 pour un format lisible
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
}
SecureRandom automatically collects entropy from the host operating system. It is crucial to ensure that system sources have sufficient entropy, especially in environments with high demand or with limited interactions (servers without a GUI).
Secure Session ID storage
Use of cookies with specific attributes improving security:
- HttpOnly: Prevents access to the cookie via JavaScript (protection against XSS)
- Secure: Sending the cookie only over secure connections (HTTPS)
- SameSite=Strict: Prevents the browser from sending this cookie with cross-site requests (protection against CSRF)
6.3 JSON Web Tokens (JWT)
Definition: JSON Web Tokens (JWT) are compact, URL-secure tokens used to securely transmit information between parties in the form of a JSON object. This information can be verified and reliable because it is digitally signed.
Signing algorithms:
- HMAC with secret
- Public/private key pair RSA or ECDSA
Structure of a JWT (6 parts)
- Header: Type of token (JWT) and signature algorithm (HMAC-SHA256 or RSA)
- Payload (Claims):
- Registered claims:
iss(issuer),exp(expiration time),sub(subject),aud(audience) - Public claims: Freely defined, registered in the IANA JSON Web Token registry
- Private claims: Personalized claims shared between parties
- Signature
Java Libraries for JWTs
- java-jwt
- JJWT
Implementation — creating a JWT in a secure cookie
public ResponseEntity<?> createSession(String userId) {
// Génération du JWT
String jwt = generateJWT(userId);
// Construction du cookie Set-Cookie
String cookieValue = "Authorization=" + jwt + "; "
+ "Path=/; "
+ "HttpOnly; " // Pas d'accès JavaScript (protection XSS)
+ "Secure; " // HTTPS uniquement
+ "SameSite=Strict"; // Protection CSRF
return ResponseEntity.ok()
.header("Set-Cookie", cookieValue)
.body("Session created");
}
private String generateJWT(String userId) {
long now = System.currentTimeMillis();
long expiration = now + 3600000; // 1 heure
return Jwts.builder()
.setSubject(userId) // Identifiant unique de l'utilisateur
.setIssuedAt(new Date(now)) // Horodatage d'émission
.setExpiration(new Date(expiration)) // Horodatage d'expiration
.signWith(getSecretKey(), SignatureAlgorithm.HS256) // Signature avec clé secrète
.compact(); // Sérialisation en chaîne
}
Important considerations:
- Use a strong, properly managed and secure signing key (predefined base64 key stored securely)
- Thoroughly validate JWTs on each request
- Be careful with the information included in the JWT — it can be easily decoded (although not modifiable without the key)
- Set appropriate expiration times for tokens
6.4 Managing concurrent connections
Tracking active sessions
Maintain a mapping of user IDs to session information (creation time, IP address, relevant metadata). Store this data in a fast-access datastore like Redis or an in-memory database.
Concurrent session limit policy
If a new user logs in and has already reached the maximum number of active sessions, choose a strategy:
- Refuse new session
- Invalidate oldest or least recently used session
Rate Limiting
To prevent brute-force attacks: Limit the number of login attempts from a single IP address or user account within a given time period. After reaching this limit, block additional attempts or require additional authentication (CAPTCHAs).
Java libraries for rate limiting:
- bucket4j
- Guava’s RateLimiter
Types of rate limits:
- Global: Applies to all users or IP addresses, preventing widespread misuse
- Local: Focus on individual user accounts or IP addresses
Network layer: Tools like NGINX or hardware appliances can be configured to provide an additional layer of rate limiting before traffic reaches your application service. Particularly effective in mitigating DDoS attacks.
6.5 Summary
This module allowed us to deepen:
- The foundations of session management (generation, management, secure termination)
- Correct handling of session identifiers to prevent session hijacking and session fixation
- The use of cryptographically secure methods (Java
SecureRandom) - Mastering JSON Web Tokens (JWT) for managing stateless sessions
- Secure generation, validation and protection against tampering of JWTs
- rate limiting and concurrent session management
- Practical strategies for managing and limiting user access to prevent abuse
7. Error Handling and Logging
7.1 Overview
This module covers several crucial aspects of secure error handling and logging.
Contents:
- Implementing custom error pages
- Error logging best practices with Log4j and SLF4J
- Types of Exceptions and Their Proper Handling
- Secure Exception Propagation
- Error Handling Policies
- Framework features (Spring MVC)
- Testing error handling strategies
7.2 Custom error pages
Role: Custom error pages override the default error pages or stack traces displayed by web servers and frameworks. Carefully designed controls what information is shown to users, protecting sensitive system details and potential security vulnerabilities.
Implementation:
- Traditional Java EE — in
web.xml:
<error-page>
<error-code>404</error-code>
<location>/error/404.html</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/error/general-error.html</location>
</error-page>
- Spring MVC — with
@ControllerAdviceand@ExceptionHandler:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleAllExceptions(Exception e) {
// Journaliser les détails sécurisés côté serveur
logger.error("Internal error", e);
// Retourner un message générique côté client
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Une erreur s'est produite. Veuillez contacter le support.");
}
}
Advantages:
- Better user experience with pages adapted to the style of the site
- Control of displayed information (data leak prevention)
- Server-side verbose logging without client-side exposure
Best practices:
- Never display sensitive data on error pages
- Maintain design consistency with the application
- Securely log error details for debugging
- Always return correct HTTP codes
- Test error pages to ensure they work properly
7.3 Classification and handling of exceptions
Three categories of Java exceptions:
-
Checked Exceptions: Exceptions that the code must explicitly handle (either by catching them or declaring them in the method signature). Intended for recoverable conditions.
-
Unchecked Exceptions: Exceptions generally resulting from programming errors (eg:
NullPointerException,IllegalArgumentException). Not expected to be captured. -
Errors: Serious problems like
OutOfMemoryErrorandStackOverflowErrorthat applications should not attempt to handle.
Best practices:
- Distinguish between error types and apply different strategies
- Write precise
catchblocks targeting specific exceptions - Ensure resource closure with
finallyblocks ortry-with-resourcesinstructions - Separate error handling from business logic
- Avoid exposing sensitive information in error messages
- Never catch
java.lang.Exceptionorjava.lang.Throwablebroadly — may hide underlying bugs
Costs:
- Detailed exception handling can make the code more complex
- Inefficient processing (especially with many try-catch blocks) can degrade performance
7.4 Secure exception propagation
Definition: Secure propagation involves controlling how exceptions are passed through layers of an application, crucial for preventing the leakage of sensitive information contained in stack traces or error messages.
Technical:
- Exception wrapping: Catch a specific exception and throw a new one with informative but sanitized custom exception types
catch (SQLException e) {
logger.error("Database error: ", e); // Log complet côté serveur
throw new ServiceException("Unable to process request"); // Message générique vers le client
}
- Exception rethrow: After specific error handling (such as logging), rethrow the original exception or a more generic one
catch (SpecificException e) {
logger.error("Specific error occurred", e);
throw new GeneralException("An error occurred"); // Pas de détails internes
}
- Sanitation of error messages: Ensure that messages are generic and do not disclose internal application details
Best practices:
- Use
catchblocks to resolve exceptions meaningfully - Securely log the full stack trace at the capture point for debugging
- Do not rethrow exceptions without handling or logging them
- Never expose sensitive internal details (API names, SQL queries, file paths)
- Avoid over-wrapping which can obscure the original context
7.5 Defining security policies for error handling
Importance: Clear and enforceable policies ensure consistent and secure responses to errors across the entire application.
Policy elements:
- Clearly define who can access error information
- Establish what should be logged, how logs are stored and how they are protected
- Specify storage locations for logs, security measures and retention periods in accordance with legal and business requirements
- Define error response procedures including notification processes and responsibilities
Cross-functional collaboration: Involve stakeholders from IT, security, compliance and business teams for comprehensive and enforceable policies.
Advantages:
- Minimizes the risk of data leaks and unauthorized access
- Standardizes error handling, improving reliability and user experience
- Regulatory compliance — adherence to data protection and privacy laws
Best practices:
- Document policies clearly and make them accessible to all relevant members
- Use encryption and apply access controls to secure log data
- Train staff on secure error handling and policy compliance
- Perform regular audits of error handling and logging practices
- Test error handling procedures to ensure alignment with policies
- Avoid policies that are too rigid or too vague
7.6 Using framework-specific features
Spring MVC — Global Handling Exception:
@ControllerAdvice
public class SecurityAwareExceptionHandler {
private static final Logger logger =
LoggerFactory.getLogger(SecurityAwareExceptionHandler.class);
@ExceptionHandler(AuthenticationException.class)
public ResponseEntity<String> handleAuth(AuthenticationException e) {
// Log sécurisé côté serveur avec détails complets
logger.error("Authentication failure: {}", e.getMessage(), e);
// Réponse générique vers le client sans détails internes
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body("Authentication failed");
}
@ExceptionHandler(DataAccessException.class)
public ResponseEntity<String> handleDataAccess(DataAccessException e) {
logger.error("Data access error: ", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Service temporarily unavailable");
}
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleGeneral(Exception e) {
logger.error("Unexpected error: ", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("An unexpected error occurred");
}
}
Advantages:
- Centralization of error handling in controllers
- Improved code consistency and reusability
- Customizable error responses tailored to specific exception types
- Cleaner and easier to maintain code
Be careful with @ExceptionHandler methods:
Ensure that they do not throw exceptions unless there is a higher level mechanism to handle them.
7.7 Testing error handling
Importance: Rigorously test error handling mechanisms to ensure that they function properly under normal conditions and are resilient to potential security threats.
Types of tests:
-
Unit testing: Use frameworks like JUnit to simulate various exception scenarios, verifying that methods respond correctly
-
Integration Testing: Checking how different parts of the application interact and handle errors together, crucial for spotting problems in exception propagation
-
System Testing: Evaluate overall behavior under failure conditions (network outages, database unavailability)
-
Penetration testing and vulnerability scanning: Evaluate the resistance of error handling mechanisms to exploitable scenarios
Best practices:
- Ensure testing covers a wide range of error scenarios, including less likely but potentially serious ones
- Use automated tools and continuous integration pipelines to regularly evaluate error handling
- Focus on error handling in sensitive areas (authentication, data validation)
- Test in conditions mimicking real operational environments
7.8 Summary
This module covered the following aspects of secure error handling and logging:
-
Custom error pages — Prevent exposure of sensitive information via detailed error messages. Generic messages on the user side, secure diagnostic information on the server side.
-
Controlled exception logging with Log4j and SLF4J — Configuring appropriate log levels, securing log files, hiding sensitive information, asynchronous logging for performance.
-
Exception classification and management — Distinction between checked and unchecked exceptions, precise
catchblocks, management avoiding the exposure of sensitive data. -
Secure Exception Propagation — Wrapping and rethrow techniques to maintain usability while hiding complex error details.
-
Security Policies for Error Handling — Robust policies dictating how errors are handled and logged, access allowed, and secure storage.
-
Framework features (Spring MVC) —
@ControllerAdviceand@ExceptionHandlerto simplify error handling. -
Testing Error Handling Strategies — Unit, integration, system, and penetration testing.
8. Conclusion
Paul Mooney’s Secure Coding in Java training covers a full spectrum of Java application security, from theory to practice. The main lessons are:
Fundamentals
| Principle | Description |
|---|---|
| Defense in depth | Multiple Layers of Security Controls |
| Least privilege | Minimum access required for each component |
| Deny by default | Anything not explicitly permitted is prohibited |
| Fail securely | In case of error, fall back to a safe state |
| Never trust user input | Validate and sanitize all incoming data |
| Security by design | Integrate security by design |
Key Tools and Libraries
| Tool / Library | Usage |
|---|---|
| OWASP Java HTML Sanitizer | HTML sanitization / XSS protection |
| BCryptPasswordEncoder (Spring Security) | Password hashing |
| PBKDF2 / Scrypt | Brute-force Resistant Hashing Algorithms |
| JJWT / java-jwt | Managing JSON Web Tokens |
| SecureRandom | Cryptographic random number generation |
| PreparedStatement (JDBC) | SQL injection protection |
| Log4j / SLF4J | Secure Logging |
| Spring @ControllerAdvice | Global exception management |
| bucket4j / Guava RateLimiter | Rate limiting |
| H2 Database | Demo Database |
| Postman | API endpoint testing |
| JUnit | Unit Testing |
OWASP Top 10 Recap (2021)
| Rank | Vulnerability |
|---|---|
| 1 | Broken Access Control |
| 2 | Cryptographic Failures |
| 3 | Injection (SQL, XSS, OS Command, etc.) |
| 4 | Insecure Design |
| 5 | Security Misconfiguration |
| 6 | Vulnerable and Outdated Components |
| 7 | Identification and Authentication Failures |
| 8 | Software and Data Integrity Failures |
| 9 | Security Logging and Monitoring Failures |
| 10 | Server-Side Request Forgery (SSRF) |
Resources
- Demo application: https://github.com/daishisystems/pluralsight-healthcare
- OWASP Top 10: https://owasp.org/www-project-top-ten/
- OWASP ASVS (Application Security Verification Standard): https://owasp.org/www-project-application-security-verification-standard/
- OWASP Java Encoder: https://owasp.org/www-project-java-encoder/
- OWASP Java HTML Sanitizer: https://owasp.org/www-project-java-html-sanitizer/
Search Terms
secure · coding · java · backend · architecture · full-stack · web · authentication · checking · error · session · validation · failures · handling · data · jwt · logging · management · security · attacks · characters · concurrent · encoding · generation