📚 docs(security): Add comprehensive Security chapter

## 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 <agent@cursor.sh>
This commit is contained in:
Apple
2026-01-09 02:04:11 -08:00
parent d77a4769c6
commit cba2ff47f3
7 changed files with 1712 additions and 0 deletions

96
security/README.md Normal file
View File

@@ -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 <container>
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

View File

@@ -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_name>
# Container logs
docker logs --tail 100 <container_name>
# Docker images
docker images
# Docker networks
docker network ls
docker network inspect <network>
# Container inspect (look for mounts, env vars)
docker inspect <container_name>
```
**🔴 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 <container>
# 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 <pid>
# Remove persistence
crontab -r
systemctl disable <service>
# Remove Docker artifacts
docker stop <container>
docker rm <container>
docker rmi <image> # 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
```

310
security/hardening/cloud.md Normal file
View File

@@ -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 <process_name>
# Видалити контейнер ТА образ
docker stop <container>
docker rm <container>
docker rmi <image> # КРИТИЧНО!
```
4. **Відповісти Hetzner:**
- URL: https://statement-abuse.hetzner.com/statements/?token=<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

View File

@@ -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

View File

@@ -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

170
security/persistence-scan.sh Executable file
View File

@@ -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"

217
security/runtime-detector.sh Executable file
View File

@@ -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}"