360 lines
10 KiB
Markdown
360 lines
10 KiB
Markdown
# Issue #365: Additional Security Enhancements - Implementation Specification
|
|
|
|
**Status**: Planning Complete
|
|
**Created**: 2025-12-21
|
|
**Issue**: https://github.com/Wikid82/Charon/issues/365
|
|
**Branch**: `feature/issue-365-additional-security`
|
|
**PRs**: #436 (targets `development`), #437 (targets `main`)
|
|
|
|
---
|
|
|
|
## Executive Summary
|
|
|
|
This specification details the implementation plan for Issue #365, which addresses six security enhancement areas. After thorough codebase analysis, this document provides file-by-file implementation details, phase breakdown, and complexity estimates.
|
|
|
|
### Scope Summary
|
|
|
|
| Requirement | Status | Complexity | Phase |
|
|
|-------------|--------|------------|-------|
|
|
| Supply Chain - SBOM Generation | ❌ TODO | Medium | 2 |
|
|
| DNS Hijacking - Documentation | ❌ TODO | Low | 1 |
|
|
| TLS Downgrade - Documentation | ✅ Partial | Low | 1 |
|
|
| Privilege Escalation - Container Hardening | ⚠️ Partial | Medium | 2 |
|
|
| Session Hijacking - Cookie/CSP Audit | ✅ Implemented | Low | 1 |
|
|
| Timing Attacks - Constant-Time Comparison | ❌ TODO | Medium | 2 |
|
|
| SIRP Documentation | ❌ TODO | Low | 1 |
|
|
| Security Update Notifications Doc | ❌ TODO | Low | 1 |
|
|
|
|
---
|
|
|
|
## Codebase Research Findings
|
|
|
|
### 1. Cookie/Session Implementation
|
|
|
|
**Location**: [backend/internal/api/handlers/auth_handler.go](backend/internal/api/handlers/auth_handler.go)
|
|
|
|
**Current Implementation** (lines 52-73):
|
|
```go
|
|
func setSecureCookie(c *gin.Context, name, value string, maxAge int) {
|
|
scheme := requestScheme(c)
|
|
secure := isProduction() && scheme == "https"
|
|
sameSite := http.SameSiteStrictMode
|
|
if scheme != "https" {
|
|
sameSite = http.SameSiteLaxMode
|
|
}
|
|
c.SetSameSite(sameSite)
|
|
c.SetCookie(name, value, maxAge, "/", "", secure, true) // HttpOnly: true ✅
|
|
}
|
|
```
|
|
|
|
**Assessment**: ✅ **SECURE** - All cookie security attributes properly configured:
|
|
- `HttpOnly: true` - Prevents XSS access
|
|
- `Secure: true` (production + HTTPS)
|
|
- `SameSite: Strict` (HTTPS) / `Lax` (HTTP dev)
|
|
|
|
### 2. Security Headers Implementation
|
|
|
|
**Location**: [backend/internal/api/middleware/security.go](backend/internal/api/middleware/security.go)
|
|
|
|
**Current Headers Set**:
|
|
- ✅ Content-Security-Policy (CSP)
|
|
- ✅ Strict-Transport-Security (HSTS) with preload
|
|
- ✅ X-Frame-Options: DENY
|
|
- ✅ X-Content-Type-Options: nosniff
|
|
- ✅ X-XSS-Protection: 1; mode=block
|
|
- ✅ Referrer-Policy: strict-origin-when-cross-origin
|
|
- ✅ Permissions-Policy (restricts camera, mic, etc.)
|
|
- ✅ Cross-Origin-Opener-Policy: same-origin
|
|
- ✅ Cross-Origin-Resource-Policy: same-origin
|
|
|
|
**Assessment**: ✅ **COMPREHENSIVE** - All major security headers present.
|
|
|
|
### 3. Token Comparison Methods
|
|
|
|
**Locations Analyzed**:
|
|
|
|
| File | Function | Method | Status |
|
|
|------|----------|--------|--------|
|
|
| [models/user.go#L62](backend/internal/models/user.go#L62) | `CheckPassword` | `bcrypt.CompareHashAndPassword` | ✅ Constant-time |
|
|
| [services/security_service.go#L151](backend/internal/services/security_service.go#L151) | `VerifyBreakGlassToken` | `bcrypt.CompareHashAndPassword` | ✅ Constant-time |
|
|
| [services/auth_service.go#L128](backend/internal/services/auth_service.go#L128) | `ValidateToken` | JWT library | ✅ Handled by library |
|
|
|
|
**Potential Issue Found**: Invite token validation uses database lookup which could leak timing:
|
|
- Location: `backend/internal/api/handlers/user_handler.go` (AcceptInvite)
|
|
- Risk: Low (requires network timing analysis)
|
|
- Recommendation: Add constant-time wrapper for token comparison after DB lookup
|
|
|
|
### 4. Current Security Documentation
|
|
|
|
**Location**: [docs/security.md](docs/security.md)
|
|
|
|
**Current Coverage**:
|
|
- ✅ Cerberus security suite (CrowdSec, WAF, ACL)
|
|
- ✅ Access Lists configuration
|
|
- ✅ Certificate management
|
|
- ✅ Break-glass token
|
|
- ✅ Zero-day protection explanation
|
|
- ❌ TLS version enforcement (not documented)
|
|
- ❌ DNS security (not documented)
|
|
- ❌ SIRP (not documented)
|
|
- ❌ Container hardening (not documented)
|
|
|
|
### 5. CI/CD Pipeline Analysis
|
|
|
|
**Location**: [.github/workflows/docker-build.yml](.github/workflows/docker-build.yml)
|
|
|
|
**Current State**:
|
|
- ✅ Trivy vulnerability scanning (SARIF + table output)
|
|
- ✅ Weekly security rebuilds (separate workflow)
|
|
- ✅ Caddy security patches verification
|
|
- ❌ SBOM generation (not implemented)
|
|
- ❌ SBOM attestation (not implemented)
|
|
|
|
**Best Integration Point**: After `build-and-push` step, before Trivy scan (around line 130)
|
|
|
|
### 6. Dockerfile Security Analysis
|
|
|
|
**Location**: [Dockerfile](Dockerfile)
|
|
|
|
**Current Security Features**:
|
|
- ✅ Non-root user (`charon:charon`, UID 1000)
|
|
- ✅ Healthcheck configured
|
|
- ✅ Minimal base image (Alpine)
|
|
- ✅ Multi-stage build (reduces attack surface)
|
|
- ⚠️ Root filesystem writable (can be improved)
|
|
- ⚠️ All capabilities retained (can drop unnecessary ones)
|
|
|
|
---
|
|
|
|
## Phase 1: Documentation Enhancements (Estimated: 1-2 hours)
|
|
|
|
### 1.1 TLS Downgrade Attack Documentation
|
|
|
|
**File**: `docs/security.md`
|
|
|
|
**Add Section**:
|
|
```markdown
|
|
## TLS Security
|
|
|
|
### TLS Version Enforcement
|
|
|
|
Charon (via Caddy) enforces a minimum TLS version of 1.2 by default. This prevents TLS downgrade attacks that attempt to force connections to use vulnerable TLS 1.0 or 1.1.
|
|
|
|
**What's Protected:**
|
|
- ✅ TLS 1.0/1.1 downgrade attacks
|
|
- ✅ BEAST, POODLE, and similar protocol-level attacks
|
|
- ✅ Weak cipher suite negotiation
|
|
|
|
**HSTS (HTTP Strict Transport Security):**
|
|
Charon sets HSTS headers with:
|
|
- `max-age=31536000` (1 year)
|
|
- `includeSubDomains`
|
|
- `preload` (for browser preload lists)
|
|
```
|
|
|
|
**Complexity**: Low | **Dependencies**: None
|
|
|
|
---
|
|
|
|
### 1.2 DNS Hijacking Documentation
|
|
|
|
**File**: `docs/security.md`
|
|
|
|
**Add Section**:
|
|
```markdown
|
|
## DNS Security
|
|
|
|
### Protecting Against DNS Hijacking
|
|
|
|
Configure your upstream resolver to use DNS-over-HTTPS (DoH) or DNS-over-TLS (DoT):
|
|
|
|
**Docker Host Configuration:**
|
|
```bash
|
|
# /etc/systemd/resolved.conf
|
|
[Resolve]
|
|
DNS=1.1.1.1#cloudflare-dns.com
|
|
DNSOverTLS=yes
|
|
```
|
|
|
|
**Additional Protections:**
|
|
1. **DNSSEC**: Ensure your domain registrar supports DNSSEC
|
|
2. **CAA Records**: Restrict which CAs can issue certs for your domain
|
|
```
|
|
|
|
**Complexity**: Low | **Dependencies**: None
|
|
|
|
---
|
|
|
|
### 1.3 Security Incident Response Plan
|
|
|
|
**New File**: `docs/security-incident-response.md`
|
|
|
|
**Content**: Incident classification, detection, containment, recovery procedures
|
|
|
|
**Complexity**: Low | **Dependencies**: None
|
|
|
|
---
|
|
|
|
### 1.4 Security Update Notifications
|
|
|
|
**Files**: `docs/getting-started.md`, `docs/security.md`
|
|
|
|
**Add**: GitHub Watch instructions, Watchtower/Diun configuration examples
|
|
|
|
**Complexity**: Low | **Dependencies**: None
|
|
|
|
---
|
|
|
|
## Phase 2: Code Changes (Estimated: 4-6 hours)
|
|
|
|
### 2.1 SBOM Generation
|
|
|
|
**File**: `.github/workflows/docker-build.yml`
|
|
|
|
**Changes** (add after build-and-push step):
|
|
```yaml
|
|
- name: Generate SBOM (CycloneDX)
|
|
uses: anchore/sbom-action@v0
|
|
with:
|
|
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build-and-push.outputs.digest }}
|
|
format: cyclonedx-json
|
|
output-file: sbom.cyclonedx.json
|
|
|
|
- name: Attest SBOM to Image
|
|
if: github.event_name != 'pull_request'
|
|
uses: actions/attest-sbom@v2
|
|
with:
|
|
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
subject-digest: ${{ steps.build-and-push.outputs.digest }}
|
|
sbom-path: sbom.cyclonedx.json
|
|
```
|
|
|
|
**Additional Files**:
|
|
- `.gitignore`: Add `sbom*.json`
|
|
- `.dockerignore`: Add `sbom*.json`
|
|
|
|
**Complexity**: Medium | **Dependencies**: None
|
|
|
|
---
|
|
|
|
### 2.2 Container Hardening Documentation
|
|
|
|
**File**: `docs/security.md`
|
|
|
|
**Add Example**:
|
|
```yaml
|
|
services:
|
|
charon:
|
|
image: ghcr.io/wikid82/charon:latest
|
|
read_only: true
|
|
tmpfs:
|
|
- /tmp:size=100M
|
|
cap_drop:
|
|
- ALL
|
|
cap_add:
|
|
- NET_BIND_SERVICE
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
```
|
|
|
|
**Complexity**: Medium | **Dependencies**: Testing with read-only FS
|
|
|
|
---
|
|
|
|
### 2.3 Constant-Time Token Comparison
|
|
|
|
**New File**: `backend/internal/util/crypto.go`
|
|
```go
|
|
package util
|
|
|
|
import "crypto/subtle"
|
|
|
|
// ConstantTimeCompare compares two strings in constant time.
|
|
func ConstantTimeCompare(a, b string) bool {
|
|
return subtle.ConstantTimeCompare([]byte(a), []byte(b)) == 1
|
|
}
|
|
```
|
|
|
|
**New Test File**: `backend/internal/util/crypto_test.go`
|
|
|
|
**Modify**: `backend/internal/api/handlers/user_handler.go` - Use constant-time comparison in AcceptInvite
|
|
|
|
**Complexity**: Medium | **Dependencies**: None
|
|
|
|
---
|
|
|
|
## Phase 3: Testing & Validation (Estimated: 2-3 hours)
|
|
|
|
### Required Tests
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `backend/internal/util/crypto_test.go` | Constant-time comparison tests + benchmarks |
|
|
| Integration test additions | Security header verification |
|
|
|
|
### Coverage Requirements
|
|
|
|
- All new code must achieve 85% coverage
|
|
- Run: `scripts/go-test-coverage.sh`
|
|
|
|
---
|
|
|
|
## File Change Summary
|
|
|
|
### Files to Create
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `backend/internal/util/crypto.go` | Constant-time comparison utilities |
|
|
| `backend/internal/util/crypto_test.go` | Tests for crypto utilities |
|
|
| `docs/security-incident-response.md` | SIRP documentation |
|
|
|
|
### Files to Modify
|
|
|
|
| File | Changes |
|
|
|------|---------|
|
|
| `docs/security.md` | TLS, DNS, container hardening sections |
|
|
| `docs/getting-started.md` | Security update notification section |
|
|
| `.github/workflows/docker-build.yml` | SBOM generation steps |
|
|
| `.gitignore` | Add `sbom*.json` |
|
|
| `.dockerignore` | Add `sbom*.json` |
|
|
| `backend/internal/api/handlers/user_handler.go` | Constant-time token comparison |
|
|
|
|
### Files Verified Secure (No Changes)
|
|
|
|
| File | Reason |
|
|
|------|--------|
|
|
| `backend/internal/api/handlers/auth_handler.go` | Cookie security correct |
|
|
| `backend/internal/api/middleware/security.go` | Headers comprehensive |
|
|
| `backend/internal/models/user.go` | bcrypt is constant-time |
|
|
| `backend/internal/services/security_service.go` | bcrypt is constant-time |
|
|
| `Dockerfile` | Non-root user configured |
|
|
|
|
---
|
|
|
|
## Out of Scope (Future Issues)
|
|
|
|
Per Issue #365:
|
|
- ❌ Certificate Transparency Log Monitoring
|
|
- ❌ MFA via Authentik
|
|
- ❌ SSO for Charon admin
|
|
- ❌ Audit logging for GDPR/SOC2
|
|
|
|
---
|
|
|
|
## Acceptance Criteria
|
|
|
|
- [ ] Documentation sections added to `docs/security.md`
|
|
- [ ] SIRP document created
|
|
- [ ] SBOM generation in CI (CycloneDX format)
|
|
- [ ] Constant-time utility with tests
|
|
- [ ] Container hardening documented
|
|
- [ ] 85%+ test coverage
|
|
- [ ] Pre-commit hooks pass
|
|
|
|
---
|
|
|
|
**Analysis Date**: 2025-12-21
|
|
**Analyzed By**: GitHub Copilot
|
|
**Status**: Ready for Implementation
|