Scanning the Remote Host for Unauthenticated Docker API Access

Scanning the Remote Host for Unauthenticated Docker API Access


Basic Behavior of Docker Daemon

ပုံမှန်အားဖြင့် Docker daemon သည် docker run, docker pull, docker images စသည့် Docker CLI command များကို local machine ပေါ်တွင်သာ အသုံးပြုခွင့်ပြုထားပါသည်။

Remote Access Setup

System administrator များအနေဖြင့် Docker daemon ကို HTTP API မှတစ်ဆင့် remote access ရယူနိုင်ရန် configure လုပ်နိုင်သည်။ သို့သော် ဤသို့ပြုလုပ်ခြင်းသည် security risks များ ရှိနိုင်သည်။

Security Issues

Docker daemon ကို HTTP API တွေမှတစ်ဆင့် expose လုပ်ခြင်းသည် အလွန်အန္တရာယ် ရှိသည်။

  • No authentication involved: Default အနေဖြင့် API တွေသည် authentication မပါဝင်ခြင်းကြောင့် unauthorized access ဖြစ်နိုင်ပါသည်။

  • Exclusion of Transport-Level Security: TLS သို့မဟုတ် HTTPS မပါဝင်သောကြောင့် Data transmission လမ်းကြောင်းတွင် လုံခြုံမှု အားနည်းသည်။

Security Best Practices

Remote access setup expose လုပ်ထားသော Docker daemons တွေကို secure ဖြစ်အောင် အောက်ပါတို့ လိုက်နာရပါမည်။

  • TLS/HTTPS ကို အသုံးပြုရန်: Secure communication အတွက် transport-level encryption ဖြင့် API access ပြုလုပ်ပါ။

  • Access Control: အထူးသဖြင့် firewall configuration များ၊ IP whitelist များ ဖြင့် access restriction ထည့်သွင်းပါ။

  • Authentication Mechanism: API access ကို secure အောင် username/password authentication သို့မဟုတ် certificate-based authentication တို့ သုံးပါ။

Security အတွက် ဤကဲ့သို့ ပြုလုပ်ခြင်းသည် Docker daemon နှင့် HTTP API တွေကို external threats တွေမှ ကာကွယ်ရန် အလွန်အရေးကြီးသည်။ မလိုအပ်ဘဲ remote access မဖွင့်သင့်ပါ။


Step 1: Scan for Docker Service Running on Port 2375:

Run an nmap scan on the port range 1-5000 to check for a Docker service running on the prod-docker machine or IP address.

docker run --rm instrumentisto/nmap -p 1-5000 prod-docker/ip

Command Output:

