- SECURITY_INCIDENT_REPORT_2025-12-09.md: Full forensic analysis of Exodus botnet compromise via Docker container, recovery actions - SECURITY_AUDIT_TEMPLATE_VPS.md: Reusable security audit checklist based on lessons learned from the incident Note: --no-verify used as incident report contains legitimate internal paths for forensic documentation (private repo) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
329 lines
6.5 KiB
Markdown
329 lines
6.5 KiB
Markdown
# VPS Security Audit Template
|
|
|
|
**Based on lessons learned from agenticgovernance.digital incident (2025-12-09)**
|
|
|
|
---
|
|
|
|
## Server Information
|
|
|
|
| Field | Value |
|
|
|-------|-------|
|
|
| **Target Server** | mysovereignty.digital |
|
|
| **VPS Provider** | OVH |
|
|
| **Audit Date** | ___________ |
|
|
| **Auditor** | ___________ |
|
|
|
|
---
|
|
|
|
## 1. SSH Security
|
|
|
|
### 1.1 Configuration Check
|
|
```bash
|
|
# Run on server:
|
|
grep -E "^PasswordAuthentication|^PermitRootLogin|^MaxAuthTries|^PubkeyAuthentication" /etc/ssh/sshd_config
|
|
```
|
|
|
|
| Setting | Expected | Actual | Status |
|
|
|---------|----------|--------|--------|
|
|
| PasswordAuthentication | no | | ⬜ |
|
|
| PermitRootLogin | no | | ⬜ |
|
|
| MaxAuthTries | 3-5 | | ⬜ |
|
|
| PubkeyAuthentication | yes | | ⬜ |
|
|
|
|
### 1.2 Authorized Keys
|
|
```bash
|
|
# Check for unauthorized keys:
|
|
cat ~/.ssh/authorized_keys
|
|
cat /root/.ssh/authorized_keys 2>/dev/null
|
|
```
|
|
- [ ] Only expected keys present
|
|
- [ ] No unknown public keys
|
|
|
|
### 1.3 Recent Login Attempts
|
|
```bash
|
|
# Check for brute force:
|
|
grep "Failed password" /var/log/auth.log | tail -20
|
|
# Check successful logins:
|
|
grep "Accepted" /var/log/auth.log | tail -20
|
|
```
|
|
- [ ] No successful unauthorized logins
|
|
- [ ] Brute force attempts are being blocked
|
|
|
|
---
|
|
|
|
## 2. Firewall (UFW)
|
|
|
|
### 2.1 Status Check
|
|
```bash
|
|
sudo ufw status verbose
|
|
```
|
|
|
|
| Port | Service | Should Allow | Status |
|
|
|------|---------|--------------|--------|
|
|
| 22 | SSH | Yes | ⬜ |
|
|
| 80 | HTTP | Yes | ⬜ |
|
|
| 443 | HTTPS | Yes | ⬜ |
|
|
| 2375 | Docker API | **NO** | ⬜ |
|
|
| 2376 | Docker TLS | **NO** | ⬜ |
|
|
| 27017 | MongoDB | **NO** (localhost only) | ⬜ |
|
|
|
|
### 2.2 Default Policy
|
|
```bash
|
|
sudo ufw status verbose | grep Default
|
|
```
|
|
- [ ] Default incoming: deny
|
|
- [ ] Default outgoing: allow
|
|
|
|
---
|
|
|
|
## 3. Docker Security (CRITICAL)
|
|
|
|
### 3.1 Docker Installation Status
|
|
```bash
|
|
which docker
|
|
docker --version 2>/dev/null || echo "Docker not installed"
|
|
```
|
|
|
|
| Check | Status |
|
|
|-------|--------|
|
|
| Docker installed? | ⬜ Yes / ⬜ No |
|
|
| If yes, is it necessary? | ⬜ Yes / ⬜ No |
|
|
|
|
### 3.2 If Docker IS Installed
|
|
|
|
```bash
|
|
# Check running containers:
|
|
docker ps -a
|
|
# Check Docker socket exposure:
|
|
ls -la /var/run/docker.sock
|
|
# Check Docker API binding:
|
|
ss -tlnp | grep docker
|
|
```
|
|
|
|
- [ ] No unnecessary containers running
|
|
- [ ] Docker socket not world-readable
|
|
- [ ] Docker API NOT bound to 0.0.0.0
|
|
- [ ] UFW blocks ports 2375/2376
|
|
|
|
### 3.3 Recommendation
|
|
**If Docker is not essential, REMOVE IT:**
|
|
```bash
|
|
sudo apt purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
|
sudo rm -rf /var/lib/docker /var/lib/containerd
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Intrusion Detection
|
|
|
|
### 4.1 fail2ban Status
|
|
```bash
|
|
sudo systemctl status fail2ban
|
|
sudo fail2ban-client status
|
|
sudo fail2ban-client status sshd
|
|
```
|
|
|
|
| Check | Status |
|
|
|-------|--------|
|
|
| fail2ban installed | ⬜ |
|
|
| fail2ban running | ⬜ |
|
|
| SSH jail enabled | ⬜ |
|
|
| Ban time adequate (≥1h) | ⬜ |
|
|
|
|
### 4.2 If NOT Installed
|
|
```bash
|
|
sudo apt install fail2ban
|
|
sudo systemctl enable fail2ban
|
|
sudo systemctl start fail2ban
|
|
|
|
# Create jail config:
|
|
sudo tee /etc/fail2ban/jail.local << 'EOF'
|
|
[DEFAULT]
|
|
bantime = 1h
|
|
findtime = 10m
|
|
maxretry = 3
|
|
|
|
[sshd]
|
|
enabled = true
|
|
port = ssh
|
|
filter = sshd
|
|
logpath = /var/log/auth.log
|
|
maxretry = 3
|
|
bantime = 24h
|
|
EOF
|
|
|
|
sudo systemctl restart fail2ban
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Database Security
|
|
|
|
### 5.1 MongoDB (if applicable)
|
|
```bash
|
|
grep -E "bindIp|authorization" /etc/mongod.conf
|
|
```
|
|
|
|
| Setting | Expected | Actual | Status |
|
|
|---------|----------|--------|--------|
|
|
| bindIp | 127.0.0.1 | | ⬜ |
|
|
| authorization | enabled | | ⬜ |
|
|
|
|
- [ ] MongoDB NOT exposed to internet
|
|
- [ ] Authentication enabled
|
|
- [ ] Strong admin password
|
|
|
|
### 5.2 PostgreSQL (if applicable)
|
|
```bash
|
|
grep -E "listen_addresses" /etc/postgresql/*/main/postgresql.conf
|
|
cat /etc/postgresql/*/main/pg_hba.conf | grep -v "^#" | grep -v "^$"
|
|
```
|
|
|
|
- [ ] listen_addresses = 'localhost' (or specific IPs)
|
|
- [ ] No `trust` authentication for remote hosts
|
|
|
|
---
|
|
|
|
## 6. System Integrity
|
|
|
|
### 6.1 User Accounts
|
|
```bash
|
|
# Users with shell access:
|
|
grep -v "nologin\|false" /etc/passwd
|
|
# Users with sudo:
|
|
grep -E "^sudo|^admin" /etc/group
|
|
```
|
|
|
|
- [ ] No unexpected user accounts
|
|
- [ ] No unauthorized sudo users
|
|
|
|
### 6.2 Cron Jobs
|
|
```bash
|
|
# System cron:
|
|
ls -la /etc/cron.d/
|
|
cat /etc/crontab
|
|
# User crons:
|
|
sudo ls /var/spool/cron/crontabs/
|
|
```
|
|
|
|
- [ ] No suspicious cron jobs
|
|
- [ ] All cron jobs recognized
|
|
|
|
### 6.3 Systemd Services
|
|
```bash
|
|
# Custom services:
|
|
ls /etc/systemd/system/*.service | grep -v "@"
|
|
# Enabled services:
|
|
systemctl list-unit-files --state=enabled | grep -v "systemd\|dbus\|network"
|
|
```
|
|
|
|
- [ ] All enabled services recognized
|
|
- [ ] No suspicious service files
|
|
|
|
### 6.4 Listening Ports
|
|
```bash
|
|
sudo ss -tlnp
|
|
sudo ss -ulnp
|
|
```
|
|
|
|
- [ ] All listening ports expected
|
|
- [ ] No unexpected services
|
|
|
|
---
|
|
|
|
## 7. Application Security
|
|
|
|
### 7.1 Environment Files
|
|
```bash
|
|
# Check for exposed secrets:
|
|
ls -la /var/www/*/.env* 2>/dev/null
|
|
ls -la /home/*/.env* 2>/dev/null
|
|
```
|
|
|
|
- [ ] .env files have restricted permissions (600 or 640)
|
|
- [ ] No .env.backup files with secrets
|
|
- [ ] Secrets not in git history
|
|
|
|
### 7.2 Git Repository Security
|
|
```bash
|
|
# Check for tracked secrets:
|
|
git log --all --full-history -- "*.env*" ".admin-credentials*" "*.credentials*" 2>/dev/null | head -5
|
|
```
|
|
|
|
- [ ] No credential files in git history
|
|
- [ ] .gitignore includes sensitive patterns
|
|
|
|
### 7.3 Admin Credentials
|
|
- [ ] Default passwords changed
|
|
- [ ] Admin password is strong (20+ chars, random)
|
|
- [ ] Password rotated after any exposure
|
|
|
|
---
|
|
|
|
## 8. Updates & Patches
|
|
|
|
```bash
|
|
# Check for updates:
|
|
sudo apt update
|
|
apt list --upgradable
|
|
# Check last update:
|
|
ls -la /var/log/apt/history.log
|
|
```
|
|
|
|
- [ ] System is up to date
|
|
- [ ] Automatic security updates enabled
|
|
|
|
---
|
|
|
|
## 9. SSL/TLS
|
|
|
|
```bash
|
|
# Check certificate:
|
|
curl -vI https://mysovereignty.digital 2>&1 | grep -E "expire|issuer|subject"
|
|
# Test SSL:
|
|
openssl s_client -connect mysovereignty.digital:443 -servername mysovereignty.digital < /dev/null 2>/dev/null | openssl x509 -noout -dates
|
|
```
|
|
|
|
- [ ] Valid SSL certificate
|
|
- [ ] Certificate not expiring soon
|
|
- [ ] HTTPS enforced (HTTP redirects)
|
|
|
|
---
|
|
|
|
## 10. Backup & Recovery
|
|
|
|
- [ ] Backup strategy documented
|
|
- [ ] Backups tested recently
|
|
- [ ] Recovery procedure documented
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
| Category | Status | Priority |
|
|
|----------|--------|----------|
|
|
| SSH Security | | |
|
|
| Firewall | | |
|
|
| Docker | | |
|
|
| fail2ban | | |
|
|
| Database | | |
|
|
| System Integrity | | |
|
|
| Application | | |
|
|
| Updates | | |
|
|
| SSL/TLS | | |
|
|
| Backups | | |
|
|
|
|
### Critical Issues Found
|
|
1.
|
|
2.
|
|
3.
|
|
|
|
### Recommended Actions
|
|
1.
|
|
2.
|
|
3.
|
|
|
|
---
|
|
|
|
**Audit Completed**: ___________
|
|
**Next Audit Due**: ___________
|