Benutzer-Werkzeuge

Webseiten-Werkzeuge


lighttpd

Lighttpd

Sicherheit

HTTP Strict Transport Security (HSTS)

To enable HTTP Strict Transport Security in lighttpd use the following config:

server.modules += ( "mod_setenv" )
$HTTP["scheme"] == "https" {
        setenv.add-response-header  = ( "Strict-Transport-Security" => "max-age=31536000")
}

The max-age value is in seconds. Use 31536000 for 12 months or 63072000 for 24 months.

Adding includeSubdomains means that subdomains of the main domain should also be accessed using SSL.

Content Security Policy (CSP)

Dieses Beispiel führt ein Upgrade der HTTP-Verbindungen auf HTTPS durch (HSTS und CSP: /etc/lighttpd/lighttpd.conf):

server.modules += ( "mod_setenv" )
$HTTP["scheme"] == "https" {
        setenv.add-response-header  = ( "Strict-Transport-Security" => "max-age=31536000",
                                        "Content-Security-Policy" => "default-src https: data: 'unsafe-inline' 'unsafe-eval' always; upgrade-insecure-requests" )
}

nur LTS 1.2

SSL-Cipher auflisten:

> openssl ciphers -V
> openssl ciphers | tr -s ':' '\n'
> openssl ciphers -V 'EECDH+aRSA+AES256:!SSLv3'
> openssl ciphers -V 'EECDH+aRSA+AES256:ECDHE-RSA-AES128-GCM-SHA256:!SSLv3'
> openssl ciphers -V 'EECDH+aRSA+AES256:ECDHE-RSA-AES128-GCM-SHA256'
> openssl ciphers -V 'TLSv1+HIGH:!LOW:!3DES:!MD5:!RC4:!DSS:!PSK:!EXP:!SRP:!aNULL:!eNULL:!SSLv2:@STRENGTH'
> vi /etc/lighttpd/conf-enabled/10-ssl.conf
...
##
## Documentation: /usr/share/doc/lighttpd-doc/ssl.txt
##
#### SSL engine
$SERVER["socket"] == "0.0.0.0:443" {
        ssl.engine                          = "enable"
        ssl.pemfile                         = "/etc/lighttpd/ssl/domain.de.pem"
        ssl.ca-file                         = "/etc/lighttpd/ssl/intermediate.domain.de.crt"
        ssl.use-sslv2                       = "disable"
        ssl.use-sslv3                       = "disable"
        ssl.honor-cipher-order              = "enable"
        ssl.use-compression                 = "disable"
        ssl.cipher-list                     = "EECDH+aRSA+AES256:ECDHE-RSA-AES128-GCM-SHA256:!SSLv3"
        ssl.disable-client-renegotiation    = "enable"

        $HTTP["useragent"] =~ ".*MSIE (9|10)\..*" {
                server.max-keep-alive-requests = 0
        }
}
...

Datenübertragung

nur GET und POST

viele HTML-Aufruf-Methoden können gefährlich sein, deshalb lassen wir mit diesem Teil nur "GET", "POST" und "HEAD" zu:

> vi /etc/lighttpd/lighttpd.conf
...
$HTTP["request-method"] !~ "^(GET|POST|HEAD)$" {
        url.access-deny = ("")
}
...

Das kann mit diesem SED-Kommando ganz leicht eingestellt werden:

> sed -i 's/\$HTTP\["request-method"\] .*/$HTTP["request-method"] !~ "^(GET|POST|HEAD)$" {/' /etc/lighttpd/lighttpd.conf

Logging

Debug-Level

http://redmine.lighttpd.net/projects/1/wiki/DebugVariables

um Fehler zu finden ist es oft gut, ins Log zu sehen, damit im Log auch genug zu sehen ist, muss debug.log-request-header eingeschaltet werden:

> vi /etc/lighttpd/lighttpd.conf
...
debug.log-request-header   = "enable"

server.errorlog-use-syslog = "enable"
#server.errorlog            = "/var/log/lighttpd/error.log"

accesslog.format           = "premiumsim.de %V %h %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
accesslog.use-syslog       = "enable"
#accesslog.filename         = "/var/log/lighttpd/access.log"
...

MySQL-Auth mit LighttpD

Leider gibt es für LighttpD kein Modul um die Passwortabfrage auf eine DB zu realisieren, wie man es vom Apache kennt. Um eine derartige Funktionalität in LighttpD umzusetzten, muss man ein entsprechendes LUA-Skript einbinden.

Die Dateien, die Passwörter enthalten, dürfen nicht für die Welt lesbar sein!

> chown 33:33 /etc/lighttpd/sha512crypt.php /etc/lighttpd/mysql_auth.lua
> chmod 0640 /etc/lighttpd/sha512crypt.php /etc/lighttpd/mysql_auth.lua

hier muß die IP ("192.168.2.99") des Web-Servers eingetragen werden:

