Sicherheitshaertung: Injection-Schutz, atomares Locking, Pfad-Validierung

- load_config blockiert Shell-Operatoren (;|&`) in .env-Werten
- validate_path prueft Sonderzeichen und Path-Traversal in Pfad-Variablen
- validate_config prüft DARKTABLE_BIN-basename und ruft validate_path auf
- Lockdir-Trap erst nach erfolgreicher Lock-Akquisition registriert
  (verhindert dass externer Lockdir bei gescheitertem Lock entfernt wird)
- uninstall.sh nutzt rmdir statt rm -rf fuer Lockdir
- security.bats mit 10 Tests fuer alle Sicherheitsanforderungen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-19 19:57:39 +02:00
parent 46664ab3b6
commit 92a5d50082
5 changed files with 192 additions and 15 deletions
+2 -2
View File
@@ -52,8 +52,8 @@ setup() {
[ -f "$CONFIG_DIR/sync_pending" ]
}
@test "Lockfile wird nach Abschluss entfernt" {
@test "Lockdir wird nach Abschluss entfernt" {
run_with_stubs env SSH_STUB_FAIL=0 bash "$SYNC_SCRIPT"
[ "$status" -eq 0 ]
[ ! -f "/tmp/darktable_sync.sh.lock" ]
[ ! -d "$CONFIG_DIR/sync.lock" ]
}
+147
View File
@@ -0,0 +1,147 @@
#!/usr/bin/env bats
# Security-Tests fuer darktable-sync
load helpers/setup
COMMON_SCRIPT="$BATS_TEST_DIRNAME/../scripts/darktable_common.sh"
SYNC_SCRIPT="$BATS_TEST_DIRNAME/../scripts/darktable_sync.sh"
WRAPPER_SCRIPT="$BATS_TEST_DIRNAME/../scripts/darktable_wrapper.sh"
setup() {
create_valid_env
mkdir -p "$HOME/.config/darktable"
touch "$HOME/.config/darktable/library.db"
touch "$HOME/.config/darktable/data.db"
mkdir -p "$HOME/Pictures"
export DISPLAY=:99
}
# --- K1: .env Code-Injection wird geblockt ---
@test "security: .env mit Semikolon wird abgelehnt" {
cat > "$CONFIG_DIR/.env" <<'EOF'
SERVER_IP=192.168.1.100
SERVER_USER=testuser
SERVER_SSH_PORT=22
SERVER_DB_DIR=/remote/db
SERVER_PHOTO_DIR=/remote/photos
LOCAL_DARKTABLE_DB_DIR=/tmp/dt_test
LOCAL_PHOTO_DIR=/tmp/photos_test
DARKTABLE_BIN=darktable
SYNC_BIN=/usr/local/bin/darktable_sync.sh
INJECTION_MARKER=injected; touch /tmp/dt_security_test_marker
EOF
run bash -c "source '$COMMON_SCRIPT'; load_config; echo done"
rm -f /tmp/dt_security_test_marker
[ "$status" -eq 1 ]
[[ "$output" == *"unerlaubte Zeichen"* ]]
}
@test "security: .env mit Backtick wird abgelehnt" {
cat > "$CONFIG_DIR/.env" <<'EOF'
SERVER_IP=192.168.1.100
SERVER_USER=testuser
SERVER_SSH_PORT=22
SERVER_DB_DIR=/remote/db
SERVER_PHOTO_DIR=/remote/photos
LOCAL_DARKTABLE_DB_DIR=/tmp/dt_test
LOCAL_PHOTO_DIR=/tmp/photos_test
DARKTABLE_BIN=darktable
SYNC_BIN=/usr/local/bin/darktable_sync.sh
EVIL=`touch /tmp/evil`
EOF
run bash -c "source '$COMMON_SCRIPT'; load_config; echo done"
[ "$status" -eq 1 ]
[[ "$output" == *"unerlaubte Zeichen"* ]]
}
# --- K2: validate_path blockt SSH-Injection ---
@test "security: SERVER_DB_DIR mit Single-Quote wird geblockt" {
create_valid_env
# Wert in Double-Quotes damit bash ihn fehlerfrei laedt, validate_path muss dann blockieren
printf 'SERVER_DB_DIR="/remote/db'"'"'injection"\n' >> "$CONFIG_DIR/.env"
run bash -c "source '$COMMON_SCRIPT'; load_config; validate_config"
[ "$status" -eq 1 ]
[[ "$output" == *"SERVER_DB_DIR"* ]]
}
@test "security: SERVER_DB_DIR mit Path-Traversal wird geblockt" {
create_valid_env
echo 'SERVER_DB_DIR=/../../../etc' >> "$CONFIG_DIR/.env"
run bash -c "source '$COMMON_SCRIPT'; load_config; validate_config"
[ "$status" -eq 1 ]
[[ "$output" == *"SERVER_DB_DIR"* ]]
}
# --- H1: Atomares Locking mit mkdir ---
@test "security: gleichzeitiger Sync wird durch Lockdir geblockt" {
mkdir -p "$CONFIG_DIR/sync.lock"
run_with_stubs env SSH_STUB_FAIL=0 bash "$SYNC_SCRIPT"
[ "$status" -eq 1 ]
[[ "$output" == *"laeuft bereits"* ]]
rmdir "$CONFIG_DIR/sync.lock"
}
# --- H2: Lockdir nicht durch Symlink angreifbar ---
@test "security: Lockdir ist kein Symlink-Angriffspunkt" {
# mkdir schlaegt bei existierendem Symlink fehl kein Ziel wird geloescht
TARGET="$BATS_TMPDIR/symlink_target"
echo "wichtiger Inhalt" > "$TARGET"
ln -sf "$TARGET" "$CONFIG_DIR/sync.lock"
run_with_stubs env SSH_STUB_FAIL=0 bash "$SYNC_SCRIPT"
# Script muss fehlschlagen (Symlink statt echtes Verzeichnis = mkdir schlaegt fehl)
[ "$status" -eq 1 ]
# Zieldatei darf nicht geloescht worden sein
[ -f "$TARGET" ]
rm -f "$CONFIG_DIR/sync.lock" "$TARGET"
}
# --- H3: DARKTABLE_BIN muss 'darktable' sein ---
@test "security: DARKTABLE_BIN mit anderem basename wird geblockt" {
create_valid_env
echo "DARKTABLE_BIN=/usr/bin/evil_binary" >> "$CONFIG_DIR/.env"
run bash -c "source '$COMMON_SCRIPT'; load_config; validate_config"
[ "$status" -eq 1 ]
[[ "$output" == *"DARKTABLE_BIN"* ]]
}
# --- M2: .env-Berechtigungen werden gewarnt ---
@test "security: .env mit world-readable Berechtigungen loest Warnung aus" {
create_valid_env
chmod 644 "$CONFIG_DIR/.env"
run bash -c "source '$COMMON_SCRIPT'; load_config; echo \$SERVER_IP"
[ "$status" -eq 0 ]
[[ "$output" == *"world-readable"* ]]
}
# --- validate_config: fehlende Variablen ---
@test "security: validate_config blockt leere SERVER_IP" {
create_valid_env
echo "SERVER_IP=" >> "$CONFIG_DIR/.env"
run bash -c "source '$COMMON_SCRIPT'; load_config; validate_config"
[ "$status" -eq 1 ]
[[ "$output" == *"SERVER_IP"* ]]
}
@test "security: validate_config blockt fehlende SERVER_DB_DIR" {
create_valid_env
sed -i '/^SERVER_DB_DIR/d' "$CONFIG_DIR/.env"
run bash -c "source '$COMMON_SCRIPT'; load_config; validate_config"
[ "$status" -eq 1 ]
[[ "$output" == *"SERVER_DB_DIR"* ]]
}
# --- Lockdir Cleanup ---
@test "security: Lockdir wird bei normalem Exit entfernt" {
run_with_stubs env SSH_STUB_FAIL=0 bash "$SYNC_SCRIPT"
[ "$status" -eq 0 ]
[ ! -d "$CONFIG_DIR/sync.lock" ]
}