mirror of
https://github.com/Zproger/Aurum.git
synced 2026-10-13 02:56:39 +07:00
- 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 и таблица двух переменных, решающих, кто может достучаться до инстанса.
46 lines
1.8 KiB
Bash
46 lines
1.8 KiB
Bash
#!/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
|