/etc/lighttpd/conf-enabled/20-mysql_auth.conf
#
$HTTP["host"] =~ "192.168.2.99" {
                magnet.attract-physical-path-to = ( "/etc/lighttpd/mysql_auth.lua" )
}
/etc/lighttpd/mysql_auth.lua
-- vim: set ts=4 sw=4 sts=4 noai noet:
--[[
 
    MySQL-Auth - IQ
 
lighttpd-mod-magnet
lua-socket
lua-sql-mysql
 
*************************** 1. row ***************************
      id: 1
   login: Fritz
password: a8e13417253337017fb29cbe1a647bba2d7dca95b232f70f782bd64da49855606d122e5715d6a63754d88d1ea3fe561af26260fedd7b2425044c7e565fa1dfa0
]]
 
--[[
https://redmine.lighttpd.net/projects/lighttpd/wiki/AbsoLUAtion#Do-basic-HTTP-Auth-against-a-MySQL-DBTable
 
Known Problems:
 
    This Script is blocking!!! Lighttpd will hang, if there are MySQL connection problems.
    Additionally, a whole new MySQL Connection is created with every request! So you shouldn't use this on High-Traffic Sites.
    Passwords are stored plain in MySQL - well, easy to fix. Look for MySQL's PASSWORD function....
]]
 
-- nur "/geheim.php" soll passwortgeschützt sein
if ( string.format('%s', lighty.env["uri.path"]) == "/geheim.php" ) then
 
-- Force https
if (lighty.env["uri.scheme"] == "http") then
    lighty.header["Location"] = "https://" .. lighty.env["uri.authority"] .. lighty.env["request.uri"]
    return 302
end
 
--[[
    Config Variables
]]
local dbConf = {}
dbConf.database = 'authdb'
dbConf.username = 'dbuser'
dbConf.password = 'geheim'
dbConf.hostname = '192.168.2.10'
dbConf.port = "3306"
--[[
dbConf.users_table = "dealer_logins" 
dbConf.col_user = "login"
dbConf.col_pass = "password"
]]
 
--[[
    Requires
]]
 
-- Debian package: liblua5.1-socket2
 
-- required for Base64 De-/encoding. See: http://w3.impa.br/~diego/software/luasocket/home.html
require("mime")
 
-- Debian package: liblua5.1-sql-mysql-2
 
-- Lua Mysql Driver
luasql = require("luasql.mysql")
 
--[[
    Function to send HTTP-Auth request
]]
 
function doAuth()
    lighty.header["WWW-Authenticate"] = string.format('Basic realm="%s"', lighty.env["uri.authority"])
    return 401
end
 
--[[
    Function to check Auth Creds against MySQL Database
]]
local env = assert(luasql.mysql())
local con = assert(env:connect (
        dbConf.database
        ,dbConf.username
        ,dbConf.password
        ,dbConf.hostname
        ,dbConf.port
))
 
function checkAuthMySQL(user,pass)
        local res = con:execute(string.format([[
                SELECT login, password
                FROM `dealer_logins`
                WHERE `login` = '%s'
                AND `password` = '%s'
                ]], user, pass)
        )
 
        -- Die Tabelle wir in ein Array gespeichert
        local row = res:fetch ({}, "a")
 
        -- print(type(row))
 
 
        -- close everything
        -- res:close()  -- already closed because all the result set was consumed
        con:close()
        -- env:close()
 
 
        if (not row) then
                return false
        else
                lighty.req_env['REMOTE_USER'] = user
                return true
        end
end
 
 
-- MAIN
 
--[[
    Check for Authorization Header
    and force Basic Auth if not set.
]]
 
if (not lighty.request.Authorization) then
    return doAuth()
end
 
--[[
    Header found: check string for "Basic" and base64 encoded username & password
    - upb = User Password Base64 encoded
]]
_, _, upb = string.find(lighty.request.Authorization, "^Basic%s+(.+)$")
up = mime.unb64(upb) -- Base64 Decode
_, _, username, password = string.find(up, "^(.+):(.+)$") -- split by ":" to get username and password supplied
 
 
-- =============================================================================
-- In der DB steht das Passwort nicht im klartext drin, sondern verschlüsselt
-- deshalb muss auch der Passwort-Hash und nicht das Passwort verglichen werden.
--
-- hier wird aus dem Passwort der Passwort-Hash generiert
--
-- /var/www/webauftritt/libs/WebServices/Ovp/Authentication/Encrypt.php
 
local start = ("/usr/bin/php /etc/lighttpd/sha512crypt.php " .. password)
datei = assert (io.popen (start))
pwhash = datei:read ("*l") -- read one line
 
-- =============================================================================
 
if (not checkAuthMySQL(username, pwhash)) then
        return doAuth()
end
 
 
end
 
-- return nothing to proceed normal operation
return

Leider gibt es nur für eine SHA256-Verschlüsselung eine native LUA-Umsetzung. Für SHA512 müssen wir uns eines externen Programmes (in diesem Fall ein PHP-Skript) bedienen.

Der Salz-hash aus der Live-Umgebung ⇒ '<decrypt>U2FsdGVkX19AL/PUlfXxQQgDKgzZzAgiqTCFVCoKZUc=</decrypt>';

/etc/lighttpd/sha512crypt.php
<?php
$salt = 'Salz-hash';
echo hash('sha512', $salt . $argv[1]);
?>
/home/http/wiki/data/pages/lighttpd.txt · Zuletzt geändert: von manfred