From cba2ff47f397783ae60fbf1b06f876e3182d544a Mon Sep 17 00:00:00 2001 From: Apple Date: Fri, 9 Jan 2026 02:04:11 -0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9A=20docs(security):=20Add=20comprehe?= =?UTF-8?q?nsive=20Security=20chapter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## New Security Documentation Structure /security/ ├── README.md # Security overview & contacts ├── forensics-checklist.md # Incident investigation guide ├── persistence-scan.sh # Quick persistence detector ├── runtime-detector.sh # Mining/suspicious process detector └── hardening/ ├── docker.md # Docker security baseline ├── kubernetes.md # K8s policies (future reference) └── cloud.md # Hetzner-specific hardening ## Key Components ### Forensics Checklist - Process analysis commands - Persistence mechanism detection - Network connection analysis - File system inspection - Authentication audit - Decision matrix for threat response ### Scripts - persistence-scan.sh: Cron, systemd, executables, SSH keys - runtime-detector.sh: Mining process detection with --kill option ### Hardening Guides - Docker: Secure compose template, Dockerfile best practices - Kubernetes: NetworkPolicy, PodSecurityStandard, Falco rules - Cloud: Egress firewall, SSH hardening, fail2ban, monitoring ## Post-Incident Documentation Based on lessons learned from Incidents #1 and #2 (Jan 2026) Co-authored-by: Cursor Agent --- security/README.md | 96 ++++++++++ security/forensics-checklist.md | 293 ++++++++++++++++++++++++++++ security/hardening/cloud.md | 310 ++++++++++++++++++++++++++++++ security/hardening/docker.md | 310 ++++++++++++++++++++++++++++++ security/hardening/kubernetes.md | 316 +++++++++++++++++++++++++++++++ security/persistence-scan.sh | 170 +++++++++++++++++ security/runtime-detector.sh | 217 +++++++++++++++++++++ 7 files changed, 1712 insertions(+) create mode 100644 security/README.md create mode 100644 security/forensics-checklist.md create mode 100644 security/hardening/cloud.md create mode 100644 security/hardening/docker.md create mode 100644 security/hardening/kubernetes.md create mode 100755 security/persistence-scan.sh create mode 100755 security/runtime-detector.sh diff --git a/security/README.md b/security/README.md new file mode 100644 index 00000000..a0660713 --- /dev/null +++ b/security/README.md @@ -0,0 +1,96 @@ +# 🔐 Security — DAARION Infrastructure + +**Версія:** 1.0.0 +**Останнє оновлення:** 2026-01-09 +**Статус:** Production Active + +--- + +## 📋 Зміст + +| Документ | Призначення | +|----------|-------------| +| [forensics-checklist.md](./forensics-checklist.md) | Чекліст розслідування інцидентів | +| [persistence-scan.sh](./persistence-scan.sh) | Скрипт виявлення persistence | +| [runtime-detector.sh](./runtime-detector.sh) | Детектор підозрілих процесів | +| [hardening/docker.md](./hardening/docker.md) | Docker security baseline | +| [hardening/kubernetes.md](./hardening/kubernetes.md) | Kubernetes security policies | +| [hardening/cloud.md](./hardening/cloud.md) | Cloud security (Hetzner) | + +--- + +## 🎯 Принципи безпеки DAARION + +### 1. Defense in Depth + +``` +[Network] → [Container] → [Process] → [Data] + ↓ ↓ ↓ ↓ + Firewall read-only runtime encrypt + egress cap_drop detection at rest +``` + +### 2. Zero Trust + +- Кожен сервіс має мінімальні привілеї +- Мережевий доступ deny-by-default +- Аутентифікація для всіх internal API + +### 3. Detect → Respond → Prevent + +``` +[Incident] → [Forensics] → [Root Cause] → [Hardening] → [Monitoring] +``` + +--- + +## 🚨 Incident Response Flow + +### При виявленні підозрілої активності: + +```bash +# 1. Detect +./security/persistence-scan.sh +./security/runtime-detector.sh + +# 2. Contain +docker stop +iptables -I OUTPUT -d 0.0.0.0/0 -j DROP # emergency + +# 3. Investigate +./security/forensics-checklist.md # follow checklist + +# 4. Remediate +# Based on findings + +# 5. Document +# Update INFRASTRUCTURE.md with incident details +``` + +--- + +## 📊 Security Metrics + +| Metric | Target | Current | +|--------|--------|---------| +| Containers with `read_only` | 100% | 🔄 In progress | +| Services with `cap_drop: ALL` | 100% | 🔄 In progress | +| Egress firewall rules | Active | ✅ Active | +| Runtime detection | Active | 🔄 Planned | +| Vulnerability scan frequency | Weekly | 🔄 Planned | + +--- + +## 📞 Security Contacts + +- **Security Lead:** admin@daarion.city +- **Hetzner Abuse:** abuse@hetzner.com +- **Emergency:** Submit statement via Hetzner Robot + +--- + +## 📚 Related Documents + +- [INFRASTRUCTURE.md](../INFRASTRUCTURE.md) — Infrastructure overview + Incident history +- [SECURITY-REBUILD-REPORT.md](../SECURITY-REBUILD-REPORT.md) — daarion-web incident analysis +- [TASK_REBUILD_DAARION_WEB.md](../TASK_REBUILD_DAARION_WEB.md) — Rebuild task details diff --git a/security/forensics-checklist.md b/security/forensics-checklist.md new file mode 100644 index 00000000..31b61725 --- /dev/null +++ b/security/forensics-checklist.md @@ -0,0 +1,293 @@ +# 🔍 Forensics Checklist — Incident Investigation + +**Мета:** Відповісти на 3 критичні питання: + +1. **Як саме зайшли** (initial access vector) +2. **Чи є persistence** (чи повернеться знову) +3. **Чи можна довіряти системі далі** (чи потрібен rebuild) + +--- + +## 📋 Швидкий чекліст + +### A. Process-level Analysis + +```bash +# Всі процеси з деревом +ps auxf + +# Top CPU consumers +ps -eo pid,ppid,user,cmd,%cpu,%mem --sort=-%cpu | head -20 + +# Процеси конкретного користувача (напр. container user 1001) +ps aux | grep "1001" + +# Zombie процеси +ps aux | grep defunct | wc -l +``` + +**🔴 Red flags:** +- Дивні назви: `softirq`, `.syslog`, `catcal`, `G4NQXBp`, `vrarhpb` +- Процеси без батьків (orphans) +- user ≠ expected +- CPU > 50% на невідомому процесі + +--- + +### B. Persistence Mechanisms + +```bash +# Cron jobs +crontab -l +cat /etc/crontab +ls -la /etc/cron.d/ +ls -la /etc/cron.daily/ +ls -la /etc/cron.hourly/ + +# Systemd services +systemctl list-unit-files --state=enabled +ls -la /etc/systemd/system/ +ls -la /usr/lib/systemd/system/ + +# Init scripts +ls -la /etc/init.d/ +ls -la /etc/rc.local + +# Docker auto-restart +docker ps --filter "restart=always" +docker ps --filter "restart=unless-stopped" +``` + +**🔴 Red flags:** +- Незнайомі cron jobs +- Нові systemd services +- Контейнери з `restart: unless-stopped` + compromised + +--- + +### C. Network Analysis + +```bash +# Listening ports +ss -tulpn +netstat -tulpn + +# Active connections +ss -antp +netstat -antp + +# Firewall rules +iptables -L -n -v +iptables -L -n -v -t nat + +# DNS queries (if available) +cat /var/log/syslog | grep -i dns +``` + +**🔴 Red flags:** +- Outbound до mining pools (порти 3333, 5555, 7777, 14433) +- Нові listening ports +- З'єднання до unknown IP + +**Known mining pool patterns:** +``` +*pool* +*xmr* +*monero* +*crypto* +*.ru:* +*.cn:* +``` + +--- + +### D. File System Analysis + +```bash +# Executable files in temp directories +find /tmp /var/tmp /dev/shm -type f -executable 2>/dev/null + +# Recently modified binaries +find /usr/bin /usr/local/bin /usr/sbin -mtime -3 2>/dev/null + +# Hidden files in home directories +find /root /home -name ".*" -type f 2>/dev/null + +# Large files in unexpected places +find /tmp /var/tmp -size +10M 2>/dev/null + +# SUID/SGID binaries +find / -perm -4000 -type f 2>/dev/null +find / -perm -2000 -type f 2>/dev/null +``` + +**🔴 Red flags:** +- Executables в /tmp, /dev/shm +- Нещодавно змінені системні бінарники +- Hidden files з executable permissions + +--- + +### E. Authentication & Access + +```bash +# Login history +last +lastlog +who + +# SSH keys +grep -R "ssh-rsa" /root/.ssh /home 2>/dev/null +cat /root/.ssh/authorized_keys +ls -la /root/.ssh/ + +# Failed logins +grep "Failed" /var/log/auth.log | tail -50 +grep "Accepted" /var/log/auth.log | tail -50 + +# Sudo usage +grep "sudo" /var/log/auth.log | tail -50 +``` + +**🔴 Red flags:** +- Незнайомі SSH ключі +- Логіни з unknown IP +- Нові користувачі + +--- + +### F. Docker-specific + +```bash +# All containers (including stopped) +docker ps -a + +# Container processes +docker top + +# Container logs +docker logs --tail 100 + +# Docker images +docker images + +# Docker networks +docker network ls +docker network inspect + +# Container inspect (look for mounts, env vars) +docker inspect +``` + +**🔴 Red flags:** +- Контейнери з `--privileged` +- Mounted host directories (особливо /) +- Unknown images + +--- + +## 📊 Decision Matrix + +| Знахідка | Рівень загрози | Дія | +|----------|----------------|-----| +| Підозрілий процес, CPU > 50% | 🔴 Critical | Kill + investigate | +| Cron job до unknown binary | 🔴 Critical | Remove + investigate | +| New SSH key | 🔴 Critical | Remove + rotate all | +| Outbound to mining pool | 🔴 Critical | Block + kill | +| Modified system binary | 🔴 Critical | Full rebuild | +| Container with persistence | 🟡 High | Remove container + image | +| Unknown listening port | 🟡 High | Investigate + block | +| Failed SSH attempts | 🟢 Low | Monitor + fail2ban | + +--- + +## 🔧 Post-Investigation Actions + +### If compromised (any 🔴 finding): + +1. **Contain:** + ```bash + # Stop affected services + docker stop + + # Block outbound (emergency) + iptables -I OUTPUT -d 0.0.0.0/0 -p tcp --dport 22 -j DROP + ``` + +2. **Preserve evidence:** + ```bash + # Save process list + ps auxf > /root/evidence/ps_$(date +%Y%m%d_%H%M%S).txt + + # Save network connections + ss -antp > /root/evidence/ss_$(date +%Y%m%d_%H%M%S).txt + + # Save Docker state + docker ps -a > /root/evidence/docker_$(date +%Y%m%d_%H%M%S).txt + ``` + +3. **Eradicate:** + ```bash + # Kill processes + kill -9 + + # Remove persistence + crontab -r + systemctl disable + + # Remove Docker artifacts + docker stop + docker rm + docker rmi # CRITICAL! + ``` + +4. **Recover:** + - Rebuild from clean source + - Apply hardening + - Monitor for recurrence + +5. **Document:** + - Update INFRASTRUCTURE.md + - Create incident report + - Update hardening procedures + +--- + +## 📝 Incident Report Template + +```markdown +## Incident Report: [Title] + +**Date:** YYYY-MM-DD HH:MM UTC +**Severity:** Critical/High/Medium/Low +**Status:** Resolved/Ongoing + +### Timeline +- HH:MM — Detection +- HH:MM — Containment +- HH:MM — Eradication +- HH:MM — Recovery + +### Root Cause +[Description of how the attack occurred] + +### Impact +- Services affected +- Data affected +- Downtime + +### Indicators of Compromise (IOCs) +- Process names +- File paths +- IP addresses +- Domains + +### Remediation +- Actions taken +- Hardening applied + +### Lessons Learned +- What worked +- What to improve +- Prevention measures +``` diff --git a/security/hardening/cloud.md b/security/hardening/cloud.md new file mode 100644 index 00000000..d2a6c9f9 --- /dev/null +++ b/security/hardening/cloud.md @@ -0,0 +1,310 @@ +# ☁️ Cloud Security Hardening — Hetzner + +**Версія:** 1.0.0 +**Provider:** Hetzner Dedicated (GEX44) +**Server:** NODE1 (144.76.224.179) + +--- + +## 🎯 Критичні налаштування + +### 1. Egress Firewall (№1 Priority) + +**Блокування внутрішніх мереж Hetzner:** + +```bash +#!/bin/bash +# /root/firewall-egress.sh + +# Block Hetzner internal networks (prevent scanning) +iptables -I OUTPUT -d 10.0.0.0/8 -j DROP +iptables -I OUTPUT -d 172.16.0.0/12 -j DROP +iptables -I OUTPUT -d 192.168.0.0/16 -j DROP + +# Allow necessary internal traffic +iptables -I OUTPUT -d 10.0.0.0/8 -p tcp --dport 443 -j ACCEPT +iptables -I OUTPUT -d 10.0.0.0/8 -p tcp --dport 80 -j ACCEPT + +# Log blocked attempts +iptables -I OUTPUT -d 10.0.0.0/8 -j LOG --log-prefix "BLOCKED_INTERNAL: " + +# Block known mining pool ports +MINING_PORTS="3333 5555 7777 14433 45700 45560 14444 9999" +for port in $MINING_PORTS; do + iptables -A OUTPUT -p tcp --dport $port -j DROP + iptables -A OUTPUT -p tcp --dport $port -j LOG --log-prefix "BLOCKED_MINING: " +done + +# Save rules +iptables-save > /etc/iptables/rules.v4 +``` + +### 2. SSH Hardening + +```bash +# /etc/ssh/sshd_config + +# Disable root login with password +PermitRootLogin prohibit-password + +# Use only SSH keys +PasswordAuthentication no +PubkeyAuthentication yes + +# Limit authentication attempts +MaxAuthTries 3 +MaxSessions 5 + +# Idle timeout +ClientAliveInterval 300 +ClientAliveCountMax 2 + +# Disable unused features +X11Forwarding no +AllowAgentForwarding no +AllowTcpForwarding no + +# Allow only specific users +AllowUsers root + +# Use strong ciphers +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com +``` + +### 3. Fail2ban Configuration + +```ini +# /etc/fail2ban/jail.local + +[DEFAULT] +bantime = 3600 +findtime = 600 +maxretry = 3 + +[sshd] +enabled = true +port = ssh +filter = sshd +logpath = /var/log/auth.log +maxretry = 3 +bantime = 86400 + +[docker-abuse] +enabled = true +filter = docker-abuse +logpath = /var/log/syslog +maxretry = 5 +bantime = 3600 +``` + +--- + +## 🔒 Network Security + +### UFW Configuration + +```bash +#!/bin/bash +# /root/setup-ufw.sh + +# Reset UFW +ufw --force reset + +# Default policies +ufw default deny incoming +ufw default deny outgoing + +# Allow SSH (from specific IPs if possible) +ufw allow in 22/tcp + +# Allow HTTP/HTTPS +ufw allow in 80/tcp +ufw allow in 443/tcp + +# Allow outbound DNS +ufw allow out 53/tcp +ufw allow out 53/udp + +# Allow outbound HTTP/HTTPS +ufw allow out 80/tcp +ufw allow out 443/tcp + +# Allow outbound to Docker registry +ufw allow out to any port 443 proto tcp + +# Block mining pools (additional layer) +# Add rules from firewall-egress.sh + +# Enable UFW +ufw --force enable +``` + +### Port Exposure Rules + +| Port | Service | Binding | Notes | +|------|---------|---------|-------| +| 22 | SSH | 0.0.0.0 | With fail2ban | +| 80 | Nginx | 0.0.0.0 | Redirect to 443 | +| 443 | Nginx | 0.0.0.0 | HTTPS only | +| 3000 | daarion-web | 127.0.0.1 | Via Nginx | +| 9102 | Router | 127.0.0.1 | Internal | +| 9300 | Gateway | 127.0.0.1 | Via Nginx | +| * | Other services | 127.0.0.1 | Never public | + +--- + +## 📊 Monitoring + +### System Monitoring Script + +```bash +#!/bin/bash +# /root/security-monitor.sh +# Run via cron every 5 minutes + +LOG_FILE="/var/log/security-monitor.log" +ALERT_THRESHOLD_CPU=80 +ALERT_THRESHOLD_LOAD=10 + +timestamp() { + date '+%Y-%m-%d %H:%M:%S' +} + +# Check load average +LOAD=$(cat /proc/loadavg | awk '{print $1}') +LOAD_INT=${LOAD%.*} + +if [ "$LOAD_INT" -gt "$ALERT_THRESHOLD_LOAD" ]; then + echo "[$(timestamp)] ALERT: High load average: $LOAD" >> $LOG_FILE + # Send alert (implement your notification) +fi + +# Check for mining processes +MINING=$(ps aux | grep -iE "xmrig|catcal|softirq|vrarhpb|miner" | grep -v grep) +if [ -n "$MINING" ]; then + echo "[$(timestamp)] CRITICAL: Mining process detected!" >> $LOG_FILE + echo "$MINING" >> $LOG_FILE + # Kill the process + echo "$MINING" | awk '{print $2}' | xargs -r kill -9 +fi + +# Check outbound connections to mining ports +MINING_CONN=$(ss -antp | grep -E ":(3333|5555|7777|14433)") +if [ -n "$MINING_CONN" ]; then + echo "[$(timestamp)] CRITICAL: Mining pool connection!" >> $LOG_FILE + echo "$MINING_CONN" >> $LOG_FILE +fi + +# Check Docker containers CPU +docker stats --no-stream --format "{{.Name}}: {{.CPUPerc}}" | while read line; do + CPU=$(echo "$line" | grep -oE '[0-9]+' | head -1) + if [ -n "$CPU" ] && [ "$CPU" -gt "$ALERT_THRESHOLD_CPU" ]; then + echo "[$(timestamp)] WARNING: High CPU container: $line" >> $LOG_FILE + fi +done +``` + +### Cron Setup + +```bash +# /etc/cron.d/security-monitor + +# Run security monitor every 5 minutes +*/5 * * * * root /root/security-monitor.sh + +# Run persistence scan daily +0 3 * * * root /opt/microdao-daarion/security/persistence-scan.sh >> /var/log/persistence-scan.log 2>&1 + +# Log rotation +0 0 * * * root find /var/log -name "*.log" -mtime +30 -delete +``` + +--- + +## 🚨 Incident Response (Hetzner) + +### При отриманні Abuse Report: + +1. **Негайно:** + ```bash + # Заблокувати весь вихідний трафік + iptables -I OUTPUT -j DROP + + # Зберегти стан для аналізу + ps auxf > /root/incident/ps_$(date +%s).txt + ss -antp > /root/incident/ss_$(date +%s).txt + docker ps -a > /root/incident/docker_$(date +%s).txt + ``` + +2. **Знайти джерело:** + ```bash + # Запустити forensics + /opt/microdao-daarion/security/persistence-scan.sh + /opt/microdao-daarion/security/runtime-detector.sh + ``` + +3. **Усунути загрозу:** + ```bash + # Kill процеси + killall -9 + + # Видалити контейнер ТА образ + docker stop + docker rm + docker rmi # КРИТИЧНО! + ``` + +4. **Відповісти Hetzner:** + - URL: https://statement-abuse.hetzner.com/statements/?token= + - Описати причину та вжиті заходи + - Зареєструвати retry test + +5. **Задокументувати:** + - Оновити INFRASTRUCTURE.md + - Створити incident report + +--- + +## 🔐 Secrets Management + +### Environment Variables + +```bash +# /opt/microdao-daarion/.env + +# NEVER commit to git! +# Use .env.example as template + +# Generate secure passwords +openssl rand -base64 32 + +# Store secrets securely +chmod 600 .env +chown root:root .env +``` + +### SSH Keys + +```bash +# Generate strong SSH key +ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519 + +# Rotate keys periodically +# Keep backup of old keys until rotation complete +``` + +--- + +## ✅ Hetzner Security Checklist + +- [ ] Egress firewall blocking internal networks +- [ ] Mining pool ports blocked +- [ ] SSH hardened (key-only, fail2ban) +- [ ] UFW configured (deny by default) +- [ ] All services bound to 127.0.0.1 except Nginx +- [ ] Security monitoring cron active +- [ ] Log rotation configured +- [ ] .env file secured (chmod 600) +- [ ] Rescue mode access documented +- [ ] Hetzner Robot access secured diff --git a/security/hardening/docker.md b/security/hardening/docker.md new file mode 100644 index 00000000..1ac6b9c4 --- /dev/null +++ b/security/hardening/docker.md @@ -0,0 +1,310 @@ +# 🐳 Docker Security Hardening — DAARION + +**Версія:** 1.0.0 +**Принцип:** Майнінг можливий тільки там, де дозволений **outbound + CPU без контролю** + +--- + +## 📋 Security Checklist + +### Must-Have (Обов'язково) + +| Налаштування | docker-compose | Пояснення | +|--------------|----------------|-----------| +| Read-only filesystem | `read_only: true` | Запобігає запису malware | +| Drop capabilities | `cap_drop: [ALL]` | Мінімальні привілеї | +| No new privileges | `security_opt: [no-new-privileges:true]` | Блокує privilege escalation | +| CPU limit | `cpus: '1.0'` | Обмежує crypto mining | +| Memory limit | `memory: 512M` | Запобігає DoS | +| Non-root user | `user: "1001:1001"` | Не root в контейнері | +| No privileged | `privileged: false` | Завжди! | + +--- + +## 🛡️ Secure docker-compose Template + +```yaml +version: '3.8' + +services: + secure-service: + image: your-image:tag + container_name: secure-service + + # ============================================ + # SECURITY HARDENING + # ============================================ + + # 1. Restart policy (use "no" until verified) + restart: "no" # Change to "unless-stopped" after verification + + # 2. Network binding (localhost only for internal services) + ports: + - "127.0.0.1:8080:8080" + + # 3. Read-only root filesystem + read_only: true + + # 4. Temporary filesystems (for apps that need write) + tmpfs: + - /tmp:size=64M,mode=1777 + - /app/cache:size=128M,mode=1777 + + # 5. Drop ALL capabilities + cap_drop: + - ALL + + # 6. Add only what's needed (rarely needed) + # cap_add: + # - NET_BIND_SERVICE # Only if port < 1024 + + # 7. Security options + security_opt: + - no-new-privileges:true + + # 8. Resource limits + deploy: + resources: + limits: + cpus: '1.0' + memory: 512M + reservations: + cpus: '0.25' + memory: 128M + + # 9. Process limits + pids_limit: 100 + + # 10. Disable privileged mode + privileged: false + + # 11. Non-root user + user: "1001:1001" + + # 12. Health check + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s + + # 13. Logging limits + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + # 14. Labels for audit + labels: + - "security.hardened=true" + - "security.reviewed=2026-01-09" + +networks: + default: + driver: bridge + driver_opts: + com.docker.network.bridge.enable_icc: "false" # Disable inter-container communication +``` + +--- + +## 🔧 Secure Dockerfile Template + +```dockerfile +# ============================================ +# Stage 1: Builder +# ============================================ +FROM node:20-alpine AS builder +WORKDIR /app + +# Copy only package files first (cache optimization) +COPY package*.json ./ +RUN npm ci --only=production --ignore-scripts + +COPY . . +RUN npm run build + +# ============================================ +# Stage 2: Production (minimal) +# ============================================ +FROM node:20-alpine AS production + +# Security: Create non-root user +RUN addgroup -g 1001 -S appgroup && \ + adduser -u 1001 -S appuser -G appgroup + +WORKDIR /app + +# Security: Remove unnecessary tools +RUN apk del --purge wget curl busybox-extras && \ + rm -rf /var/cache/apk/* /tmp/* /var/tmp/* + +# Copy from builder +COPY --from=builder --chown=appuser:appgroup /app/dist ./dist +COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules +COPY --from=builder --chown=appuser:appgroup /app/package.json ./ + +# Security: Restrictive permissions +RUN chmod -R 500 /app && \ + chmod 400 /app/package.json + +# Switch to non-root +USER appuser + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \ + CMD node -e "require('http').get('http://localhost:8080/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))" + +EXPOSE 8080 +CMD ["node", "dist/server.js"] +``` + +--- + +## 🚫 Anti-Patterns (НЕ робіть) + +```yaml +# ❌ NEVER DO THIS: + +services: + insecure: + privileged: true # ❌ Full host access + + ports: + - "8080:8080" # ❌ Binds to 0.0.0.0 (public) + + volumes: + - /:/host # ❌ Full host filesystem + - /var/run/docker.sock:/var/run/docker.sock # ❌ Docker escape + + cap_add: + - SYS_ADMIN # ❌ Too powerful + - NET_ADMIN # ❌ Network manipulation + + restart: unless-stopped # ❌ Without verification + + # No resource limits # ❌ Crypto mining possible + # No read_only # ❌ Malware can persist + # No user specification # ❌ Runs as root +``` + +--- + +## 📊 Security Scanning + +### Pre-deployment scan + +```bash +# Install Trivy +brew install trivy # macOS +apt install trivy # Ubuntu + +# Scan image for vulnerabilities +trivy image --severity HIGH,CRITICAL your-image:tag + +# Scan with detailed output +trivy image --format json -o scan-report.json your-image:tag + +# Scan Dockerfile +trivy config Dockerfile +``` + +### CI/CD Integration + +```yaml +# .github/workflows/security-scan.yml +name: Security Scan + +on: [push, pull_request] + +jobs: + scan: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Build image + run: docker build -t app:${{ github.sha }} . + + - name: Run Trivy scan + uses: aquasecurity/trivy-action@master + with: + image-ref: 'app:${{ github.sha }}' + format: 'table' + exit-code: '1' + severity: 'HIGH,CRITICAL' +``` + +--- + +## 🔍 Runtime Monitoring + +### Container inspection + +```bash +# Check container security settings +docker inspect --format=' + Privileged: {{.HostConfig.Privileged}} + ReadonlyRootfs: {{.HostConfig.ReadonlyRootfs}} + User: {{.Config.User}} + CapDrop: {{.HostConfig.CapDrop}} + CapAdd: {{.HostConfig.CapAdd}} +' container_name +``` + +### Resource monitoring + +```bash +# Real-time stats +docker stats container_name + +# CPU limit check +docker inspect --format='{{.HostConfig.NanoCpus}}' container_name + +# Memory limit check +docker inspect --format='{{.HostConfig.Memory}}' container_name +``` + +--- + +## 📝 DAARION-specific Rules + +### Services that MUST have hardening: + +| Service | Priority | Notes | +|---------|----------|-------| +| daarion-web | 🔴 Critical | Post-incident, see Dockerfile.secure | +| dagi-gateway | 🔴 Critical | Public-facing | +| dagi-router | 🟡 High | Core routing | +| All others | 🟡 High | Apply baseline | + +### Network rules: + +```yaml +# Internal services: bind to localhost +ports: + - "127.0.0.1:PORT:PORT" + +# Public services: use Nginx reverse proxy +# Never expose directly to 0.0.0.0 +``` + +--- + +## ✅ Verification Checklist + +Before deploying any container: + +- [ ] Image scanned with Trivy (no HIGH/CRITICAL) +- [ ] `read_only: true` set +- [ ] `cap_drop: [ALL]` set +- [ ] `security_opt: [no-new-privileges:true]` set +- [ ] CPU/memory limits set +- [ ] Non-root user configured +- [ ] Health check defined +- [ ] Restart policy is "no" for new deployments +- [ ] Port bound to 127.0.0.1 (unless public) +- [ ] No privileged mode +- [ ] No dangerous volume mounts diff --git a/security/hardening/kubernetes.md b/security/hardening/kubernetes.md new file mode 100644 index 00000000..73ea60f1 --- /dev/null +++ b/security/hardening/kubernetes.md @@ -0,0 +1,316 @@ +# ☸️ Kubernetes Security Hardening — DAARION + +**Версія:** 1.0.0 +**Статус:** Reference (для майбутньої K8s міграції) + +--- + +## 🎯 Критичні налаштування + +### 1. NetworkPolicy (Egress deny-by-default) + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: default-deny-egress + namespace: daarion +spec: + podSelector: {} + policyTypes: + - Egress + egress: [] # Deny all outbound by default +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-dns-only + namespace: daarion +spec: + podSelector: {} + policyTypes: + - Egress + egress: + - to: + - namespaceSelector: + matchLabels: + name: kube-system + ports: + - protocol: UDP + port: 53 +``` + +### 2. PodSecurityStandard: Restricted + +```yaml +apiVersion: v1 +kind: Namespace +metadata: + name: daarion + labels: + pod-security.kubernetes.io/enforce: restricted + pod-security.kubernetes.io/audit: restricted + pod-security.kubernetes.io/warn: restricted +``` + +### 3. Secure Pod Template + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: secure-pod + namespace: daarion +spec: + # Security Context (Pod level) + securityContext: + runAsNonRoot: true + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + seccompProfile: + type: RuntimeDefault + + # Service Account + serviceAccountName: minimal-sa + automountServiceAccountToken: false + + containers: + - name: app + image: your-image:tag + + # Security Context (Container level) + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1001 + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + + # Resource limits (CRITICAL for anti-mining) + resources: + requests: + cpu: "100m" + memory: "128Mi" + limits: + cpu: "1000m" # Max 1 CPU + memory: "512Mi" + + # Liveness/Readiness probes + livenessProbe: + httpGet: + path: /health + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 30 + + readinessProbe: + httpGet: + path: /ready + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 10 + + # Volume mounts (if needed) + volumeMounts: + - name: tmp + mountPath: /tmp + - name: cache + mountPath: /app/cache + + # Temporary volumes + volumes: + - name: tmp + emptyDir: + sizeLimit: 64Mi + - name: cache + emptyDir: + sizeLimit: 128Mi +``` + +--- + +## 🛡️ Security Policies + +### ResourceQuota (Namespace limits) + +```yaml +apiVersion: v1 +kind: ResourceQuota +metadata: + name: daarion-quota + namespace: daarion +spec: + hard: + requests.cpu: "10" + requests.memory: 20Gi + limits.cpu: "20" + limits.memory: 40Gi + pods: "50" +``` + +### LimitRange (Default limits) + +```yaml +apiVersion: v1 +kind: LimitRange +metadata: + name: daarion-limits + namespace: daarion +spec: + limits: + - type: Container + default: + cpu: "500m" + memory: "256Mi" + defaultRequest: + cpu: "100m" + memory: "128Mi" + max: + cpu: "2" + memory: "1Gi" +``` + +--- + +## 🔍 Runtime Detection (Falco) + +### Falco Rule: Crypto Mining Detection + +```yaml +# falco-rules.yaml +- rule: Detect Crypto Mining Process + desc: Detect processes commonly used for cryptocurrency mining + condition: > + spawned_process and + (proc.name in (xmrig, minerd, cpuminer, cgminer, bfgminer, ethminer, + catcal, softirq, vrarhpb, G4NQXBp) or + proc.cmdline contains "stratum+" or + proc.cmdline contains "pool" or + proc.cmdline contains "cryptonight") + output: > + Crypto mining process detected + (user=%user.name command=%proc.cmdline container=%container.name + image=%container.image.repository) + priority: CRITICAL + tags: [cryptomining, mitre_execution] + +- rule: Detect Connection to Mining Pool + desc: Detect outbound connections to known mining pool ports + condition: > + outbound and + (fd.sport in (3333, 5555, 7777, 14433, 45700, 45560, 14444, 9999)) + output: > + Connection to potential mining pool + (user=%user.name command=%proc.cmdline connection=%fd.name + container=%container.name) + priority: CRITICAL + tags: [cryptomining, network] + +- rule: High CPU in Container + desc: Detect containers with sustained high CPU usage + condition: > + container and + container.cpu.usage > 80 + output: > + High CPU usage in container + (container=%container.name cpu=%container.cpu.usage%) + priority: WARNING + tags: [performance, cryptomining] +``` + +### Falco Deployment + +```yaml +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: falco + namespace: falco +spec: + selector: + matchLabels: + app: falco + template: + metadata: + labels: + app: falco + spec: + serviceAccountName: falco + containers: + - name: falco + image: falcosecurity/falco:latest + securityContext: + privileged: true + volumeMounts: + - name: proc + mountPath: /host/proc + readOnly: true + - name: rules + mountPath: /etc/falco/rules.d + volumes: + - name: proc + hostPath: + path: /proc + - name: rules + configMap: + name: falco-rules +``` + +--- + +## 📊 Monitoring & Alerting + +### Prometheus Rules + +```yaml +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: daarion-security-rules + namespace: monitoring +spec: + groups: + - name: security + rules: + - alert: HighCPUUsage + expr: > + sum(rate(container_cpu_usage_seconds_total{namespace="daarion"}[5m])) + by (pod) > 0.8 + for: 5m + labels: + severity: warning + annotations: + summary: "High CPU usage in pod {{ $labels.pod }}" + + - alert: UnauthorizedNetworkConnection + expr: > + increase(falco_events_total{rule=~".*mining.*"}[5m]) > 0 + for: 1m + labels: + severity: critical + annotations: + summary: "Potential crypto mining detected" +``` + +--- + +## ✅ K8s Security Checklist + +Before deploying to Kubernetes: + +- [ ] Namespace has PodSecurityStandard: restricted +- [ ] NetworkPolicy: deny egress by default +- [ ] All pods have resource limits +- [ ] All pods run as non-root +- [ ] All pods have readOnlyRootFilesystem +- [ ] All pods drop ALL capabilities +- [ ] seccompProfile: RuntimeDefault +- [ ] No privileged containers +- [ ] ServiceAccount tokens not auto-mounted +- [ ] Falco or similar runtime detection deployed +- [ ] Resource quotas set on namespace diff --git a/security/persistence-scan.sh b/security/persistence-scan.sh new file mode 100755 index 00000000..6da7bdd8 --- /dev/null +++ b/security/persistence-scan.sh @@ -0,0 +1,170 @@ +#!/bin/bash +# ============================================ +# Persistence Scanner — DAARION Security +# Version: 1.0.0 +# Purpose: Quick detection of persistence mechanisms +# Usage: ./persistence-scan.sh +# ============================================ + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +echo -e "${BLUE}============================================${NC}" +echo -e "${BLUE} DAARION Persistence Scanner${NC}" +echo -e "${BLUE}============================================${NC}" +echo "" + +FINDINGS=0 + +# ============================================ +# 1. Cron Jobs +# ============================================ +echo -e "${YELLOW}[1/7] Checking cron jobs...${NC}" + +echo "User crontab:" +crontab -l 2>/dev/null || echo " (none)" + +echo "" +echo "System cron directories:" +for dir in /etc/cron.d /etc/cron.daily /etc/cron.hourly /etc/cron.weekly /etc/cron.monthly; do + if [ -d "$dir" ]; then + count=$(ls -1 "$dir" 2>/dev/null | wc -l) + echo " $dir: $count files" + if [ $count -gt 0 ]; then + ls -la "$dir" 2>/dev/null | grep -v "^total" | head -10 + fi + fi +done + +# ============================================ +# 2. Systemd Services +# ============================================ +echo "" +echo -e "${YELLOW}[2/7] Checking systemd services...${NC}" + +echo "Enabled services (excluding common):" +systemctl list-unit-files --state=enabled 2>/dev/null | \ + grep -vE "(ssh|network|system|docker|cron|rsyslog|ufw|fail2ban|nginx)" | \ + head -20 + +echo "" +echo "Custom services in /etc/systemd/system:" +ls -la /etc/systemd/system/*.service 2>/dev/null | grep -v "wants" | head -10 || echo " (none)" + +# ============================================ +# 3. Suspicious Executables +# ============================================ +echo "" +echo -e "${YELLOW}[3/7] Checking for suspicious executables...${NC}" + +echo "Executables in /tmp, /var/tmp, /dev/shm:" +SUSPICIOUS_EXEC=$(find /tmp /var/tmp /dev/shm -type f -executable 2>/dev/null) +if [ -n "$SUSPICIOUS_EXEC" ]; then + echo -e "${RED}⚠️ FOUND:${NC}" + echo "$SUSPICIOUS_EXEC" + FINDINGS=$((FINDINGS + 1)) +else + echo -e " ${GREEN}(none)${NC}" +fi + +echo "" +echo "Recently modified binaries (last 3 days):" +MODIFIED_BIN=$(find /usr/bin /usr/local/bin /usr/sbin -mtime -3 -type f 2>/dev/null) +if [ -n "$MODIFIED_BIN" ]; then + echo -e "${YELLOW}Modified:${NC}" + echo "$MODIFIED_BIN" | head -10 +else + echo -e " ${GREEN}(none)${NC}" +fi + +# ============================================ +# 4. High CPU Processes +# ============================================ +echo "" +echo -e "${YELLOW}[4/7] Checking high CPU processes...${NC}" + +echo "Top 15 by CPU:" +ps -eo pid,user,cmd,%cpu --sort=-%cpu | head -n 16 + +# Check for known mining process names +MINING_PATTERNS="xmrig|catcal|softirq|vrarhpb|G4NQXBp|kswapd|ksoftirqd|kworker.*mining|cryptonight" +MINING_PROC=$(ps aux | grep -iE "$MINING_PATTERNS" | grep -v grep) +if [ -n "$MINING_PROC" ]; then + echo "" + echo -e "${RED}⚠️ POTENTIAL MINING PROCESSES DETECTED:${NC}" + echo "$MINING_PROC" + FINDINGS=$((FINDINGS + 1)) +fi + +# ============================================ +# 5. Network Connections +# ============================================ +echo "" +echo -e "${YELLOW}[5/7] Checking network connections...${NC}" + +echo "Outbound connections:" +ss -antp 2>/dev/null | grep ESTAB | grep -v "127.0.0.1" | head -20 + +# Check for connections to known mining ports +MINING_PORTS="3333|5555|7777|14433|45700|45560" +MINING_CONN=$(ss -antp 2>/dev/null | grep -E ":($MINING_PORTS)") +if [ -n "$MINING_CONN" ]; then + echo "" + echo -e "${RED}⚠️ POTENTIAL MINING POOL CONNECTIONS:${NC}" + echo "$MINING_CONN" + FINDINGS=$((FINDINGS + 1)) +fi + +# ============================================ +# 6. Docker Containers +# ============================================ +echo "" +echo -e "${YELLOW}[6/7] Checking Docker containers...${NC}" + +if command -v docker &> /dev/null; then + echo "Containers with auto-restart:" + docker ps -a --filter "restart=always" --filter "restart=unless-stopped" --format "{{.Names}}: {{.Status}}" 2>/dev/null || echo " (none)" + + echo "" + echo "All running containers:" + docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}" 2>/dev/null || echo " Docker not available" +else + echo " Docker not installed" +fi + +# ============================================ +# 7. SSH Keys +# ============================================ +echo "" +echo -e "${YELLOW}[7/7] Checking SSH keys...${NC}" + +echo "Authorized keys for root:" +if [ -f /root/.ssh/authorized_keys ]; then + wc -l /root/.ssh/authorized_keys + echo "Keys:" + cat /root/.ssh/authorized_keys | cut -d' ' -f3 | head -5 +else + echo " (no authorized_keys file)" +fi + +# ============================================ +# Summary +# ============================================ +echo "" +echo -e "${BLUE}============================================${NC}" +if [ $FINDINGS -gt 0 ]; then + echo -e "${RED} ⚠️ FINDINGS: $FINDINGS potential issues${NC}" + echo -e "${RED} Review the output above carefully!${NC}" +else + echo -e "${GREEN} ✓ No obvious persistence mechanisms found${NC}" +fi +echo -e "${BLUE}============================================${NC}" +echo "" +echo "For detailed investigation, see:" +echo " security/forensics-checklist.md" diff --git a/security/runtime-detector.sh b/security/runtime-detector.sh new file mode 100755 index 00000000..239a748b --- /dev/null +++ b/security/runtime-detector.sh @@ -0,0 +1,217 @@ +#!/bin/bash +# ============================================ +# Runtime Detector — DAARION Security +# Version: 1.0.0 +# Purpose: Detect and respond to suspicious runtime activity +# Usage: ./runtime-detector.sh [--kill] [--alert] +# ============================================ + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# Configuration +KILL_MODE=false +ALERT_MODE=false +ALERT_ENDPOINT="${ALERT_ENDPOINT:-}" +CPU_THRESHOLD=80 +LOG_FILE="/var/log/daarion-security.log" + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + --kill) + KILL_MODE=true + shift + ;; + --alert) + ALERT_MODE=true + shift + ;; + *) + shift + ;; + esac +done + +# ============================================ +# Logging function +# ============================================ +log() { + local level=$1 + local message=$2 + local timestamp=$(date '+%Y-%m-%d %H:%M:%S') + echo "[$timestamp] [$level] $message" >> "$LOG_FILE" 2>/dev/null || true + + case $level in + "CRITICAL") + echo -e "${RED}[$level] $message${NC}" + ;; + "WARNING") + echo -e "${YELLOW}[$level] $message${NC}" + ;; + "INFO") + echo -e "${GREEN}[$level] $message${NC}" + ;; + *) + echo "[$level] $message" + ;; + esac +} + +# ============================================ +# Alert function +# ============================================ +send_alert() { + local message=$1 + local hostname=$(hostname) + + if [ "$ALERT_MODE" = true ] && [ -n "$ALERT_ENDPOINT" ]; then + curl -s -X POST "$ALERT_ENDPOINT" \ + -H "Content-Type: application/json" \ + -d "{\"host\":\"$hostname\",\"message\":\"$message\",\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" \ + 2>/dev/null || true + fi +} + +# ============================================ +# Check for mining processes +# ============================================ +check_mining_processes() { + log "INFO" "Checking for mining processes..." + + # Known mining process patterns + local patterns="xmrig|catcal|softirq|vrarhpb|G4NQXBp|minergate|cpuminer|cgminer|bfgminer|ethminer|cryptonight" + + local suspicious=$(ps aux | grep -iE "$patterns" | grep -v grep | grep -v "$0") + + if [ -n "$suspicious" ]; then + log "CRITICAL" "Suspicious mining process detected!" + echo "$suspicious" + + send_alert "Mining process detected on $(hostname): $(echo "$suspicious" | head -1)" + + if [ "$KILL_MODE" = true ]; then + log "WARNING" "Kill mode enabled - terminating processes..." + echo "$suspicious" | awk '{print $2}' | xargs -r kill -9 2>/dev/null || true + log "INFO" "Processes terminated" + else + log "INFO" "Run with --kill to terminate processes" + fi + + return 1 + fi + + log "INFO" "No mining processes found" + return 0 +} + +# ============================================ +# Check high CPU processes +# ============================================ +check_high_cpu() { + log "INFO" "Checking for high CPU usage..." + + local high_cpu=$(ps -eo pid,user,cmd,%cpu --sort=-%cpu | awk -v threshold="$CPU_THRESHOLD" 'NR>1 && $NF > threshold {print}') + + if [ -n "$high_cpu" ]; then + log "WARNING" "Processes with CPU > ${CPU_THRESHOLD}%:" + echo "$high_cpu" + + # Check if it's a known good process + local suspicious=$(echo "$high_cpu" | grep -vE "(node|python|docker|nginx|postgres|redis)" | head -5) + + if [ -n "$suspicious" ]; then + log "CRITICAL" "Unknown high-CPU process detected!" + send_alert "High CPU process on $(hostname): $(echo "$suspicious" | head -1)" + return 1 + fi + fi + + return 0 +} + +# ============================================ +# Check outbound connections +# ============================================ +check_network() { + log "INFO" "Checking network connections..." + + # Known mining pool ports + local mining_ports="3333|5555|7777|14433|45700|45560|14444|9999" + + local suspicious_conn=$(ss -antp 2>/dev/null | grep ESTAB | grep -E ":($mining_ports)") + + if [ -n "$suspicious_conn" ]; then + log "CRITICAL" "Connection to potential mining pool detected!" + echo "$suspicious_conn" + + send_alert "Mining pool connection on $(hostname): $(echo "$suspicious_conn" | head -1)" + + return 1 + fi + + log "INFO" "No suspicious connections found" + return 0 +} + +# ============================================ +# Check Docker containers +# ============================================ +check_docker() { + if ! command -v docker &> /dev/null; then + return 0 + fi + + log "INFO" "Checking Docker containers..." + + # Check container CPU usage + local container_stats=$(docker stats --no-stream --format "{{.Name}}: {{.CPUPerc}}" 2>/dev/null) + + echo "$container_stats" | while read line; do + local cpu=$(echo "$line" | grep -oE '[0-9]+\.[0-9]+' | head -1) + if [ -n "$cpu" ]; then + local cpu_int=${cpu%.*} + if [ "$cpu_int" -gt "$CPU_THRESHOLD" ]; then + log "WARNING" "Container with high CPU: $line" + fi + fi + done + + return 0 +} + +# ============================================ +# Main +# ============================================ +echo -e "${BLUE}============================================${NC}" +echo -e "${BLUE} DAARION Runtime Detector${NC}" +echo -e "${BLUE}============================================${NC}" +echo "" + +ISSUES=0 + +check_mining_processes || ISSUES=$((ISSUES + 1)) +echo "" +check_high_cpu || ISSUES=$((ISSUES + 1)) +echo "" +check_network || ISSUES=$((ISSUES + 1)) +echo "" +check_docker || ISSUES=$((ISSUES + 1)) + +echo "" +echo -e "${BLUE}============================================${NC}" +if [ $ISSUES -gt 0 ]; then + echo -e "${RED} ⚠️ ISSUES DETECTED: $ISSUES${NC}" + echo -e "${RED} Immediate investigation required!${NC}" + exit 1 +else + echo -e "${GREEN} ✓ No issues detected${NC}" + exit 0 +fi +echo -e "${BLUE}============================================${NC}"