Crlf Injection in Gin with Dynamodb
Crlf Injection in Gin with Dynamodb — how this specific combination creates or exposes the vulnerability
Crlf Injection occurs when an attacker can inject a carriage return (CR, \r) and line feed (\n) sequence into a header or key, causing the server to prematurely split and interpret subsequent data as new headers or commands. In a Gin application that uses AWS DynamoDB, this typically arises when user-controlled input is reflected in HTTP headers (e.g., custom headers, Location values in redirects) or is used to construct DynamoDB expression attribute names or values that later appear in responses without proper sanitization.
Gin is a high-performance HTTP web framework written in Go. When handling requests, Gin allows developers to easily set headers and construct responses. If user input is directly inserted into headers such as Location, X-Custom-Name, or used to build DynamoDB query keys or conditional update expressions, a newline character can break the header block and inject additional commands.
DynamoDB is a managed NoSQL database service. While DynamoDB itself does not parse HTTP headers, the interaction becomes dangerous when data stored in or retrieved from DynamoDB is reflected into HTTP responses or headers without sanitization. For example, an item attribute such as redirect_url or callback might be stored by a user and later used by the Gin server in a http.Redirect call or a custom header. If the stored value contains a CRLF sequence, the injected header can manipulate session cookies, perform web cache deception, or enable cross-protocol attacks.
An attack scenario: a user registers or updates a profile in a Gin app, storing a value like location: "https://example.com\r\nSet-Cookie: session=attacker" in a DynamoDB attribute. Later, when the Gin handler reads this attribute and uses it in a header (e.g., resp.Header().Set("X-Location", item.Location)), the injected CRLF causes the header to split, and the injected Set-Cookie line is interpreted as a new header, potentially overwriting legitimate cookies.
Because middleBrick scans the unauthenticated attack surface and tests input validation and data exposure, it can identify whether headers or DynamoDB-derived data reflect unsanitized newline characters. Findings will highlight missing validation on string fields that originate from or are stored in DynamoDB and are later used in HTTP response construction.
Dynamodb-Specific Remediation in Gin — concrete code fixes
To prevent Crlf Injection in Gin when working with DynamoDB, ensure that any data stored in or retrieved from DynamoDB is validated and sanitized before being used in HTTP headers, redirects, or response construction. Below are concrete, safe patterns using the AWS SDK for Go (v2) with Gin.
First, validate and sanitize header inputs and DynamoDB attributes by rejecting or stripping CR and LF characters. Use a strict allowlist for expected formats (e.g., URLs) and avoid reflecting untrusted data into headers.
// Validate and sanitize input before using in headers or storing in DynamoDB
func containsCrlf(s string) bool {
return strings.ContainsAny(s, "\r\n")
}
// Example Gin handler: create item with safe DynamoDB write
func createItem(c *gin.Context) {
var req struct {
UserID string `json:"user_id"`
Redirect string `json:"redirect_url"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_request"})
return
}
// Reject or sanitize CRLF before storage or header use
if containsCrlf(req.Redirect) {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_redirect"})
return
}
// Safe DynamoDB put using AWS SDK for Go v2
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "config_error"})
return
}
client := dynamodb.NewFromConfig(cfg)
item := map[string]types.AttributeValue{
"user_id": &types.AttributeValueMemberS{Value: req.UserID},
"redirect_url": &types.AttributeValueMemberS{Value: req.Redirect},
}
_, err = client.PutItem(context.TODO(), &dynamodb.PutItemInput{
TableName: aws.String("UserSettings"),
Item: item,
})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "db_error"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "ok"})
}
When reading from DynamoDB and using values in HTTP responses, apply the same validation. Never directly set headers such as Location or X-Page with raw DynamoDB attributes.
// Example Gin handler: safely use DynamoDB item in a redirect
func redirectUser(c *gin.Context) {
userID := c.Param("userID")
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "config_error"})
return
}
client := dynamodb.NewFromConfig(cfg)
out, err := client.GetItem(context.TODO(), &dynamodb.GetItemInput{
TableName: aws.String("UserSettings"),
Key: map[string]types.AttributeValue{
"user_id": &types.AttributeValueMemberS{Value: userID},
},
})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "db_error"})
return
}
if out.Item == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "not_found"})
return
// Using a middleware or helper, ensure no CRLF in the URL.
}
redirectURL := *out.Item["redirect_url"].(*types.AttributeValueMemberS).Value
if containsCrlf(redirectURL) {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_data"})
return
}
// Safe redirect: no user input is used as a header key or value
c.Redirect(http.StatusFound, redirectURL)
}
For broader protection, implement a Gin middleware that scans response headers for injected newline sequences before writing the response. This complements DynamoDB-focused validation and helps catch misuse of other data sources.
// Middleware to detect CRLF in header values before sending response
func CRLFHeaderMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.AfterFunc(func() {
for _, values := range c.Writer.Header() {
for _, v := range values {
if containsCrlf(v) {
// Log and replace unsafe value; do not rely on blocking the request here
c.Writer.Header().Del(c.Request.Header.Get("Header-Key-To-Replace"))
}
}
}
})
c.Next()
}
}
These patterns ensure that data from DynamoDB is treated as untrusted and never directly controls HTTP protocol elements. By combining input validation, output encoding, and header-safe usage, the Gin application mitigates Crlf Injection risks even when storing and retrieving data from DynamoDB.