mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-07 11:39:18 +02:00
- lib/AdminAuth.php: new class with requireLogin(), login(), logout(), isAuthenticated(); starts session with hardened cookie params (HttpOnly, SameSite=Strict, Secure, Path=/admin) — also resolves item #8 (session cookie hardening) - requireLogin() auto-authenticates from nginx Basic Auth credentials ($_SERVER['PHP_AUTH_PW']) so the user only sees one browser prompt; falls back to /admin/login.php if the proxy is absent/misconfigured - config/admin_credentials.php: gitignored credential store; define ADMIN_PASSWORD_HASH with a bcrypt hash to enable PHP auth - config/admin_credentials.example.php: template for the above - config/bootstrap.php: auto-loads admin_credentials.php if present - .gitignore: exclude config/admin_credentials.php - public/admin/login.php: fallback login form (shown only when nginx Basic Auth is bypassed / proxy absent) - public/admin/logout.php: session destruction + redirect to login - All 7 admin PHP files: replace session_start() with AdminAuth::requireLogin() (defence-in-depth behind nginx Basic Auth) - public/admin/inc/head.php: Déconnexion button when ADMIN_PASSWORD_HASH is defined - nginx/PHP_AUTH_LAYER.md: documents dual-auth architecture, UX flow, and setup instructions - docs/TODO.SECURITY.md: items #2 and #8 moved to Resolved; priority order updated (all CRITICAL done)
102 lines
4.9 KiB
Markdown
102 lines
4.9 KiB
Markdown
# 🔒 Security TODO — posterg-website
|
||
|
||
> Based on `docs/SECURITY_ANALYSIS.md` (2026-02-08).
|
||
> Tracks resolution status for all identified vulnerabilities.
|
||
|
||
---
|
||
|
||
## ✅ Resolved
|
||
|
||
### Infrastructure / Deployment
|
||
|
||
| # | Issue | Severity | Resolution |
|
||
|---|-------|----------|------------|
|
||
| 1 | No HTTPS — admin credentials exposed in transit | 🔴 CRITICAL | **TLS is terminated upstream by the reverse proxy** (outside nginx). nginx.conf does not need to handle TLS directly. |
|
||
| 3 | Uploaded files stored inside the webroot | 🟠 HIGH | Storage moved to `STORAGE_ROOT` (`/var/www/posterg/storage/`), defined in `config/bootstrap.php`. `formulaire.php` updated. |
|
||
| 4 | File path mismatch — media files broken and insecure | 🟠 HIGH | DB paths are now storage-relative (`theses/YEAR/ID/file`, `covers/file`). New controller `public/media.php` serves files safely. `memoire.php` and `search.php` updated to use `/media.php?path=…`. Cover recording in `formulaire.php` fixed (was never inserted into DB). |
|
||
| 5 | Rate limiter bypassed by IP spoofing (`X-Forwarded-For`) | 🟠 HIGH | `lib/RateLimit.php` `getClientIdentifier()` now uses `REMOTE_ADDR` only. |
|
||
| 6 | `.htaccess` security rules silently ignored by nginx | 🟠 HIGH | All rules ported to `nginx/posterg.conf` (CSP to `/admin/` block, `.log` denial, `autoindex off`). See `nginx/HTACCESS_TO_NGINX.md`. |
|
||
| 13 | Deprecated `X-XSS-Protection` header | 🔵 LOW | **Removed** from `nginx/posterg.conf`; see `nginx/SECURITY_HEADERS.md` for rationale. |
|
||
|
||
---
|
||
|
||
### Frontend / Assets
|
||
|
||
| # | Issue | Severity | Resolution |
|
||
|---|-------|----------|------------|
|
||
| 10 | CDN stylesheet (water.css) without Subresource Integrity | 🟡 MEDIUM | **CDN will not be used in production.** The stylesheet will be self-hosted, eliminating the supply-chain risk entirely. |
|
||
|
||
---
|
||
|
||
### Frontend
|
||
|
||
| # | Issue | Severity | Resolution |
|
||
|---|-------|----------|------------|
|
||
| 14 | Missing `rel="noreferrer"` on external `target="_blank"` links | 🔵 LOW | `rel="noopener noreferrer"` applied in `public/admin/thanks.php`. |
|
||
|
||
---
|
||
|
||
### Code Quality / Defence in Depth
|
||
|
||
| # | Issue | Severity | Resolution |
|
||
|---|-------|----------|------------|
|
||
| 15 | Unescaped integer outputs (inconsistency) | 🔵 LOW | Explicit `(int)` casts added in `public/index.php` and `public/search.php`. |
|
||
| 16 | Redundant `DATABASE_PATH` constant never used | 🔵 LOW | `define('DATABASE_PATH', …)` removed from `config/bootstrap.php`. |
|
||
|
||
---
|
||
|
||
### Admin Panel — Authentication & Sessions
|
||
|
||
| # | Issue | Severity | Resolution |
|
||
|---|-------|----------|------------|
|
||
| 2 | No PHP-level authentication in admin panel | 🔴 CRITICAL | `lib/AdminAuth.php` implements a session guard with `password_verify` + `session_regenerate_id`. All admin PHP files now call `AdminAuth::requireLogin()` instead of bare `session_start()`. Credentials stored in gitignored `config/admin_credentials.php` (define `ADMIN_PASSWORD_HASH`). No-op when constant is absent (dev / cli-server). Also resolves item #8 (session cookie hardening via `session_set_cookie_params` before `session_start`). See `nginx/PHP_AUTH_LAYER.md`. |
|
||
| 8 | Session cookies not hardened (`Secure`, `HttpOnly`, `SameSite` missing) | 🟡 MEDIUM | **Resolved as part of item #2.** `AdminAuth::startSession()` sets `HttpOnly=true`, `SameSite=Strict`, `Secure=true` (off on cli-server), `Path=/admin`, `Lifetime=0` before every `session_start()`. |
|
||
|
||
---
|
||
|
||
## 🔧 In Progress
|
||
|
||
### Database / Input Handling
|
||
|
||
| # | Issue | Severity | Status |
|
||
|---|-------|----------|--------|
|
||
| 7 | LIKE wildcard injection in admin search (`public/admin/index.php`) | 🟡 MEDIUM | **Needs standardisation of DB input sanitisation across the whole codebase.** The public `Database::searchTheses()` already escapes `%` and `_` correctly; the same pattern must be applied to admin search and any other raw LIKE queries. |
|
||
|
||
---
|
||
|
||
## ❌ Not Yet Implemented
|
||
|
||
### Infrastructure / Deployment
|
||
|
||
| # | Issue | Severity | Files |
|
||
|---|-------|----------|-------|
|
||
| 11 | Missing Content-Security-Policy on public pages | 🟡 MEDIUM | `nginx/posterg.conf` → add `Content-Security-Policy` header to main server block (admin already has CSP via item #6) |
|
||
|
||
---
|
||
|
||
### Admin Panel — Error Logging
|
||
|
||
| # | Issue | Severity | Files |
|
||
|---|-------|----------|-------|
|
||
| 9 | `error.log` written to a web-accessible path | 🟡 MEDIUM | `public/admin/actions/formulaire.php` → use absolute path outside webroot |
|
||
|
||
---
|
||
|
||
### File Import
|
||
|
||
| # | Issue | Severity | Files |
|
||
|---|-------|----------|-------|
|
||
| 12 | CSV import missing server-side MIME validation | 🟡 MEDIUM | `public/admin/import.php` → add `finfo` MIME check |
|
||
|
||
---
|
||
|
||
## Priority Order for Remaining Work
|
||
|
||
1. 🔴 **CRITICAL** — ✅ All done (items 1–2)
|
||
2. 🟡 **MEDIUM** — Items 7, 9, 11, 12 (sanitisation standardisation, error log, CSP, CSV MIME) — item 8 resolved with item 2
|
||
3. 🔵 **LOW** — ✅ All done (items 13–16)
|
||
|
||
---
|
||
|
||
*Last updated: 2026-02-08*
|