Sql Injection in Actix
How Sql Injection Manifests in Actix
SQL Injection in Actix applications typically occurs when user input is concatenated directly into SQL queries without proper parameterization. This vulnerability allows attackers to manipulate database queries by injecting malicious SQL code through HTTP request parameters, headers, or body data.
Consider this common Actix pattern that's vulnerable:
async fn get_user(data: web::Data<AppState>, info: web::Path<(String,)>) -> impl Responder {
let conn = &data.db_pool;
let username = info.0;
// VULNERABLE: Direct string interpolation
let query = format!("SELECT * FROM users WHERE username = '{}'", username);
let result = sqlx::query_as(query)
.fetch_one(conn)
.await;
match result {
Ok(row) => HttpResponse::Ok().json(row),
Err(_) => HttpResponse::NotFound().finish(),
}
}
An attacker could exploit this by requesting /api/user/admin' OR '1'='1, which would transform the query into:
SELECT * FROM users WHERE username = 'admin' OR '1'='1'
This always evaluates to true, potentially exposing all user records. More sophisticated attacks could drop tables, extract sensitive data, or bypass authentication.
Actix's async/await model doesn't inherently prevent SQL Injection—the vulnerability exists in how database queries are constructed. The framework's web::Query and web::Json extractors make it easy to access user input, but developers must still use parameterized queries.
Another Actix-specific pattern that's risky involves dynamic query building:
async fn search_users(
query: web::Query<SearchQuery>,
data: web::Data<AppState>,
) -> impl Responder {
let conn = &data.db_pool;
let mut conditions = Vec::new();
let mut params = Vec::new();
if let Some(name) = &query.name {
conditions.push(format!("name LIKE '%{}%'", name)); // VULNERABLE
}
if let Some(age) = query.age {
conditions.push(format!("age = {}", age)); // VULNERABLE
}
let where_clause = conditions.join(" AND ");
let query = format!("SELECT * FROM users WHERE {}", where_clause);
let result = sqlx::query_as(query)
.fetch_all(conn)
.await;
HttpResponse::Ok().json(result)
}
This dynamic query building approach is particularly dangerous because it combines multiple user inputs into a single query string.
Actix-Specific Detection
Detecting SQL Injection in Actix applications requires both static code analysis and runtime scanning. middleBrick's API security scanner can identify SQL Injection vulnerabilities in Actix endpoints through several mechanisms.
For runtime scanning, middleBrick tests Actix endpoints by sending payloads designed to trigger SQL Injection responses. The scanner analyzes HTTP responses for SQL error messages, unexpected data exposure, or timing differences that indicate query manipulation.
When scanning an Actix API, middleBrick examines:
- Query parameters in GET/POST requests
- JSON body fields that might be used in database queries
- URL path parameters that get interpolated into SQL
- Header values that could influence database queries
- Database connection patterns in the code
The scanner provides Actix-specific findings with severity levels and remediation guidance. For example, it might detect that a POST endpoint at /api/users is vulnerable because it accepts JSON input that's directly concatenated into SQL queries.
Here's how you'd scan an Actix API with middleBrick:
# Install the CLI tool
npm install -g middlebrick
# Scan your Actix API endpoint
middlebrick scan https://your-actix-api.com/api/users
# Or integrate into your CI/CD pipeline
middlebrick scan --fail-on-warn https://staging.your-actix-api.com
The scanner returns a security score (A-F) with specific findings like:
SQL Injection (High Risk)
- Endpoint: POST /api/users
- Issue: Direct string interpolation in database query
- Remediation: Use parameterized queries with sqlx::query!
For Actix applications using sqlx, middleBrick specifically checks for the use of sqlx::query() with string interpolation versus sqlx::query!() with compile-time query checking.
The scanner also tests for blind SQL Injection by measuring response times with payloads like OR SLEEP(5) to detect if the application is vulnerable to time-based attacks.
Actix-Specific Remediation
Remediating SQL Injection in Actix applications centers on using parameterized queries and avoiding dynamic SQL construction. Actix works well with the sqlx crate, which provides compile-time query verification and type-safe parameterization.
Here's the secure pattern using sqlx::query!:
async fn get_user(
data: web::Data<AppState>,
info: web::Path<String>,
) -> impl Responder {
let conn = &data.db_pool;
let username = info.into_inner();
// SECURE: Parameterized query with sqlx::query!
let result = sqlx::query_as!("
SELECT id, username, email
FROM users
WHERE username = $1
", username)
.fetch_one(conn)
.await;
match result {
Ok(row) => HttpResponse::Ok().json(row),
Err(sqlx::Error::RowNotFound) => HttpResponse::NotFound().finish(),
Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
}
}
The sqlx::query! macro provides compile-time SQL validation, ensuring your query syntax is correct and that parameter types match the query's expectations.
For dynamic queries with multiple optional parameters, use conditional query building:
async fn search_users(
query: web::Query<SearchQuery>,
data: web::Data<AppState>,
) -> impl Responder {
let conn = &data.db_pool;
let mut base_query = sqlx::query_as("
SELECT id, name, email, age
FROM users
WHERE 1=1
");
let mut conditions = Vec::new();
let mut params = Vec::new();
if let Some(name) = &query.name {
conditions.push("name ILIKE $1");
params.push(format!("{}%", name));
}
if let Some(age) = query.age {
conditions.push("age = $2");
params.push(age);
}
if !conditions.is_empty() {
let where_clause = conditions.join(" AND ");
base_query = base_query.bind(where_clause);
}
// This approach requires more sophisticated query building
// A better pattern uses a query builder library
let result = base_query.fetch_all(conn).await;
HttpResponse::Ok().json(result)
}
For complex dynamic queries, consider using a query builder library like sqlx::QueryBuilder or schemars to safely construct queries without string interpolation.
Additional Actix-specific security measures:
- Use
sqlx::query!for all database operations when possible - Implement proper error handling to avoid leaking database error details
- Set appropriate database user permissions (least privilege principle)
- Use connection pooling with proper timeout configurations
- Validate and sanitize user input before it reaches query construction
middleBrick's Pro plan includes continuous monitoring that can alert you if new SQL Injection vulnerabilities are introduced in your Actix codebase, helping maintain security as your application evolves.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |