fix(security): deny config/VCS dotfiles over HTTP on standalone cac and cac-litespeed
Measured on .148: standalone cac served /.env with its contents, and cac-litespeed served /.env even at mode 0640 (OLS runs as the customer uid there). shared-httpd and shared-ols already deny these via WHP's drop-ins; the standalone tiers never got them. - cac: new configs/whp-security.conf in /etc/httpd/conf.d — the same named FilesMatch + DirectoryMatch list as WHP's shared-httpd-security.conf, re-rooted to /home. - cac-litespeed: the same `context exp:` regex as WHP's shared-ols vhconf template, added to the vhost template. Named list (.user.ini .env* .git .svn .hg .bzr .ht* .whp .site-builder), not a blanket dotfile deny, so /.well-known/ stays reachable. HTTP only: PHP still reads these files from disk. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
86a88c87db
commit
74648ba34b
3 files changed
+42
No files matched your search
@@ -40,6 +40,7 @@ COPY ./configs/phpinfo.php /var/www/html/
|
||||
COPY ./configs/mariadb.repo /etc/yum.repos.d/
|
||||
COPY ./configs/index.php /var/www/html/
|
||||
COPY ./configs/remote_ip.conf /etc/httpd/conf.d/
|
||||
COPY ./configs/whp-security.conf /etc/httpd/conf.d/
|
||||
|
||||
# Set up cron job in a single layer
|
||||
RUN echo "15 */12 * * * root /scripts/log-rotate.sh" >> /etc/crontab
|
||||
|
||||
@@ -72,6 +72,18 @@ virtualHostConfig {
|
||||
addDefaultCharset off
|
||||
}
|
||||
|
||||
## SECURITY: never serve config / VCS dotfiles over HTTP. Same named list as
|
||||
## WHP's shared-ols vhconf template (first `context exp:` there) and
|
||||
## shared-httpd's 000-whp-security.conf. Measured on .148: this tier served
|
||||
## /.env even at mode 0640, because OLS runs as the customer uid here. An
|
||||
## `exp:` regex context wins over the `context /` prefix context regardless
|
||||
## of order (measured on OLS 1.8.4 for shared-ols), so a customer .htaccess
|
||||
## cannot reopen it. Named, not blanket "^\.": /.well-known/ (ACME,
|
||||
## security.txt, app-site-association) must stay reachable.
|
||||
context exp:^/(.*/)?\.(user\.ini|env|git|svn|hg|bzr|ht|whp|site-builder) {
|
||||
allowBrowse 0
|
||||
}
|
||||
|
||||
rewrite {
|
||||
enable 1
|
||||
autoLoadHtaccess 1
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
## SECURITY: never serve config / VCS dotfiles over HTTP (standalone cac).
|
||||
##
|
||||
## Same named list as WHP's shared-httpd drop-in (web-files/configs/
|
||||
## shared-httpd-security.conf, 000-whp-security.conf on every shared-httpd host),
|
||||
## re-rooted from /mnt/users to /home because here the docroot is
|
||||
## /home/<user>/public_html. Standalone cac never got that drop-in, and measured
|
||||
## on .148 it served /.env with contents.
|
||||
##
|
||||
## <FilesMatch> matches the FILENAME resolved from the filesystem path, not the
|
||||
## request URL, so it cannot be side-stepped by URL-encoding. httpd applies
|
||||
## <Directory> sections (and .htaccess) first and <Files>/<FilesMatch> after
|
||||
## them, so this deny wins over create-vhost.sh's `Require all granted`.
|
||||
##
|
||||
## A NAMED LIST, NOT A BLANKET "^\." DENY: /.well-known/ (ACME, security.txt,
|
||||
## apple-app-site-association, assetlinks.json, payment-domain verification)
|
||||
## must stay reachable. FilesMatch tests the final path component, and for
|
||||
## /.well-known/acme-challenge/<token> that is <token>, not a dotfile.
|
||||
##
|
||||
## HTTP only: PHP still reads .user.ini and .env off the filesystem as before.
|
||||
<Directory "/home">
|
||||
<FilesMatch "^\.(user\.ini|env|git|svn|hg|bzr|ht|whp|site-builder)">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
</Directory>
|
||||
## Directory form: reaches the files INSIDE .git/ etc. (e.g. /.git/config,
|
||||
## whose own name is not a dotfile).
|
||||
<DirectoryMatch "^/home/.*/\.(git|svn|hg|bzr|whp|site-builder)(/|$)">
|
||||
Require all denied
|
||||
</DirectoryMatch>
|
||||
Reference in new issue
Block a user