Header Injection on Docker
How Header Injection Manifests in Docker
Header injection in Docker environments typically occurs when untrusted data flows into HTTP headers without proper validation. In containerized applications, this vulnerability can be particularly dangerous because containers often expose APIs to other services or the internet without the traditional network protections you might expect.
A common Docker-specific scenario involves multi-stage builds where header manipulation occurs during runtime. Consider this vulnerable Node.js Express application inside a Docker container:
const express = require('express');
const app = express();
app.use((req, res, next) => {
const customHeader = req.headers['x-custom-header'];
res.setHeader('X-Response-Header', customHeader);
next();
});
app.get('/api/data', (req, res) => {
res.json({ message: 'Hello World' });
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});This code directly reflects the X-Custom-Header value into a response header without validation. In a Docker context, this becomes more severe because containers often run with elevated privileges or share networks with other services.
Another Docker-specific pattern involves environment variable injection through headers. Many Docker applications use environment variables for configuration, and headers can be crafted to manipulate these:
// Vulnerable pattern
app.use((req, res, next) => {
const dbHost = req.headers['x-db-host'];
process.env.DB_HOST = dbHost; // Critical vulnerability
next();
});When this runs inside a Docker container, an attacker could potentially manipulate database connections or other service configurations by injecting malicious headers.
Container orchestration platforms like Kubernetes add another layer of complexity. Services often communicate via HTTP between containers, and a header injection vulnerability in one service could affect the entire cluster. For example:
// Microservice communication vulnerability
app.get('/service-call', async (req, res) => {
const targetService = req.headers['x-target-service'];
const response = await fetch(`http://${targetService}/data`);
res.json(await response.json());
});This allows header-based service discovery manipulation, potentially redirecting traffic to malicious endpoints within the Docker network.
Docker-Specific Detection
Detecting header injection in Docker environments requires both runtime monitoring and static analysis. For runtime detection, middleBrick's Docker-aware scanning can identify header injection vulnerabilities by analyzing the unauthenticated attack surface of your containerized APIs.
When scanning a Dockerized API endpoint, middleBrick tests for header injection by attempting to manipulate various HTTP headers and observing the responses. The scanner looks for patterns like:
- Response splitting via
\r\nsequences in headers - Header reflection without validation
- CRLF injection in cookie headers
- Header-based path traversal
Here's how you would scan a Docker API using middleBrick's CLI:
npx middlebrick scan http://localhost:3000/api
# Or scan a specific endpoint
npx middlebrick scan http://docker-host:8080/auth
# For continuous monitoring in Docker environments
npx middlebrick scan --continuous http://api-service:3000The scanner returns a security score with detailed findings, including any header injection vulnerabilities detected. For Docker environments specifically, it checks for:
| Check Type | Description | Docker Relevance |
|---|---|---|
| Header Reflection | Tests if headers are reflected without validation | High - common in container APIs |
| CRLF Injection | Looks for carriage return/line feed injection | Critical - can manipulate Docker network traffic |
| Header Manipulation | Tests for unauthorized header modification | Medium - affects service-to-service auth |
For static analysis in Docker environments, you can use tools like docker scan in combination with middleBrick:
# Build your Docker image
docker build -t my-api .
# Static vulnerability scan
docker scan my-api
# Then scan the running API
npx middlebrick scan http://localhost:3001middleBrick's OpenAPI spec analysis is particularly useful for Docker microservices. It can analyze your API definitions and cross-reference them with runtime findings to identify header injection risks in your service contracts.
Docker-Specific Remediation
Remediating header injection in Docker environments requires both code fixes and Docker-specific security configurations. The most effective approach combines proper input validation with Docker's native security features.
For code-level fixes, implement strict header validation using a whitelist approach:
const express = require('express');
const app = express();
// Whitelist of allowed headers
const allowedHeaders = new Set([
'x-custom-header',
'x-request-id',
'x-correlation-id'
]);
// Header sanitization middleware
app.use((req, res, next) => {
// Validate header names
for (const headerName in req.headers) {
if (!allowedHeaders.has(headerName.toLowerCase())) {
return res.status(400).json({
error: 'Invalid header detected'
});
}
}
// Sanitize header values
for (const [key, value] of Object.entries(req.headers)) {
if (typeof value === 'string') {
// Remove CRLF characters
req.headers[key] = value.replace(/[
]/g, '');
}
}
next();
});For Docker-specific security, use the --read-only flag when running containers to prevent file system modifications that could be triggered by header injection:
docker run -d \
--name my-api \
--read-only \
-p 3000:3000 \
-e NODE_ENV=production \
my-api-imageAdditionally, use Docker's seccomp profiles to restrict system calls that could be exploited through header injection:
docker run -d \
--name my-api \
--security-opt seccomp=seccomp.json \
-p 3000:3000 \
my-api-imageWhere seccomp.json might restrict dangerous system calls like ptrace or process_vm_readv.
For microservices in Docker, implement service mesh security with mutual TLS to prevent header injection across service boundaries:
# Docker Compose with service mesh
version: '3.8'
services:
api-gateway:
image: api-gateway
networks:
- app-network
security_opt:
- no-new-privileges:true
auth-service:
image: auth-service
networks:
- app-network
security_opt:
- no-new-privileges:true
# Add mTLS configuration
proxy:
image: envoyproxy/envoy
ports:
- "80:80"
- "443:443"
volumes:
- ./envoy.yaml:/etc/envoy/envoy.yaml
networks:
- app-network
networks:
app-network:
driver: bridgeFinally, implement Docker content trust to ensure only verified images run in your environment:
# Enable Docker content trust
export DOCKER_CONTENT_TRUST=1
# Pull only signed images
docker pull my-registry/my-api:latestThis prevents an attacker from replacing your API container with a malicious version that includes header injection vulnerabilities.