Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions docker/socket_exposure/DockerfileSafe
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
FROM ubuntu:22.04

LABEL authors="OSV-Scalibr Team"
LABEL description="Secure Docker socket configuration for testing"

RUN apt update && apt install -y systemd

# Create Docker-related directory structure
RUN mkdir -p /var/run \
/etc/docker \
/etc/systemd/system \
/lib/systemd/system \
/usr/lib/systemd/system

# Create Docker socket with secure permissions (660 - rw-rw----)
RUN touch /var/run/docker.sock && \
chmod 660 /var/run/docker.sock && \
chown root:docker /var/run/docker.sock

# Copy secure configuration files
COPY config/daemon-safe.json /etc/docker/daemon.json
COPY config/docker-safe.service /etc/systemd/system/docker.service

# Set proper ownership for Docker config
RUN chown root:root /etc/docker/daemon.json && \
chmod 644 /etc/docker/daemon.json

# Set proper ownership for systemd service
RUN chown root:root /etc/systemd/system/docker.service && \
chmod 644 /etc/systemd/system/docker.service

# Create docker group (typically GID 999)
RUN groupadd -g 999 docker || true

# Keep container running for testing
CMD ["sleep", "infinity"]
41 changes: 41 additions & 0 deletions docker/socket_exposure/DockerfileUnsafe
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
FROM ubuntu:22.04

LABEL authors="OSV-Scalibr Team"
LABEL description="Vulnerable Docker socket configuration for testing"

RUN apt update && apt install -y systemd

# Create Docker-related directory structure
RUN mkdir -p /var/run \
/etc/docker \
/etc/systemd/system \
/lib/systemd/system \
/usr/lib/systemd/system

# Create Docker socket with INSECURE permissions (666 - world-writable)
RUN touch /var/run/docker.sock && \
chmod 666 /var/run/docker.sock && \
chown 1000:1000 /var/run/docker.sock

# Copy insecure configuration files
COPY config/daemon-unsafe.json /etc/docker/daemon.json
COPY config/docker-unsafe.service /etc/systemd/system/docker.service

# Also place unsafe service in multiple locations for comprehensive testing
COPY config/docker-unsafe.service /lib/systemd/system/docker.service

# Set ownership for config files
RUN chown root:root /etc/docker/daemon.json && \
chmod 644 /etc/docker/daemon.json

RUN chown root:root /etc/systemd/system/docker.service && \
chmod 644 /etc/systemd/system/docker.service

RUN chown root:root /lib/systemd/system/docker.service && \
chmod 644 /lib/systemd/system/docker.service

# Create docker group (typically GID 999)
RUN groupadd -g 999 docker || true

# Keep container running for testing
CMD ["sleep", "infinity"]
95 changes: 95 additions & 0 deletions docker/socket_exposure/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Docker Socket Exposure Testbed

This testbed demonstrates Docker socket exposure vulnerabilities that can be detected by the OSV-Scalibr Docker socket detector.

## Setup

Run `docker compose up` to start both safe and unsafe Docker socket configurations.

## Vulnerable Instance (docker_socket_unsafe)

The unsafe container contains multiple Docker security misconfigurations:

1. **World-writable Docker socket**: `/var/run/docker.sock` has 666 permissions (world-readable and writable)
2. **Non-root socket ownership**: Socket owned by UID 1000 instead of root
3. **Insecure daemon configuration**: `/etc/docker/daemon.json` exposes TCP endpoints without TLS:
- `tcp://0.0.0.0:2375` (unencrypted, accessible from any IP)
- `tcp://127.0.0.1:2376` (unencrypted, localhost only)
4. **Insecure systemd service**: Docker service configured with `-H tcp://` flags without `--tls`

### Testing the Vulnerable Container

```bash
# Access the unsafe container
docker exec -it docker_socket_unsafe /bin/bash

# Check socket permissions (should show 666 permissions)
ls -la /var/run/docker.sock

# Check daemon configuration (should show insecure TCP bindings)
cat /etc/docker/daemon.json

# Check systemd service (should show TCP without TLS)
cat /etc/systemd/system/docker.service
```

## Safe Instance (docker_socket_safe)

The safe container demonstrates proper Docker security configurations:

1. **Secure socket permissions**: `/var/run/docker.sock` has 660 permissions (group-readable/writable only)
2. **Proper ownership**: Socket owned by root:docker
3. **Secure daemon configuration**: `/etc/docker/daemon.json` uses TLS authentication for remote access
4. **Secure systemd service**: Docker service configured with proper TLS flags

