feat: enhance Content Security Policy and add additional security headers

This commit is contained in:
Théophile Diot 2024-12-20 15:31:14 +01:00
parent bf676b32dd
commit 328caa229e
No known key found for this signature in database
GPG key ID: FA995104A0BA376A
4 changed files with 53 additions and 14 deletions

View file

@ -70,15 +70,15 @@ server {
render = template.render
end
local nonce_style = rand(16)
local nonce_script = rand(16)
local nonce_style = rand(32)
local nonce_script = rand(32)
-- Override CSP header
ngx.header["Content-Security-Policy"] = "default-src 'none'; script-src http: https: 'unsafe-inline' 'strict-dynamic' 'nonce-"
ngx.header["Content-Security-Policy"] = "default-src 'none'; script-src 'strict-dynamic' 'nonce-"
.. nonce_script
.. "'; style-src 'nonce-"
.. nonce_style
.. "'; frame-ancestors 'none'; base-uri 'none'; img-src 'self' data:; font-src 'self' data:; require-trusted-types-for 'script'; block-all-mixed-content; upgrade-insecure-requests;"
.. "'; frame-ancestors 'none'; base-uri 'none'; img-src data:; font-src data:; require-trusted-types-for 'script';"
-- Remove server header
ngx.header["Server"] = nil
@ -86,6 +86,7 @@ server {
-- Override HSTS header
if ngx.var.scheme == "https" then
ngx.header["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains; preload"
ngx.header["Content-Security-Policy"] = ngx.header["Content-Security-Policy"] .. " upgrade-insecure-requests;"
end
-- Override X-Content-Type-Options header
@ -94,6 +95,15 @@ server {
-- Override Referrer-Policy header
ngx.header["Referrer-Policy"] = "no-referrer"
-- Override Permissions-Policy header
ngx.header["Permissions-Policy"] = "accelerometer=(), ambient-light-sensor=(), attribution-reporting=(), autoplay=(), battery=(), bluetooth=(), browsing-topics=(), camera=(), compute-pressure=(), display-capture=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), identity-credentials-get=(), idle-detection=(), local-fonts=(), magnetometer=(), microphone=(), midi=(), otp-credentials=(), payment=(), picture-in-picture=(), publickey-credentials-create=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), speaker-selection=(), storage-access=(), usb=(), web-share=(), window-management=(), xr-spatial-tracking=(), interest-cohort=()"
-- Override Content-Type header
ngx.header["Content-Type"] = "text/html; charset=utf-8"
-- Override Cache-Control header
ngx.header["Cache-Control"] = "no-cache, no-store, must-revalidate"
-- Render template
render("index.html", {
nonce_style = nonce_style,

View file

@ -90,8 +90,16 @@ function antibot:header()
for directive, value in pairs(csp_directives) do
csp_content = csp_content .. directive .. " " .. value .. "; "
end
csp_content = csp_content .. "block-all-mixed-content; upgrade-insecure-requests;"
ngx.header["Content-Security-Policy"] = csp_content
local hdr = ngx.header
hdr["Content-Security-Policy"] = csp_content
local ssl = (self.ctx.bw and self.ctx.bw.scheme == "https") or ngx.var.scheme == "https"
if ssl then
hdr["Content-Security-Policy"] = hdr["Content-Security-Policy"] .. " upgrade-insecure-requests;"
end
return self:ret(true, "successfully overridden CSP header")
end

View file

@ -86,17 +86,17 @@ function errors:log()
end
function errors:render_template(code)
local nonce_script = rand(16)
local nonce_style = rand(16)
local nonce_script = rand(32)
local nonce_style = rand(32)
-- Override CSP header
--luacheck: ignore 631
ngx.header["Content-Security-Policy"] = "default-src 'none'; script-src http: https: 'unsafe-inline' 'strict-dynamic' 'nonce-"
ngx.header["Content-Security-Policy"] = "default-src 'none'; script-src 'strict-dynamic' 'nonce-"
.. nonce_script
.. "'; style-src 'nonce-"
.. nonce_style
--luacheck: ignore 631
.. "'; frame-ancestors 'none'; base-uri 'none'; img-src 'self' data:; font-src 'self' data:; require-trusted-types-for 'script'; block-all-mixed-content; upgrade-insecure-requests;"
.. "'; frame-ancestors 'none'; base-uri 'none'; img-src data:; font-src data:; require-trusted-types-for 'script';"
-- Remove server header
ngx.header["Server"] = nil
@ -112,6 +112,7 @@ function errors:render_template(code)
if ssl then
ngx.header["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains; preload"
ngx.header["Content-Security-Policy"] = ngx.header["Content-Security-Policy"] .. " upgrade-insecure-requests;"
end
-- Override X-Content-Type-Options header
@ -120,6 +121,16 @@ function errors:render_template(code)
-- Override Referrer-Policy header
ngx.header["Referrer-Policy"] = "no-referrer"
-- Override Permissions-Policy header
ngx.header["Permissions-Policy"] =
"accelerometer=(), ambient-light-sensor=(), attribution-reporting=(), autoplay=(), battery=(), bluetooth=(), browsing-topics=(), camera=(), compute-pressure=(), display-capture=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), identity-credentials-get=(), idle-detection=(), local-fonts=(), magnetometer=(), microphone=(), midi=(), otp-credentials=(), payment=(), picture-in-picture=(), publickey-credentials-create=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), speaker-selection=(), storage-access=(), usb=(), web-share=(), window-management=(), xr-spatial-tracking=(), interest-cohort=()"
-- Override Content-Type header
ngx.header["Content-Type"] = "text/html; charset=utf-8"
-- Override Cache-Control header
ngx.header["Cache-Control"] = "no-cache, no-store, must-revalidate"
-- Render template
render("error.html", {
title = code .. " - " .. self.default_errors[code].title,

View file

@ -17,12 +17,12 @@ location / {
render = template.render
end
local nonce_style = rand(16)
local nonce_style = rand(32)
-- Override CSP header
ngx.header["Content-Security-Policy"] = "default-src 'none'; frame-ancestors 'none'; form-action 'self'; img-src 'self' data:; style-src 'self' 'nonce-"
.. nonce_style
.. "'; font-src 'self' data:; base-uri 'self'; require-trusted-types-for 'script'; block-all-mixed-content; upgrade-insecure-requests;"
ngx.header["Content-Security-Policy"] = "default-src 'none'; style-src 'nonce-"
.. nonce_style
.. "'; frame-ancestors 'none'; base-uri 'none'; img-src data:; font-src data:; require-trusted-types-for 'script';"
-- Remove server header
ngx.header["Server"] = nil
@ -30,6 +30,7 @@ location / {
-- Override HSTS header
if ngx.var.scheme == "https" then
ngx.header["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains; preload"
ngx.header["Content-Security-Policy"] = ngx.header["Content-Security-Policy"] .. " upgrade-insecure-requests;"
end
-- Override X-Content-Type-Options header
@ -38,6 +39,15 @@ location / {
-- Override Referrer-Policy header
ngx.header["Referrer-Policy"] = "no-referrer"
-- Override Permissions-Policy header
ngx.header["Permissions-Policy"] = "accelerometer=(), ambient-light-sensor=(), attribution-reporting=(), autoplay=(), battery=(), bluetooth=(), browsing-topics=(), camera=(), compute-pressure=(), display-capture=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), identity-credentials-get=(), idle-detection=(), local-fonts=(), magnetometer=(), microphone=(), midi=(), otp-credentials=(), payment=(), picture-in-picture=(), publickey-credentials-create=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), speaker-selection=(), storage-access=(), usb=(), web-share=(), window-management=(), xr-spatial-tracking=(), interest-cohort=()"
-- Override Content-Type header
ngx.header["Content-Type"] = "text/html; charset=utf-8"
-- Override Cache-Control header
ngx.header["Cache-Control"] = "no-cache, no-store, must-revalidate"
-- Render template
render("default.html", {
nonce_style = nonce_style,