Attack Surface: SQL Injection (Via Bypassed Safeguards)
- Description: Execution of malicious SQL code due to developers circumventing Exposed's built-in protection mechanisms.
- How Exposed Contributes: Exposed provides safe ways to interact with the database (DAOs,
Entity
classes), but also offers "escape hatches" (raw SQL execution, dynamicOp
building) that, if misused, directly lead to SQL injection. The framework's flexibility is the direct contributor to this risk. - Example:
// UNSAFE: User input directly concatenated into a WHERE clause using Exposed's functions val userInput = request.getParameter("username") Users.select { Users.name eq "admin' OR username = '$userInput" }.forEach { ... } // SAFE: Using Exposed's parameterized query val userInput = request.getParameter("username") Users.select { Users.name eq "admin" or (Users.username eq userInput) }.forEach { ... }
- Impact: Complete database compromise, data theft, data modification, data deletion, potential server compromise (depending on database privileges).
- Risk Severity: Critical
- Mitigation Strategies:
- Mandatory Code Reviews: Every database interaction using Exposed, especially
Transaction.exec()
, dynamicOp
building, or any string manipulation within queries, requires rigorous review. - Static Analysis: Use static analysis tools configured to detect SQL injection patterns specifically within the context of Exposed usage.
- Developer Training: Comprehensive training on secure Exposed usage, emphasizing the dangers of raw SQL and dynamic query construction with user input within Exposed's API. Focus on correct use of Exposed's features.
- Principle of Least Privilege: Database user account should have minimal permissions. (While a general best practice, it directly limits the impact of an Exposed-related SQL injection).
- Mandatory Code Reviews: Every database interaction using Exposed, especially
Attack Surface: Data Exposure (Over-Fetching with exposed-dao
)
- Description: Unintentional retrieval and potential exposure of sensitive data due to fetching entire entities or more columns than necessary using
exposed-dao
. - How Exposed Contributes: The ease of retrieving complete
Entity
objects withexposed-dao
directly encourages developers to fetch all columns, even when only a subset is needed. This is a feature of Exposed that increases the risk. - Example:
// Potentially exposes sensitive data if User entity has fields like "passwordHash" // Directly using exposed-dao's findById val user = User.findById(userId) return user // Returning the entire entity // Safer: Use a DTO and Exposed's select to get only necessary columns val user = Users.select { Users.id eq userId }.map { UserDto(it[Users.id].value, it[Users.username]) }.singleOrNull() return user
- Impact: Leakage of sensitive data (PII, credentials, internal data) to unauthorized users or attackers.
- Risk Severity: High
- Mitigation Strategies:
- Explicit Column Selection: Always use Exposed's
select
orslice
to retrieve only the specific columns required. Avoid fetching entire entities withexposed-dao
unless absolutely necessary and justified. - Data Transfer Objects (DTOs): Use DTOs in conjunction with Exposed's query results to represent the data returned, ensuring only intended fields are exposed. Never directly return
Entity
objects.
- Explicit Column Selection: Always use Exposed's
Attack Surface: Denial of Service (Unbounded Queries via Exposed API)
- Description: An attacker triggers a query through Exposed that returns a massive result set, consuming excessive resources.
- How Exposed Contributes: Exposed's API does not inherently limit the number of rows returned by a query. Developers must explicitly use Exposed's features to implement safeguards. The lack of built-in limits within the Exposed API is the direct contributor.
- Example:
// Potentially returns ALL users, causing a DoS, directly using Exposed's selectAll val allUsers = Users.selectAll().toList() // Safer: Use Exposed's pagination features val page = request.getParameter("page")?.toIntOrNull() ?: 1 val pageSize = 20 val users = Users.selectAll().limit(pageSize, offset = (page - 1) * pageSize.toLong()).toList()
- Impact: Application unavailability, resource exhaustion, potential database server crash.
- Risk Severity: High
- Mitigation Strategies:
- Pagination (Using Exposed's
limit
): Mandatory pagination for all queries using Exposed that could potentially return many results. Use Exposed'slimit
andoffset
functions. Enforce a maximum page size. - Query Timeouts (Configured through Exposed's Transaction): Set appropriate timeouts for database queries within Exposed's transaction management to prevent long-running queries.
- Pagination (Using Exposed's
Attack Surface: Insecure Logging of Sensitive Data (Exposed's Default Behavior)
- Description: Exposed's logging, if not carefully configured, logs the full SQL query, including potentially sensitive parameter values.
- How Exposed Contributes: This is a direct consequence of Exposed's default logging behavior. The framework provides the logging functionality that, without modification, creates this risk.
- Example:
- Exposed's default logging might output:
SELECT * FROM Users WHERE username = 'admin' AND password = 'plaintext_password'
- Exposed's default logging might output:
- Impact: Exposure of sensitive data (credentials, PII) in application logs.
- Risk Severity: High
- Mitigation Strategies:
- Disable Sensitive Data Logging in Exposed: Specifically configure Exposed's logging to never log raw query parameters. Use parameterized query logging (if available in Exposed) to show placeholders instead of values. This is a direct configuration change within Exposed.
- Log Level Control (Within Exposed's Configuration): Set Exposed's log level appropriately (e.g.,
INFO
,WARN
,ERROR
) to minimize unnecessary logging. AvoidDEBUG
in production. This is a direct configuration of Exposed.