Crlf Injection in Actix with Cockroachdb
Crlf Injection in Actix with Cockroachdb — how this specific combination creates or exposes the vulnerability
Crlf Injection occurs when an attacker can inject a CRLF sequence (\r\n) into a header or query parameter, causing the application to split or smuggled headers. In an Actix web service that uses Cockroachdb as the backend datastore, this typically arises when user-controlled input is reflected into SQL identifiers, dynamic query fragments, or response headers without proper validation or encoding.
Consider an endpoint that accepts a table_name or sort parameter to construct SQL statements. If the input is concatenated into a query and later echoed in HTTP headers (e.g., X-Table-Name), a malicious payload such as users%0D%0ASet-Cookie:%20evil=1 can inject additional headers. In Actix, middleware or custom responders that build headers using unchecked input can inadvertently allow injected headers to be processed before the response is sent.
When the injected header modifies response behavior—such as setting Set-Cookie or Location—it can lead to session fixation or open redirect-like behavior. Although Cockroachdb does not directly interpret CRLF in SQL strings as new statements, the injection occurs at the HTTP layer before data reaches the database. However, if the application uses the tainted input to construct dynamic SQL (for example, table or column names), and that SQL is executed via the Cockroachdb driver, the CRLF may be treated as part of an identifier, leading to malformed queries or unexpected routing of requests across schemas.
Another scenario involves logging or error handling. Actix applications that log request parameters or database errors may include user input verbatim. If CRLF sequences appear in logs and are later viewed in log-aggregation tools that render entries as separate lines, this can facilitate log injection or obscuration of related events. While this does not directly alter database state, it weakens auditability and can mask related attacks against the Cockroachdb instance.
Because middleBrick scans the unauthenticated attack surface and checks for header injection and input validation issues across its 12 security checks, such CRLF Injection vectors are detectable when user input reaches response headers or influences SQL construction in Actix services connected to Cockroachdb. The scanner does not fix the issue but provides findings with severity, remediation guidance, and mappings to frameworks like OWASP API Top 10 to help prioritize the risk.
Cockroachdb-Specific Remediation in Actix — concrete code fixes
Remediation focuses on strict input validation, avoiding direct concatenation of user input into SQL or headers, and ensuring Actix handlers and middleware treat data safely when interacting with Cockroachdb.
1. Validate and sanitize header-related input
Never pass raw user input into HTTP headers. In Actix, use extractor patterns that reject CRLF characters before constructing responses.
use actix_web::{web, HttpResponse, Result};
use regex::Regex;
/// Allow only alphanumeric and underscores for table-related identifiers
fn is_safe_identifier(value: &str) -> bool {
let re = Regex::new(r"^[a-zA-Z_][a-zA-Z0-9_]*$").unwrap();
re.is_match(value)
}
async fn get_table_data(
table_name: web::Query<TableQuery>,
) -> Result<HttpResponse> {
if !is_safe_identifier(&table_name.name) {
return Ok(HttpResponse::BadRequest().body("Invalid table name"));
}
// Safe to use with parameterized patterns or mapping logic
Ok(HttpResponse::Ok().header("X-Table-Name", &table_name.name).finish())
}
struct TableQuery {
name: String,
}
2. Use parameterized queries and schema mapping instead of dynamic SQL identifiers
Do not interpolate user input into SQL strings. Map allowed values to predefined statements or use Cockroachdb’s placeholders for values, not identifiers.
// Example using a static mapping to prevent injection in table selection
async fn fetch_user_data(
pool: web::Data<Pool>,
payload: web::Json<UserRequest>,
) -> Result<HttpResponse> {
let table_map = match payload.table.as_str() {
"customers" => "crdb_public.customers",
"orders" => "crdb_public.orders",
_ => return Ok(HttpResponse::BadRequest().body("Unsupported table")),
};
// Use placeholders for values, not identifiers
let rows = pool
.query(&format!("SELECT id, email FROM {} WHERE status = $1", table_map), &[&"active"])
.await
.map_err(|e| actix_web::error::ErrorInternalServerError(e))?;
// Process rows...
Ok(HttpResponse::Ok().finish())
}
3. Encode or reject problematic characters in inputs bound to Cockroachdb
If identifiers must be dynamic, enforce a strict allowlist and avoid passing raw input to the database driver. For values, prefer placeholders; for object names, use a whitelist mapping as shown above.
// Reject any input containing carriage return or line feed
fn contains_crlf(s: &str) -> bool {
s.contains('\r') || s.contains('\n')
}
async fn create_record(
body: web::Json<RecordInput>,
) -> Result<HttpResponse> {
if contains_crlf(&body.label) {
return Ok(HttpResponse::BadRequest().body("Invalid characters in input"));
}
// Proceed with safe, parameterized execution
// ...
}
4. Secure logging and error handling
Ensure logs do not propagate CRLF from user input. In Actix response guards or logging middleware, sanitize data before it is written to observability pipelines that may interact with Cockroachdb metadata or diagnostics.
use actix_web::dev::ServiceRequest;
use actix_web::Error;
use log::warn;
pub fn sanitize_log_input(input: &str) -> String {
input.replace(|c: char| c == '\r' || c == '\n', "_")
}
// Example guard or logger integration
fn log_request(req: &ServiceRequest) -> Result<(), Error> {
let safe_body = sanitize_log_input(&req.body().as_ref().map(|b| String::from_utf8_lossy(b).into_owned()).unwrap_or_default());
warn!("Request received: {}", safe_body);
Ok(())
}