Updated content
This commit is contained in:
commit
f0564e87ee
6 changed files with 121 additions and 2 deletions
|
|
@ -1,11 +1,15 @@
|
||||||
FROM php:8.4.14-apache
|
FROM php:8.4.14-apache
|
||||||
|
|
||||||
# Enable Apache modules and custom config as root during build
|
# Enable Apache modules and custom config as root during build
|
||||||
RUN a2enmod rewrite
|
RUN a2enmod rewrite headers
|
||||||
|
|
||||||
COPY apache.conf /etc/apache2/conf-available/custom.conf
|
COPY apache.conf /etc/apache2/conf-available/custom.conf
|
||||||
RUN a2enconf custom
|
RUN a2enconf custom
|
||||||
|
|
||||||
|
# Override default security.conf settings
|
||||||
|
RUN sed -i 's/^ServerTokens OS/ServerTokens Prod/' /etc/apache2/conf-available/security.conf \
|
||||||
|
&& sed -i 's/^ServerSignature On/ServerSignature Off/' /etc/apache2/conf-available/security.conf
|
||||||
|
|
||||||
# Log to /proc/self/fd for container output
|
# Log to /proc/self/fd for container output
|
||||||
RUN sed -i 's|ErrorLog.*|ErrorLog /proc/self/fd/2|' /etc/apache2/sites-available/000-default.conf \
|
RUN sed -i 's|ErrorLog.*|ErrorLog /proc/self/fd/2|' /etc/apache2/sites-available/000-default.conf \
|
||||||
&& sed -i 's|CustomLog.*|CustomLog /proc/self/fd/1 combined|' /etc/apache2/sites-available/000-default.conf \
|
&& sed -i 's|CustomLog.*|CustomLog /proc/self/fd/1 combined|' /etc/apache2/sites-available/000-default.conf \
|
||||||
|
|
|
||||||
10
apache.conf
10
apache.conf
|
|
@ -1,5 +1,13 @@
|
||||||
|
# Minimize server version disclosure
|
||||||
|
ServerTokens Prod
|
||||||
|
|
||||||
|
# Disable PHP version header and error display
|
||||||
|
php_flag expose_php Off
|
||||||
|
php_flag display_errors Off
|
||||||
|
php_flag log_errors On
|
||||||
|
|
||||||
<Directory /var/www/>
|
<Directory /var/www/>
|
||||||
Options Indexes FollowSymLinks
|
Options FollowSymLinks
|
||||||
AllowOverride All
|
AllowOverride All
|
||||||
Require all granted
|
Require all granted
|
||||||
</Directory>
|
</Directory>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,31 @@
|
||||||
DirectorySlash Off
|
DirectorySlash Off
|
||||||
|
|
||||||
|
# Block direct access to content source files
|
||||||
|
<FilesMatch "\.(ini|md|html|php)$">
|
||||||
|
# Allow only the entry point
|
||||||
|
<If "%{REQUEST_URI} != '/index.php'">
|
||||||
|
Require all denied
|
||||||
|
</If>
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
<IfModule mod_headers.c>
|
||||||
|
Header set X-Content-Type-Options "nosniff"
|
||||||
|
Header set X-Frame-Options "DENY"
|
||||||
|
Header set Referrer-Policy "strict-origin-when-cross-origin"
|
||||||
|
Header set Permissions-Policy "camera=(), microphone=(), geolocation=()"
|
||||||
|
Header unset X-Powered-By
|
||||||
|
Header always unset X-Powered-By
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# Restrict HTTP methods to GET, POST, HEAD
|
||||||
<IfModule mod_rewrite.c>
|
<IfModule mod_rewrite.c>
|
||||||
RewriteEngine On
|
RewriteEngine On
|
||||||
RewriteBase /
|
RewriteBase /
|
||||||
|
|
||||||
|
RewriteCond %{REQUEST_METHOD} !^(GET|POST|HEAD)$ [NC]
|
||||||
|
RewriteRule .* - [F,L]
|
||||||
|
|
||||||
# Route /app requests to index.php
|
# Route /app requests to index.php
|
||||||
RewriteCond %{REQUEST_URI} ^/app/
|
RewriteCond %{REQUEST_URI} ^/app/
|
||||||
RewriteRule ^(.*)$ /index.php [L,QSA]
|
RewriteRule ^(.*)$ /index.php [L,QSA]
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,31 @@
|
||||||
DirectorySlash Off
|
DirectorySlash Off
|
||||||
|
|
||||||
|
# Block direct access to content source files
|
||||||
|
<FilesMatch "\.(ini|md|html|php)$">
|
||||||
|
# Allow only the entry point
|
||||||
|
<If "%{REQUEST_URI} != '/index.php'">
|
||||||
|
Require all denied
|
||||||
|
</If>
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
<IfModule mod_headers.c>
|
||||||
|
Header set X-Content-Type-Options "nosniff"
|
||||||
|
Header set X-Frame-Options "DENY"
|
||||||
|
Header set Referrer-Policy "strict-origin-when-cross-origin"
|
||||||
|
Header set Permissions-Policy "camera=(), microphone=(), geolocation=()"
|
||||||
|
Header unset X-Powered-By
|
||||||
|
Header always unset X-Powered-By
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# Restrict HTTP methods to GET, POST, HEAD
|
||||||
<IfModule mod_rewrite.c>
|
<IfModule mod_rewrite.c>
|
||||||
RewriteEngine On
|
RewriteEngine On
|
||||||
RewriteBase /
|
RewriteBase /
|
||||||
|
|
||||||
|
RewriteCond %{REQUEST_METHOD} !^(GET|POST|HEAD)$ [NC]
|
||||||
|
RewriteRule .* - [F,L]
|
||||||
|
|
||||||
# Route /app requests to index.php
|
# Route /app requests to index.php
|
||||||
RewriteCond %{REQUEST_URI} ^/app/
|
RewriteCond %{REQUEST_URI} ^/app/
|
||||||
RewriteRule ^(.*)$ /index.php [L,QSA]
|
RewriteRule ^(.*)$ /index.php [L,QSA]
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,12 @@ if (str_starts_with($_SERVER['REQUEST_URI'], '/app/')) {
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Harden session cookie before any session starts
|
||||||
|
ini_set('session.cookie_httponly', '1');
|
||||||
|
ini_set('session.cookie_samesite', 'Lax');
|
||||||
|
if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
|
||||||
|
ini_set('session.cookie_secure', '1');
|
||||||
|
}
|
||||||
|
|
||||||
// All other requests go to router
|
// All other requests go to router
|
||||||
require __DIR__ . '/../app/router.php';
|
require __DIR__ . '/../app/router.php';
|
||||||
|
|
|
||||||
56
docs/security-cpanel.md
Normal file
56
docs/security-cpanel.md
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
# Security Hardening — cPanel Shared Hosting
|
||||||
|
|
||||||
|
The container dev environment (Containerfile + apache.conf) handles most hardening automatically. On cPanel shared hosting, some settings must be configured manually since you don't control the Apache or PHP config directly.
|
||||||
|
|
||||||
|
## What's handled by .htaccess (works everywhere)
|
||||||
|
|
||||||
|
These are applied automatically via `content/.htaccess` (synced from `.htaccess.base`):
|
||||||
|
|
||||||
|
- Block direct access to `.ini`, `.md`, `.html`, `.php` content files
|
||||||
|
- Security headers: `X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`, `Permissions-Policy`
|
||||||
|
- Strip `X-Powered-By` header
|
||||||
|
- Restrict HTTP methods to GET/POST/HEAD
|
||||||
|
- Rewrite rules routing all requests through `index.php`
|
||||||
|
|
||||||
|
The `custom/.htaccess` and `custom/data/.htaccess` files also deploy automatically and block direct access to config files and data.
|
||||||
|
|
||||||
|
## What needs manual cPanel configuration
|
||||||
|
|
||||||
|
### 1. Disable display_errors
|
||||||
|
|
||||||
|
Go to **MultiPHP INI Editor** (Home > Software > MultiPHP INI Editor):
|
||||||
|
|
||||||
|
- Select the domain
|
||||||
|
- Set `display_errors` = **Off**
|
||||||
|
- Set `log_errors` = **On**
|
||||||
|
- Set `expose_php` = **Off**
|
||||||
|
|
||||||
|
This prevents PHP errors from leaking server paths and internal details to visitors.
|
||||||
|
|
||||||
|
### 2. PHP version
|
||||||
|
|
||||||
|
Use **MultiPHP Manager** to ensure PHP 8.4+ is selected for the domain.
|
||||||
|
|
||||||
|
### 3. Session cookie hardening
|
||||||
|
|
||||||
|
Handled in `content/index.php` via `ini_set()` calls — no cPanel action needed. The entry point sets `HttpOnly`, `SameSite=Lax`, and `Secure` (when on HTTPS) before any session starts.
|
||||||
|
|
||||||
|
### 4. Server version header
|
||||||
|
|
||||||
|
On shared hosting you typically cannot change `ServerTokens` (it's a server-level directive). The `X-Powered-By` header is stripped by `.htaccess`, but the `Server: Apache/2.4.x` header may still show the full version. This is a low-risk issue on shared hosting since the Apache version is the hosting provider's responsibility.
|
||||||
|
|
||||||
|
### 5. SSL/TLS
|
||||||
|
|
||||||
|
Use **SSL/TLS** (Home > Security > SSL/TLS) or **AutoSSL** to ensure HTTPS is active. The session cookie `Secure` flag only activates over HTTPS.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] `.htaccess` deployed (copy `.htaccess.base` if needed, preserve cPanel-generated blocks)
|
||||||
|
- [ ] `display_errors` = Off in MultiPHP INI Editor
|
||||||
|
- [ ] `expose_php` = Off in MultiPHP INI Editor
|
||||||
|
- [ ] `log_errors` = On in MultiPHP INI Editor
|
||||||
|
- [ ] SSL certificate active
|
||||||
|
- [ ] `custom/smtp-config.php` exists but is NOT in git (check `.gitignore`)
|
||||||
|
- [ ] `custom/listmonk-config.php` exists but is NOT in git (check `.gitignore`)
|
||||||
|
- [ ] `custom/data/` directory writable by web server (`chmod 755` or `775`)
|
||||||
|
- [ ] `custom/data/.htaccess` present with `Require all denied`
|
||||||
Loading…
Add table
Add a link
Reference in a new issue