### Testing the Safe Container

```bash
# Access the safe container
docker exec -it docker_socket_safe /bin/bash

# Check socket permissions (should show 660 permissions)
ls -la /var/run/docker.sock

# Check daemon configuration (should show TLS configuration)
cat /etc/docker/daemon.json

# Check systemd service (should show TLS flags)
cat /etc/systemd/system/docker.service
```

## Running the Detector

To test the OSV-Scalibr Docker socket detector against these containers:

```bash
# Test against unsafe container (should detect vulnerabilities)
docker exec docker_socket_unsafe /path/to/scalibr --detectors=dockersocket /

# Test against safe container (should report no issues)
docker exec docker_socket_safe /path/to/scalibr --detectors=dockersocket /
```

## Expected Vulnerabilities Detected

The detector should identify the following issues in the unsafe container:

- Docker socket is world-readable (permissions: 666)
- Docker socket is world-writable (permissions: 666)
- Docker socket owner is not root (uid: 1000)
- Insecure TCP binding in daemon.json: "tcp://0.0.0.0:2375" (consider using TLS)
- Insecure TCP binding in daemon.json: "tcp://127.0.0.1:2376" (consider using TLS)
- Insecure TCP binding in systemd service files (missing TLS)

## Cleanup

```bash
docker compose down
docker image prune -f
```

## Reference

- [Docker Security Documentation](https://docs.docker.com/engine/security/)
- [Docker Daemon Configuration](https://docs.docker.com/engine/reference/commandline/dockerd/)
- [CIS Docker Benchmark](https://www.cisecurity.org/benchmark/docker)
16 changes: 16 additions & 0 deletions docker/socket_exposure/config/daemon-safe.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"hosts": [
"unix:///var/run/docker.sock"
],
"tls": true,
"tlscert": "/etc/docker/certs/server-cert.pem",
"tlskey": "/etc/docker/certs/server-key.pem",
"tlsverify": true,
"tlscacert": "/etc/docker/certs/ca.pem",
"storage-driver": "overlay2",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
13 changes: 13 additions & 0 deletions docker/socket_exposure/config/daemon-unsafe.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"hosts": [
"unix:///var/run/docker.sock",
"tcp://0.0.0.0:2375",
"tcp://127.0.0.1:2376"
],
"storage-driver": "overlay2",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
29 changes: 29 additions & 0 deletions docker/socket_exposure/config/docker-safe.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service time-set.target
Wants=network-online.target containerd.service
Requires=docker.socket containerd.service

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock --tls --tlscert=/etc/docker/certs/server-cert.pem --tlskey=/etc/docker/certs/server-key.pem --tlsverify --tlscacert=/etc/docker/certs/ca.pem
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutStartSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
OOMScoreAdjust=-500

[Install]
WantedBy=multi-user.target
27 changes: 27 additions & 0 deletions docker/socket_exposure/config/docker-unsafe.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service time-set.target
Wants=network-online.target containerd.service
Requires=docker.socket containerd.service

[Service]
Type=notify
# INSECURE: Exposing Docker daemon on TCP without TLS
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375 -H tcp://127.0.0.1:2376
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutStartSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
OOMScoreAdjust=-500

[Install]
WantedBy=multi-user.target
40 changes: 40 additions & 0 deletions docker/socket_exposure/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
version: '3.8'

networks:
docker_socket_test:
ipam:
config:
- subnet: 172.30.0.0/24

services:
docker_socket_safe:
container_name: docker_socket_safe
build:
context: .
dockerfile: DockerfileSafe
image: docker_socket_safe:latest
networks:
docker_socket_test:
ipv4_address: 172.30.0.10
healthcheck:
test: ["CMD", "test", "-f", "/var/run/docker.sock"]
interval: 10s
timeout: 5s
retries: 3
start_period: 5s

docker_socket_unsafe:
container_name: docker_socket_unsafe
build:
context: .
dockerfile: DockerfileUnsafe
image: docker_socket_unsafe:latest
networks:
docker_socket_test:
ipv4_address: 172.30.0.20
healthcheck:
test: ["CMD", "test", "-f", "/var/run/docker.sock"]
interval: 10s
timeout: 5s
retries: 3
start_period: 5s