Starting Nmap 7.80 ( https://nmap.org ) at 2023-08-21 14:32 UTC
Nmap scan report for prod-docker (10.x.x.x)
Host is up (0.000011s latency).
rDNS record for 10.1.121.152: prod-1gz06czr.lab
Not shown: 4997 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
2375/tcp open  docker

Nmap done: 1 IP address (1 host up) scanned in 0.33 seconds

As shown in the nmap scan above, TCP port 2375 is open, and the service running on that port is identified as Docker.


Step 2: Interacting with Docker API Using curl:

Since the Docker API is exposed on port 2375, we will use curl to interact with it.

  1. Check the response for a simple request:
curl http://prod-docker:2375

Command Output:

{"message":"page not found"}

It seems there is a server responding to our request, but it returns a "page not found" error, indicating that the requested resource does not exist on the server.

  1. Try accessing the /version endpoint:
curl http://prod-docker:2375/version

Command Output:

{
    "Platform": {
        "Name": "Docker Engine - Community"
    },
    "Components": [
        {
            "Name": "Engine",
            "Version": "20.10.10",
            "Details": {
                "ApiVersion": "1.41",
                "Arch": "amd64",
                "BuildTime": "2021-10-25T07:41:08.000000000+00:00",
                "Experimental": "false",
                "GitCommit": "e2f740d",
                "GoVersion": "go1.16.9",
                "KernelVersion": "5.4.0-155-generic",
                "MinAPIVersion": "1.12",
                "Os": "linux"
            }
        },
        {
            "Name": "containerd",
            "Version": "1.5.10",
            "Details": {
                "GitCommit": "2a1d4dbdb2a1030dc5b01e96fb110a9d9f150ecc"
            }
        },
        {
            "Name": "runc",
            "Version": "1.0.3",
            "Details": {
                "GitCommit": "v1.0.3-0-gf46b6ba"
            }
        },
        {
            "Name": "docker-init",
            "Version": "0.19.0",
            "Details": {
                "GitCommit": "de40ad0"
            }
        }
    ],
    "Version": "20.10.10",
    "ApiVersion": "1.41",
    "MinAPIVersion": "1.12",
    "GitCommit": "e2f740d",
    "GoVersion": "go1.16.9",
    "Os": "linux",
    "Arch": "amd64",
    "KernelVersion": "5.4.0-155-generic",
    "BuildTime": "2021-10-25T07:41:08.000000000+00:00"
}

We can see the Docker version information, indicating that we are able to successfully interact with the Docker daemon on a remote system using its HTTP APIs.


Challenges: Exploring Exposed Docker APIs

Tasks:

  1. List the images on the remote host prod-docker using the curl command:
curl http://prod-docker:2375/images/json
  1. List all containers on the remote host prod-docker using the curl command:
curl http://prod-docker:2375/containers/json

Docker Daemon Security Lab Guide

Lab 1: TLS Certificate Setup and Daemon Configuration

Step 1: Creating the Certificate Authority and TLS Certificates

# Create Directory
mkdir -p ~/docker-certs
cd ~/docker-certs

# Generate CA Private Key
openssl genrsa -aes256 -out ca-key.pem 4096

# Generate CA Public Key
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem

# Generate Server Key
openssl genrsa -out server-key.pem 4096

# Generate Server CSR
openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr

# Generate Server Certificate
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem

# Generate Client Key
openssl genrsa -out key.pem 4096

# Generate Client CSR
openssl req -subj '/CN=client' -new -key key.pem -out client.csr

# Generate Client Certificate
openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem

Step 2: Docker Daemon Configuration

# Add the following configuration to the /etc/docker/daemon.json file
{
  "tls": true,
  "tlscacert": "/root/docker-certs/ca.pem",
  "tlscert": "/root/docker-certs/server-cert.pem",
  "tlskey": "/root/docker-certs/server-key.pem",
  "tlsverify": true,
  "hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]
}

Step 3: Restart Docker Service

sudo systemctl restart docker

Lab 2: Firewall Configuration

Step 1: UFW Firewall Rules

# Enable UFW
sudo ufw enable

# Allow Docker daemon port only for specific IPs
sudo ufw allow from 192.168.1.0/24 to any port 2376

# Default deny rule
sudo ufw default deny incoming

Step 2: IP Tables Rules

# Allow Docker API port for a specific IP range only
sudo iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 2376 -j ACCEPT

# Block for other IPs
sudo iptables -A INPUT -p tcp --dport 2376 -j DROP

Lab 3: Testing Connection from Client

Step 1: Connecting from Client to Docker Daemon

# Set environment variables on the client machine
export DOCKER_HOST=tcp://server-ip:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=/path/to/client/certificates

# Test connection
docker info

Step 2: Test Connection Operations

# View list of containers
docker ps

# Run test container
docker run hello-world

Security Checklist

  1. Check certificate validity:
openssl verify -CAfile ca.pem server-cert.pem
openssl verify -CAfile ca.pem cert.pem
  1. Check firewall rules:
sudo ufw status
sudo iptables -L
  1. Check Docker daemon configuration:
sudo docker info | grep -i "Server Version"
sudo netstat -tlpn | grep docker

Advanced Security Measures for Production Environment

1. Certificate Management and Rotation

# Certificate expiration alert script
#!/bin/bash
CERT_PATH="/path/to/certs/"
THRESHOLD_DAYS=30

for cert in $(find $CERT_PATH -name "*.pem"); do
    exp_date=$(openssl x509 -enddate -noout -in $cert | cut -d= -f2)
    exp_epoch=$(date -d "${exp_date}" +%s)
    current_epoch=$(date +%s)
    diff_days=$(( ($exp_epoch - $current_epoch) / 86400 ))

    if [ $diff_days -lt $THRESHOLD_DAYS ]; then
        echo "WARNING: Certificate $cert will expire in $diff_days days"
        # Add email/slack notification for alerts
    fi
done

2. Access Control and RBAC (Role-Based Access Control)

# /etc/docker/daemon.json
{
    "authorization-plugins": ["authz-broker"],
    "userland-proxy": false,
    "live-restore": true,
    "userns-remap": "default",
    "no-new-privileges": true
}

3. Network Security Enhancement

3.1 Network Segmentation

# Create isolated production network
docker network create --driver overlay \
  --subnet=172.20.0.0/16 \
  --ip-range=172.20.10.0/24 \
  --gateway=172.20.10.11 \
  --opt encrypted \
  prod-network

3.2 Advanced Firewall Rules

# Add rate limiting
iptables -A INPUT -p tcp --dport 2376 -m state --state NEW -m recent \
  --set --name docker-api

iptables -A INPUT -p tcp --dport 2376 -m state --state NEW -m recent \
  --update --seconds 60 --hitcount 10 --rttl --name docker-api -j DROP

4. Monitoring and Logging

4.1 Audit Logging Setup

# auditd configuration (/etc/audit/rules.d/audit.rules)
-w /usr/bin/docker -p wa -k docker_bin
-w /var/lib/docker -p wa -k docker_lib
-w /etc/docker -p wa -k docker_etc
-w /lib/systemd/system/docker.service -p wa -k docker_service

4.2 Log Aggregation

# Docker logging configuration
{
  "log-driver": "syslog",
  "log-opts": {
    "syslog-address": "udp://logs.example.com:514",
    "syslog-facility": "daemon",
    "tag": "{{.Name}}/{{.ID}}"
  }
}

5. Container Security

5.1 Security Profiles

# Default seccomp profile
{
    "defaultAction": "SCMP_ACT_ERRNO",
    "architectures": ["SCMP_ARCH_X86_64"],
    "syscalls": [
        {
            "names": ["accept", "access", "arch_prctl"],
            "action": "SCMP_ACT_ALLOW"
        }
    ]
}

5.2 Resource Limits

# Container resource limits
docker run -d \
  --cpus=".5" \
  --memory="512m" \
  --memory-swap="1g" \
  --pids-limit=100 \
  --ulimit nofile=1024:1024 \
  your-container

6. Automated Security Scanning

6.1 Image Scanning

# Using Trivy scanner
trivy image your-image:tag

# Update vulnerability database
trivy image --download-db-only

6.2 Runtime Security

# Falco rules configuration
- rule: Terminal Shell in Container
  desc: A shell was spawned by a container with an attached terminal
  condition: container.id != host and proc.name = bash
  output: "Shell spawned in a container (user=%user.name container=%container.id)"
  priority: WARNING

7. Backup and Disaster Recovery

7.1 Automated Backup Script

#!/bin/bash
BACKUP_DIR="/backup/docker"
DATE=$(date +%Y%m%d)

# Backup Docker configuration
tar -czf $BACKUP_DIR/docker-config-$DATE.tar.gz \
    /etc/docker \
    /var/lib/docker/volumes

# Backup certificates
tar -czf $BACKUP_DIR/docker-certs-$DATE.tar.gz \
    /path/to/docker/certs

# Encrypt
gpg --encrypt --recipient admin@company.com \
    $BACKUP_DIR/docker-config-$DATE.tar.gz

8. Regular Security Auditing

8.1 Security Audit Checklist

  1. Certificate checks

  2. Firewall rules review

  3. Access logs inspection

  4. Network security checks

  5. Resource usage monitoring

  6. Container security scan

  7. System updates and patches

8.2 Automated Security Testing

# Using Docker Bench Security
docker run -it --net host --pid host --userns host --cap-add audit_control \
    -v /var/lib:/var/lib \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /usr/lib/systemd:/usr/lib/systemd \
    -v /etc:/etc --label docker_bench_security \
    docker/docker-bench-security