mirror of
https://github.com/Zproger/Aurum.git
synced 2026-10-13 11:06:40 +07:00
security: TLS, проверка Host, шифрованное запоминание входа и аудит-лог
- TLS через подключаемый overlay docker-compose.tls.yml + Caddyfile: Caddy сам получает и продлевает сертификат Let's Encrypt, HSTS добавляется на уровне прокси — намеренно там, а не в nginx.conf, иначе установки без TLS заперли бы сами себя; - проверка заголовка Host против DNS rebinding: AURUM_ALLOWED_HOSTS, по умолчанию localhost и 127.0.0.1, чужой Host получает 421 с подсказкой, какую переменную поправить; - «запомнить меня на 7 дней» вернулось в безопасном виде: пароль шифруется AES-GCM ключом с extractable: false в IndexedDB, вместо прежнего base64 в localStorage, который разворачивался обратно в пароль одним atob. Требует secure context, поэтому по обычному HTTP к LAN-адресу чекбокс не показывается, а не притворяется рабочим; - аудит-лог необратимых операций (восстановление бэкапа, массовое создание транзакций, удаление счёта) в лог контейнера. Не в БД сознательно: таблица аудита исчезла бы ровно в том событии, которое должна объяснять; - README: раздел про TLS и таблица двух переменных, решающих, кто может достучаться до инстанса.
This commit is contained in:
45
frontend/docker-entrypoint.d/25-allowed-hosts.sh
Normal file
45
frontend/docker-entrypoint.d/25-allowed-hosts.sh
Normal file
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
# Runs before nginx starts, same convention as 20-basic-auth.sh next door.
|
||||
#
|
||||
# Writes the Host allow-list that nginx.conf includes. This is what stops DNS
|
||||
# rebinding: a page on the open internet can point its own hostname at
|
||||
# 127.0.0.1, wait for the DNS TTL to expire, and then have the victim's own
|
||||
# browser issue same-origin requests to whatever is listening there. The
|
||||
# browser's origin checks don't help — as far as it's concerned the request
|
||||
# really is same-origin — but the Host header still carries the attacker's
|
||||
# domain, so refusing hostnames we don't expect closes it.
|
||||
#
|
||||
# AURUM_ALLOWED_HOSTS is a space- or comma-separated list. Default covers
|
||||
# local access only; add your own hostname when you serve Aurum under one
|
||||
# (see .env.example). "*" disables the check entirely.
|
||||
set -eu
|
||||
|
||||
FRAGMENT=/etc/nginx/allowed-hosts.conf
|
||||
HOSTS="${AURUM_ALLOWED_HOSTS:-localhost 127.0.0.1}"
|
||||
|
||||
if [ "$HOSTS" = "*" ]; then
|
||||
: > "$FRAGMENT"
|
||||
echo "[aurum] Host header check disabled (AURUM_ALLOWED_HOSTS=*)." >&2
|
||||
return 0 2>/dev/null || exit 0
|
||||
fi
|
||||
|
||||
# "a,b c" -> "a|b|c", with regex metacharacters in each entry escaped so an
|
||||
# IP's dots can't match any character.
|
||||
PATTERN="$(printf '%s' "$HOSTS" \
|
||||
| tr ',' ' ' \
|
||||
| tr -s ' ' '\n' \
|
||||
| sed '/^$/d' \
|
||||
| sed 's/[].[^$*\/+?(){}|\\]/\\&/g' \
|
||||
| paste -sd '|' -)"
|
||||
|
||||
cat > "$FRAGMENT" <<EOF
|
||||
# Generated at container start by docker-entrypoint.d/25-allowed-hosts.sh.
|
||||
# \$host is the Host header without the port, so entries here are bare
|
||||
# hostnames. "if" is normally best avoided in nginx, but a bare "return"
|
||||
# inside it is one of the two documented-safe uses.
|
||||
if (\$host !~* '^(${PATTERN})\$') {
|
||||
return 421 "Aurum: unexpected Host header '\$host'. Add it to AURUM_ALLOWED_HOSTS in .env (see .env.example), or set that variable to * to disable this check.\n";
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "[aurum] Host header allow-list: ${HOSTS}" >&2
|
||||
Reference in New Issue
Block a user