diff --git a/docs/audit/2026-02-20/SUMMARY.md b/docs/audit/2026-02-20/SUMMARY.md new file mode 100644 index 0000000..b29e763 --- /dev/null +++ b/docs/audit/2026-02-20/SUMMARY.md @@ -0,0 +1,115 @@ +# KNEL-Football Secure OS - Executive Summary + +**Audit Date**: 2026-02-20 +**Auditor**: External Security Auditor +**Classification**: CONFIDENTIAL + +--- + +## Project Overview + +KNEL-Football is a hardened Debian 13 Linux distribution designed as a **secure remote terminal** for accessing tier0 infrastructure via WireGuard VPN. The project implements a two-factor security model requiring both physical possession of the device and access to a privileged workstation. + +--- + +## Audit Scope + +- Security architecture review +- Encryption configuration validation +- Build system and supply chain analysis +- SDLC compliance verification +- Code quality assessment +- Firewall and network security review + +--- + +## Risk Assessment + +### Overall Risk Level: **MEDIUM** + +| Severity | Count | Key Areas | +|----------|-------|-----------| +| Critical | 0 | - | +| High | 2 | Secure Boot keys, Firewall output | +| Medium | 4 | Docker privileged, USB automount, KDF config, Supply chain | +| Low | 3 | Test gaps, Documentation, Input validation | +| Info | 1 | Package management | + +--- + +## Critical Findings Requiring Immediate Attention + +### 1. Secure Boot Key Management (HIGH) +Keys generated at build time without HSM or secure storage. An attacker with build system access could extract private keys and sign malicious bootloaders. + +**Impact**: Complete chain of trust compromise +**Effort**: Medium (requires key management infrastructure) + +### 2. Firewall Output Chain Blocks Essential Services (HIGH) +Default DROP policy on OUTPUT chain prevents DNS resolution, NTP synchronization, and system updates. + +**Impact**: System cannot function properly (DNS, time sync, updates) +**Effort**: Low (add explicit allow rules) + +--- + +## Positive Security Observations + +1. **Strong SDLC Enforcement** - Pre-commit hooks enforce TDD, linting, and coverage +2. **Comprehensive Encryption** - LUKS2 with AES-256-XTS-512, passphrase validation +3. **Defense in Depth** - Multiple layers: FDE, firewall, audit, FIM, hardening +4. **No SSH Server** - Correctly implements client-only SSH per requirements +5. **Clean Code Quality** - All scripts pass shellcheck with zero warnings +6. **Host FDE Enforcement** - Build system refuses to run without host encryption + +--- + +## Recommendations Priority + +### Must Fix Before Release +1. Fix firewall OUTPUT chain to allow DNS/NTP/updates +2. Disable USB automount (conflicts with security model) +3. Verify Argon2id KDF is actually used in LUKS + +### Short-term (30 days) +1. Implement Secure Boot key management with HSM or air-gapped storage +2. Pin Docker package versions for reproducible builds +3. Add functional integration tests for encryption + +### Long-term (90 days) +1. Implement SLSA/SBOM for supply chain security +2. Add USB authorization with usbguard +3. Build environment attestation + +--- + +## Compliance Status + +| Standard | Status | Notes | +|----------|--------|-------| +| NIST SP 800-53 SC-8 | ✅ Pass | WireGuard encryption | +| NIST SP 800-53 SC-12 | ⚠️ Issue | Key management needs work | +| NIST SP 800-53 AC-19 | ⚠️ Issue | USB automount | +| NIST SP 800-111 | ✅ Pass | LUKS2 encryption | +| CIS Benchmark 6.x | ✅ Pass | Comprehensive audit logging | +| FedRAMP SC-7 | ⚠️ Issue | Firewall output policy | + +--- + +## Audit Artifacts + +- `docs/audit/2026-02-20/findings.md` - Detailed findings (10 findings) +- `docs/audit/2026-02-20/SUMMARY.md` - This document + +--- + +## Conclusion + +KNEL-Football demonstrates **mature security architecture** with strong foundations. The project is **suitable for production with remediation** of the two HIGH findings. The SDLC practices are exemplary and should be maintained. + +**Recommendation**: Address firewall and Secure Boot key issues before release. The remaining findings can be addressed post-release with documented timelines. + +--- + +**Signed**: External Security Auditor +**Date**: 2026-02-20 diff --git a/docs/audit/2026-02-20/findings.md b/docs/audit/2026-02-20/findings.md new file mode 100644 index 0000000..efe24f6 --- /dev/null +++ b/docs/audit/2026-02-20/findings.md @@ -0,0 +1,459 @@ +# KNEL-Football Secure OS - Security Audit Report + +**Date**: 2026-02-20 +**Auditor**: External Security Auditor +**Scope**: Comprehensive security and QA review +**Classification**: CONFIDENTIAL + +--- + +## Executive Summary + +**Overall Assessment**: The KNEL-Football Secure OS project demonstrates a **mature security posture** with strong architectural foundations. The project shows evidence of security-first thinking, comprehensive documentation, and automated enforcement mechanisms. However, several areas require attention before production deployment. + +### Risk Summary + +| Severity | Count | Areas | +|----------|-------|-------| +| **Critical** | 0 | - | +| **High** | 2 | Secure Boot key management, Firewall output policy | +| **Medium** | 4 | Docker privileged mode, USB automount, Argon2 KDF config, Supply chain | +| **Low** | 3 | Test coverage gaps, Hadolint warnings, Documentation sync | +| **Informational** | 5 | Various observations | + +### Key Strengths + +1. **Strong SDLC Enforcement**: Pre-commit hooks enforce TDD, linting, and test coverage +2. **Comprehensive Encryption**: LUKS2 with AES-256-XTS-512, proper passphrase validation +3. **Defense in Depth**: Multiple security layers (FDE, firewall, audit, FIM, hardening) +4. **No SSH Server**: Correctly implements client-only SSH per PRD FR-006 +5. **Clean Shellcheck**: All scripts pass shellcheck with zero warnings +6. **Host FDE Enforcement**: Build system refuses to run without host encryption + +### Areas Requiring Attention + +1. **Secure Boot Key Management**: Keys generated at build time without HSM or secure storage +2. **Firewall Output Policy**: Default DROP on output chain may break DNS/updates +3. **USB Automount**: Security risk for a secure workstation +4. **Supply Chain**: No SLSA/SBOM, unpinned Docker packages + +--- + +## Detailed Findings + +### FINDING-001: Secure Boot Key Management (HIGH) + +**Category**: Cryptographic Key Management +**Severity**: HIGH +**Status**: Open + +**Description**: +Secure Boot keys (PK, KEK, db) are generated at ISO build time using OpenSSL with self-signed certificates. The private keys are stored in the build directory and potentially embedded in the ISO. + +**Location**: +- `run.sh:441-484` - `sb_generate_keys()` function +- `run.sh:455-472` - OpenSSL key generation commands + +**Code Examined**: +```bash +openssl req -new -x509 -newkey rsa:4096 -sha256 -days 3650 \ + -nodes -subj "/CN=KNEL-Football PK/" \ + -keyout "${SB_KEY_DIR}/PK.key" \ + -out "${SB_KEY_DIR}/PK.crt" 2>/dev/null +``` + +**Issues**: +1. Keys generated on every build with no persistence or secure storage +2. Private keys could be exposed in build artifacts +3. No Hardware Security Module (HSM) integration +4. 10-year validity without rotation policy +5. No key escrow or recovery mechanism +6. Subject DN uses generic CN without organization identification + +**Risk**: An attacker with build system access could extract private keys and sign malicious bootloaders. + +**Recommendation**: +1. Pre-generate keys offline and store in HSM or air-gapped secure storage +2. Only embed public keys/certificates in the ISO +3. Implement key rotation policy +4. Add key provenance documentation +5. Consider using a commercial PKI for production deployments + +**Compliance Impact**: NIST SP 800-57, FedRAMP SC-12 + +--- + +### FINDING-002: Firewall Output Chain Default DROP (HIGH) + +**Category**: Network Security +**Severity**: HIGH +**Status**: Open + +**Description**: +The nftables firewall configuration sets a default DROP policy on the OUTPUT chain, only allowing loopback, WireGuard traffic, and ICMP ping. + +**Location**: +- `src/firewall-setup.sh:43-47` - Output chain rules +- `config/hooks/live/firewall-setup.sh:29-34` - Live hook output rules + +**Code Examined**: +```bash +chain output { + type filter hook output priority 0; policy drop + oif lo accept comment "Accept loopback" + udp dport "$port" ip daddr "$ip" accept comment "Allow WireGuard traffic" + icmp type echo-request accept comment "Allow ping" +} +``` + +**Issues**: +1. No DNS (UDP/TCP 53) allowed - system cannot resolve hostnames +2. No NTP (UDP 123) allowed - time synchronization will fail +3. No HTTP/HTTPS allowed - system cannot fetch updates or time +4. WireGuard endpoint IP must be known at configuration time +5. No outbound rules for apt repositories + +**Risk**: System may be unable to: +- Synchronize time (breaks Kerberos, certificate validation) +- Resolve DNS names +- Receive security updates +- Access WireGuard endpoint if IP changes + +**Recommendation**: +1. Add explicit DNS rules (TCP/UDP 53 to known DNS servers) +2. Add NTP rules (UDP 123 to time servers) +3. Consider allowing HTTPS to specific update repositories +4. Document the firewall policy and required endpoints +5. Add validation that WireGuard endpoint is reachable + +**Compliance Impact**: NIST SP 800-41, CIS Benchmark 3.x + +--- + +### FINDING-003: Docker Privileged Mode (MEDIUM) + +**Category**: Build Security +**Severity**: MEDIUM +**Status**: Open + +**Description**: +The ISO build process runs Docker with `--privileged` flag. + +**Location**: +- `run.sh:979` - Docker run command + +**Code Examined**: +```bash +docker run --rm --privileged \ + -v "${SCRIPT_DIR}:/workspace:ro" \ + ... +``` + +**Issues**: +1. Privileged containers have full access to host devices +2. Could allow container escape if build process compromised +3. live-build requires privileged mode for loop device access + +**Risk**: If the build environment is compromised, attacker could escape to host. + +**Mitigating Factors**: +1. Build runs in isolated environment (documented requirement) +2. Build artifacts are read-only mounted +3. Pre-commit hooks validate code before build + +**Recommendation**: +1. Document the security implications of privileged mode +2. Consider using rootless Docker or podman +3. Implement build environment attestation +4. Consider using dedicated build infrastructure + +--- + +### FINDING-004: USB Automount Enabled (MEDIUM) + +**Category**: Endpoint Security +**Severity**: MEDIUM +**Status**: Open + +**Description**: +The system automatically mounts USB storage devices when connected. + +**Location**: +- `config/hooks/live/usb-automount.sh` - Entire file + +**Code Examined**: +```bash +cat >/etc/udev/rules.d/99-usb-automount.rules <<'EOF' +ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", RUN+="/usr/local/bin/usb-automount.sh %k" +``` + +**Issues**: +1. Automatic mounting of untrusted media is a security risk +2. BadUSB attacks could compromise the system +3. USB devices could exfiltrate data +4. Conflicts with "secure workstation" threat model + +**Risk**: Physical access attack vector via malicious USB devices. + +**Recommendation**: +1. Disable USB automount by default +2. Implement USB device authorization (usbguard) +3. Consider blocking USB storage entirely for tier0 access +4. If USB required, implement manual mount-only policy + +**Compliance Impact**: CIS Benchmark 1.1.x, NIST SP 800-53 AC-19 + +--- + +### FINDING-005: Argon2id KDF Not Explicitly Configured (MEDIUM) + +**Category**: Encryption +**Severity**: MEDIUM +**Status**: Open + +**Description**: +The PRD specifies Argon2id KDF for LUKS2, but the preseed.cfg does not explicitly configure it. + +**Location**: +- `config/includes.installer/preseed.cfg:111-116` - LUKS configuration +- `docs/PRD.md` - FR-001 requirement + +**Code Examined**: +```bash +d-i partman-crypto/cipher aes-xts-plain64 +d-i partman-crypto/keysize 512 +d-i partman-crypto/use-luks2 boolean true +``` + +**Issues**: +1. No explicit Argon2id configuration in preseed +2. Debian partman-crypto defaults may use PBKDF2 +3. Documentation claims Argon2id but implementation unclear + +**Risk**: If PBKDF2 is used instead of Argon2id, weaker key derivation against brute-force. + +**Recommendation**: +1. Add explicit `d-i partman-crypto/keyscript` or post-install hook to enforce Argon2id +2. Verify actual KDF in use after installation +3. Add test to validate LUKS header uses Argon2id + +**Verification Required**: Install system and run `cryptsetup luksDump` to verify KDF. + +--- + +### FINDING-006: Unpinned Docker Packages (MEDIUM) + +**Category**: Supply Chain +**Severity**: MEDIUM +**Status**: Open + +**Description**: +Dockerfile does not pin package versions, using `apt-get install ` instead of `=`. + +**Location**: +- `Dockerfile:16, 29, 45, 55` - apt-get install commands + +**Hadolint Output**: +``` +-:16 DL3008 warning: Pin versions in apt get install +-:29 DL3008 warning: Pin versions in apt get install +-:45 DL3008 warning: Pin versions in apt get install +-:55 DL3008 warning: Pin versions in apt get install +``` + +**Issues**: +1. Non-reproducible builds - different package versions on different days +2. Cannot verify exact software supply chain +3. Security updates may introduce regressions + +**Recommendation**: +1. Pin all package versions in Dockerfile +2. Generate SBOM (Software Bill of Materials) during build +3. Consider SLSA compliance for supply chain security +4. Document package version freeze policy + +--- + +### FINDING-007: Test Coverage Gaps (LOW) + +**Category**: Quality Assurance +**Severity**: LOW +**Status**: Open + +**Description**: +Test coverage documentation claims 562 tests, but several areas have minimal testing. + +**Location**: +- `tests/unit/encryption-validation_test.bats` - Only 4 tests +- Various unit tests are text-based (grep for strings) not functional + +**Issues**: +1. encryption-validation_test.bats has only 4 tests +2. Many tests verify text presence rather than behavior +3. No integration tests for actual LUKS encryption +4. Firewall tests mock rather than execute nft + +**Examples**: +```bash +# Weak test - only checks for string presence +@test "Validation checks for LUKS2 format" { + grep -q "LUKS\|luks" /workspace/config/hooks/installed/encryption-validation.sh +} +``` + +**Recommendation**: +1. Increase functional test coverage +2. Add integration tests with actual cryptsetup operations +3. Test firewall rules with nft --check +4. Document test coverage gaps + +--- + +### FINDING-008: Documentation-Code Synchronization (LOW) + +**Category**: Documentation +**Severity**: LOW +**Status**: Open + +**Description**: +Some discrepancies between documentation and implementation. + +**Issues**: +1. PRD specifies Argon2id, preseed doesn't configure it explicitly +2. PRD FR-005 says WiFi/Bluetooth "permanently disabled", but modules can be reloaded by root +3. User account inconsistency: preseed creates "football" user, hooks reference "kneluser" + +**Location**: +- `config/includes.installer/preseed.cfg:38` - User "football" +- `config/hooks/installed/encryption-validation.sh:106` - Path "/home/kneluser" + +**Recommendation**: +1. Add documentation validation to CI +2. Create user account consistency test +3. Document the difference between "disabled" and "blacklisted" modules + +--- + +### FINDING-009: QR Code Scanner Command Injection Risk (LOW) + +**Category**: Input Validation +**Severity**: LOW +**Status**: Open + +**Description**: +The QR code import script parses untrusted input from QR codes and processes it with Python. + +**Location**: +- `config/hooks/live/qr-code-import.sh:48-76` - Python QR parsing + +**Issues**: +1. QR data is untrusted input +2. Python script does minimal validation +3. Could potentially inject malicious config values + +**Mitigating Factors**: +1. Script runs as user (pkexec for elevation) +2. WireGuard config has limited attack surface +3. Physical access required to present QR code + +**Recommendation**: +1. Add strict input validation in Python script +2. Sanitize all parsed values before writing config +3. Add length limits on QR data +4. Log all QR imports for audit trail + +--- + +### FINDING-010: Package Management Disabled Aggressively (INFORMATIONAL) + +**Category**: System Administration +**Severity**: INFORMATIONAL +**Status**: Informational + +**Description**: +Package management is disabled by removing execute permissions and making directories immutable. + +**Location**: +- `config/hooks/installed/disable-package-management.sh` + +**Code Examined**: +```bash +chmod -x /usr/bin/apt /usr/bin/apt-get /usr/bin/dpkg +chattr +i /usr/bin/apt /usr/bin/apt-get /usr/bin/dpkg +rm -rf /var/lib/apt/* /var/lib/dpkg/* +``` + +**Observations**: +1. Effective at preventing package installation +2. Makes security updates impossible without recovery +3. Consider document update procedure for security patches + +**Recommendation**: Document the security patching procedure for deployed systems. + +--- + +## Positive Observations + +### OBSERVATION-001: Strong Pre-Commit Enforcement +The pre-commit hook enforces SDLC requirements including linting, testing, and coverage checks. This is excellent security practice. + +### OBSERVATION-002: No Hardcoded Credentials +No hardcoded passwords, API keys, or secrets found in the codebase. Password prompts are forced during installation. + +### OBSERVATION-003: Comprehensive Audit Rules +The auditd configuration is thorough and covers security-critical files and operations. + +### OBSERVATION-004: SSH Client Only +Correctly implements client-only SSH (no sshd installed) per PRD FR-006. + +### OBSERVATION-005: Host FDE Enforcement +Build system validates host encryption before allowing ISO builds - prevents data leakage via build artifacts. + +--- + +## Compliance Matrix + +| Standard | Requirement | Status | +|----------|-------------|--------| +| NIST SP 800-53 SC-8 | Transmission Confidentiality | ✅ WireGuard | +| NIST SP 800-53 SC-12 | Cryptographic Key Management | ⚠️ See FINDING-001 | +| NIST SP 800-53 AC-19 | Access Control for Mobile Devices | ⚠️ See FINDING-004 | +| NIST SP 800-111 | Storage Encryption | ✅ LUKS2 | +| CIS Benchmark 1.x | Filesystem Configuration | ⚠️ USB automount | +| CIS Benchmark 6.x | Logging and Auditing | ✅ Comprehensive audit | +| FedRAMP SC-7 | Boundary Protection | ⚠️ See FINDING-002 | + +--- + +## Recommendations Summary + +### Immediate (Before Release) +1. Review and fix firewall OUTPUT chain policy (FINDING-002) +2. Decide on USB automount policy (FINDING-004) +3. Verify Argon2id KDF is actually used (FINDING-005) + +### Short-term (30 days) +1. Implement Secure Boot key management plan (FINDING-001) +2. Pin Docker package versions (FINDING-006) +3. Add functional integration tests (FINDING-007) + +### Long-term (90 days) +1. Consider SLSA/SBOM implementation +2. Implement USB authorization (usbguard) +3. Add build environment attestation + +--- + +## Conclusion + +The KNEL-Football Secure OS project demonstrates strong security fundamentals with comprehensive encryption, hardening, and audit capabilities. The SDLC enforcement through pre-commit hooks is exemplary. + +The primary concerns relate to: +1. Secure Boot key management (keys generated at build time) +2. Firewall configuration that may break essential services +3. USB automount conflicting with the security model + +With the recommended fixes, this project would be suitable for tier0 infrastructure access in compliance-focused environments. + +**Signed**: External Security Auditor +**Date**: 2026-02-20 diff --git a/run.sh b/run.sh index 867098d..8b11578 100755 --- a/run.sh +++ b/run.sh @@ -14,16 +14,16 @@ readonly OUTPUT_DIR="${SCRIPT_DIR}/output" readonly BUILD_DIR="${SCRIPT_DIR}/tmp" readonly BUILD_LOG="/tmp/knel-iso-build.log" -# VM Testing Configuration (using libvirt session - no root required) +# VM Testing Configuration (system libvirt for virt-manager visibility, /tmp for no sudo) readonly ISO_PATH="${SCRIPT_DIR}/output/knel-football-secure.iso" readonly VM_NAME="knel-football-test" readonly VM_RAM="2048" readonly VM_CPUS="2" readonly VM_DISK_SIZE="10" -readonly LIBVIRT_URI="qemu:///session" -VM_DISK_PATH="${HOME}/.local/share/libvirt/images/${VM_NAME}.qcow2" +readonly LIBVIRT_URI="qemu:///system" +VM_DISK_PATH="/tmp/${VM_NAME}.qcow2" readonly VM_DISK_PATH -VM_ISO_PATH="${HOME}/.local/share/libvirt/images/$(basename "$ISO_PATH")" +VM_ISO_PATH="/tmp/${VM_NAME}.iso" readonly VM_ISO_PATH # Colors for output diff --git a/tests/unit/run_comprehensive_test.bats b/tests/unit/run_comprehensive_test.bats index 11f0283..10e88f6 100644 --- a/tests/unit/run_comprehensive_test.bats +++ b/tests/unit/run_comprehensive_test.bats @@ -253,8 +253,8 @@ grep -q 'VM_DISK_SIZE=' /workspace/run.sh } -@test "run.sh uses session libvirt URI (no root required)" { - grep -q 'qemu:///session' /workspace/run.sh +@test "run.sh uses system libvirt URI" { + grep -q 'qemu:///system' /workspace/run.sh } # =============================================================================