Crlf Injection in Grape with Basic Auth
Crlf Injection in Grape with Basic Auth — how this specific combination creates or exposes the vulnerability
Crlf Injection occurs when user-controlled data is reflected in HTTP headers without sanitization, allowing an attacker to inject newline characters (CRLF = \r\n). In Grape, this commonly arises when header values are derived from params, headers, or cookies. When Basic Authentication is used, the Authorization header is typically parsed by Grape or underlying Rack middleware to extract a username and password. If the application then reuses parts of the Authorization header — or a value derived from it — in another response header, an attacker can supply CRLF sequences to inject additional headers or even create a new request line.
For example, a Grape API might extract a user identifier from the Basic Auth credentials (e.g., the username) and use it in a custom header like X-User-Name. If the username contains \r\n and the developer does not sanitize or validate it, the injected CRLF can terminate the current header line and append new headers such as Set-Cookie or X-Injected. Because Basic Auth credentials are often base64-encoded in the request header, the server-side code must decode the Authorization header and explicitly handle the decoded values. If this decoded value is reflected unsafely, the injection is possible despite the encoding layer.
The risk is compounded when the API exposes verbose logging or error messages that include the Authorization header. An attacker can probe endpoints with crafted Basic Auth strings containing CRLF to see if injected headers appear in responses, confirming the presence of Crlf Injection. This becomes an avenue for HTTP response splitting, cache poisoning, or session fixation when injected Set-Cookie headers are processed. The unauthenticated scan capability of middleBrick tests such header reflection paths, including scenarios where Basic Auth is present, to detect whether user-controlled input reaches response headers without proper sanitization.
Middleware or Rack-level normalization does not automatically neutralize CRLF in decoded Basic Auth values. Each header that incorporates data derived from authentication must be treated as a potential injection surface. The presence of Basic Auth does not inherently cause Crlf Injection, but it supplies a common, attacker-controllable input channel when values are parsed and later echoed into headers.
Basic Auth-Specific Remediation in Grape — concrete code fixes
Remediation centers on strict validation and encoding of any data derived from the Authorization header before it is used in response headers. Do not rely on automatic parsing or implicit trust in decoded credentials. Instead, explicitly extract values, sanitize them, and avoid reflecting them in headers where possible.
Example vulnerable Grape endpoint
require 'grape'
class VulnerableAPI < Grape::API
format :json
before { authenticate! }
helpers do
def authenticate!
auth_header = request.env['HTTP_AUTHORIZATION']
if auth_header&.start_with?('Basic ')
encoded = auth_header.split(' ').last
decoded = Base.strict_decode64(encoded)
@current_user = decoded.split(':', 2).first # username
else
error!('Unauthorized', 401)
end
end
end
get :profile do
# Vulnerable: reflects username in a custom header
header['X-User-Name'] = @current_user
{ message: 'ok' }
end
end
Secured Grape endpoint with sanitization
require 'grape'
class SecureAPI < Grape::API
format :json
before { authenticate! }
helpers do
def authenticate!
auth_header = request.env['HTTP_AUTHORIZATION']
if auth_header&.start_with?('Basic ')
encoded = auth_header.split(' ').last
decoded = Base.strict_decode64(encoded)
@current_user = decoded.split(':', 2).first
# Reject obviously malicious input
unless @current_user&.match?(\A[\w\-\.]+\z)
error!('Invalid credentials', 401)
end
else
error!('Unauthorized', 401)
end
end
end
get :profile do
# Safe: sanitize before using in headers
safe_user = @current_user.to_s.gsub(/[\r\n]/, '')
header['X-User-Name'] = safe_user
{ message: 'ok' }
end
end
Key practices:
- Always decode and parse Basic Auth explicitly; do not rely on framework auto-parsing that may hide reflected values.
- Validate usernames or passwords against a strict allowlist (e.g., alphanumeric with a limited set of symbols) rather than trying to blacklist CRLF characters alone.
- If you must reflect authentication-derived data in headers, perform a CRLF filter (e.g., gsub(/[\r\n]/, '')) and prefer safer representations such as hashing a value for use in headers.
- Avoid putting raw Authorization-derived values in Set-Cookie, Location, or other header fields that influence request processing.
middleBrick scans endpoints that use Basic Auth and checks whether decoded credentials can reach response headers, helping to identify Crlf Injection paths specific to this authentication method.