Symlink Attack on Docker
How Symlink Attack Manifests in Docker
Symlink attacks in Docker exploit the way containers handle file system permissions and bind mounts. When a malicious actor creates symbolic links pointing to sensitive files outside the container's root filesystem, they can potentially access or modify files that should be inaccessible.
The most common Docker-specific manifestation occurs during docker run operations with bind mounts. Consider this vulnerable pattern:
docker run -v /var/run/docker.sock:/var/run/docker.sock -v /:/host alpine:latestThis command mounts the host's root filesystem into the container, allowing an attacker to create symlinks like /host/etc/shadow or /host/root/.ssh/id_rsa. Once inside, they can read or modify critical system files.
Another Docker-specific scenario involves Dockerfile COPY operations. If a Dockerfile contains:
COPY --chown=1000:1000 . /appAnd the source directory contains symlinks, Docker will follow these symlinks during the build process, potentially copying sensitive files from outside the intended context.
Container escape via symlink attacks can also target Docker's storage backend. By creating symlinks to /var/lib/docker or /var/lib/containers, attackers might access other containers' filesystems or manipulate Docker's internal state.
The attack becomes particularly dangerous when combined with Docker's default user permissions. Many containers run as root, giving symlinks full read/write capabilities on mounted volumes. An attacker can create a symlink to /etc/passwd and modify it to maintain persistence, or target /etc/shadow to change password hashes.
Docker-Specific Detection
Detecting symlink attacks in Docker environments requires both runtime monitoring and static analysis of Docker configurations. The most effective approach combines multiple detection methods.
Runtime detection should monitor for suspicious symlink creation patterns. Use auditd rules to track symlink system calls:
auditctl -a exit,always -F arch=b64 -S symlink -k docker_symlinkMonitor Docker daemon logs for unusual mount operations. The following command shows recent mount activities:
journalctl -u docker.service --since "1 hour ago" | grep -E "(mount|bind)"For Dockerfile analysis, scan for dangerous patterns:
# Check for overly permissive COPY operations
find . -name "Dockerfile" -exec grep -l "COPY.*--chown" {} \;
# Look for suspicious RUN commands that might create symlinks
docker history <image> | grep -E "(ln|symlink|mount)"middleBrick provides specialized Docker scanning that identifies symlink attack vulnerabilities without requiring credentials. The scanner examines your container images and runtime configurations, detecting:
- Overly permissive volume mounts that expose sensitive host paths
- Dangerous COPY operations that might follow symlinks
- Containers running with excessive privileges
- Missing security options like
--read-onlyor--tmpfs
The scanner produces a security score with specific findings about symlink-related risks, including severity levels and remediation guidance.
For continuous monitoring, integrate middleBrick into your CI/CD pipeline. The GitHub Action can automatically scan Docker images before deployment, failing builds that contain high-risk symlink vulnerabilities.
Docker-Specific Remediation
Remediating symlink attack vulnerabilities in Docker requires a defense-in-depth approach. Start with Docker daemon configuration to limit attack surface.
First, restrict dangerous mount options in /etc/docker/daemon.json:
{
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 64000,
"Soft": 64000
}
},
"userland-proxy": false,
"seccomp-profile": "/etc/docker/seccomp/default.json"
}Implement the principle of least privilege in your Dockerfiles:
# Use non-root user
RUN addgroup -g 1001 -S appgroup \n && adduser -u 1001 -S appuser -G appgroup
# Create application directory with restricted permissions
RUN mkdir -p /app/data && chown appuser:appgroup /app/data
# Switch to non-root user
USER appuser
# Use --chown only when absolutely necessary
COPY --chown=appuser:appgroup . /app
# Remove setuid/setgid bits from binaries
RUN find /usr/local/bin /usr/bin -perm /6000 -exec chmod a-s {} \; 2>/dev/null || trueFor runtime protection, use Docker's security features:
# Run container with read-only filesystem
docker run --read-only -v /tmp:/tmp:rw -v /var/run/docker.sock:/var/run/docker.sock myapp:latest
# Use tmpfs for temporary files
docker run --tmpfs /tmp:rw,size=100m myapp:latest
# Drop Linux capabilities
docker run --cap-drop ALL --cap-add CHOWN myapp:latestImplement filesystem isolation using SELinux or AppArmor profiles. For example, create an AppArmor profile that prevents symlink creation to certain paths:
# Create AppArmor profile
apparmor_parser -r -W /etc/apparmor.d/docker-app-profile
# Run container with AppArmor confinement
docker run --security-opt apparmor:docker-app-profile myapp:latestFor production deployments, use container orchestration security policies. In Kubernetes, define PodSecurityPolicies or (preferably) Pod Security Standards:
apiVersion: policy/v1
kind: PodSecurityPolicy
metadata:
name: restricted-symlink
spec:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
requiredDropCapabilities:
- ALL
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
- 'persistentVolumeClaim'Finally, implement runtime detection with Falco or similar tools to alert on suspicious symlink activities within running containers.