Security headers for lighttpd
TL;DR To configure your lighttpd webserver to use security headers that will harden your website against
common hacking attacks, add the section below to your config file (typically /etc/lighttpd/lighttpd.conf
),
restart the webserver, and you're good to go.
server.modules += ("mod_setenv")
$HTTP["scheme"] == "https" {
setenv.add-response-header = (
"Referrer-Policy" => "same-origin",
"Strict-Transport-Security" => "max-age=31536000",
"Content-Security-Policy" => "default-src 'self'",
"X-Frame-Options" => "DENY",
"X-Content-Type-Options" => "nosniff",
"Permissions-Policy" => "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()",
"X-Xss-Protection" => "1; mode=block",
"Server" => "my webserver",
)
}
troubleshooting the setup
Some problems you may run into:
- The headers don't show up. Did you restart the lighttpd service with
sudo service lighttpd restart
?
- The headers still don't show up. Are you using https? The config snippet above only affects https traffic:
add an http section with the relevant headers.
- Still no headers. Do you have more than one place in your config where
setenv.add-response-header
is applied? This won't work, as contrary to the name, it replaces instead of adds the headers.
so you have to add all headers you want in one go.
- Headers show up fine, but website is broken. You may have made the config too strict. Try loosening the
rules up a bit. Likely suspects: the CSP and HSTS headers.
- Weird things still happen. Check the browser console, syslog, and lighttpd log files for clues.
why do I want these headers?
The headers listed above help prevent common hack attempts by allowing less and revealing less. Most headers add
an extra layer of defense, making it harder to exploit mistakes in the website running on your webserver.
For example, when an attacker manages to inject javascript or other malicious content in your website, these
measures will help limit the resulting damage.
To see in what shape you website is, you can enter the url on the
securityheaders.com website and will get a rating together with some
hints how to improve.
I'll dive into the different headers in more detail below.
Referrer-Policy
The Referrer-Policy
header controls how much information the browser will send in the referer
header
for requests made from your site.
Note that the actual request header is incorrectly spelled "referer", while this header and its values use the correct
spelling of the word.
Good options are no-referrer
(omits the header) or same-origin
(only include for requests
to the same site). Restricting the referer headers prevents accidentally leaking any sensitive data in the
originating url.
Strict-Transport-Security
The Strict-Transport-Security
or HSTS header tells your browser to always use https when connecting to your
website. This prevents certain hacks where the attacker tries to trick visitors into using http to connect to the
website, making the traffic susceptible to snooping. The max-age
parameter is the time the browser
should remember this, in second. For a year, use 31536000.
Content-Security-Policy
The Content-Security-Policy
or CSP header tells the browser which sources are okay to load content from.
This can stop maliciously injected content from being fetched by the browser. Can be specified per resource type.
X-Frame-Options
Whether this webpage can be put in a frame. Turning this off helps prevent
clickjacking for your site.
X-Content-Type-Options
This modifies the browsers behavior to "guesstimate" the type of content it is being served. This can be abused
in some hacking scenarios, so better turn it off by setting it to "nosniff", where no assumptions are made and
the only the Content-type
header is respected.
Permissions-Policy
This header limits the type of "special" permissions your website will try to use.
For example, if you know your website should never ask for "geolocation" or "camera", you can turn it off.
This way any maliciously injected code won't succeed in gaining such privileges. Only problem is that there's
no "deny all" option, so you have to list every possible option, making it kind of verbose. Also, you have to
revisit from time to time, as new permission types will keep being added.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
X-Xss-Protection
This header is sort of dubious, as it is not part of the http standard. Some (older) browsers do some cross site
scripting mitigation when the header is set, but no guarantees. MDN even
recommends not using it,
unless you expect to be serving older browsers, in which case you should set it to 1; mode=block"
.
Server
The server header may reveal detailed information on the exact type of webserver you are using, e.g.
Apache/2.4.1 (Unix)
. Lighttpd also does this by default.
This is not so great, as it makes it easier for attackers to abuse known
problems in the specific webserver you are running, so it's best to either disable the header, or set it to
something generic, like my webserver
related blogs:
-
Sending mail from a contact form
How I set up my contact form to send emails in a way that does not reveal my email address to the world.