#!/usr/bin/env bash
#
# degrade-security.sh
# ===================
# But pédagogique : dégrade VOLONTAIREMENT la configuration d'une VM
# Debian 12 fraîchement installée afin de générer des alertes Lynis
# claires, faciles à expliquer puis à corriger.
#
#  /!\  A N'UTILISER QUE SUR UNE VM JETABLE / DE DEMO, ISOLEE DU RESEAU.
#  /!\  Certaines options ouvrent réellement la machine (root SSH,
#       mots de passe vides autorisés, etc.).
#
# Le script :
#   1. sauvegarde chaque fichier modifié dans /root/lynis-demo-backups/<date>/
#   2. journalise chaque action dans CHANGELOG.txt
#   3. génère un restore.sh pour tout remettre en l'état
#   4. écrit la liste des chemins touchés dans FICHIERS-MODIFIES.txt
#
set -euo pipefail

# ----------------------------------------------------------------------
# Garde-fous
# ----------------------------------------------------------------------
if [[ ${EUID} -ne 0 ]]; then
  echo "Ce script doit être lancé en root (sudo)." >&2
  exit 1
fi

TS="$(date +%Y%m%d-%H%M%S)"
BACKUP_DIR="/root/lynis-demo-backups/${TS}"
CHANGELOG="${BACKUP_DIR}/CHANGELOG.txt"
RESTORE="${BACKUP_DIR}/restore.sh"
MODIFIED="${BACKUP_DIR}/FICHIERS-MODIFIES.txt"

mkdir -p "${BACKUP_DIR}"

log() { echo "[$(date +%H:%M:%S)] $*" | tee -a "${CHANGELOG}"; }

# Sauvegarde un fichier et inscrit sa commande de restauration.
# - fichier existant  -> restauré par copie (contenu + droits préservés)
# - fichier absent     -> supprimé à la restauration
backup_file() {
  local f="$1"
  if [[ -e "${f}" ]]; then
    local dest="${BACKUP_DIR}/files${f}"
    mkdir -p "$(dirname "${dest}")"
    cp -a "${f}" "${dest}"
    echo "cp -a -- '${dest}' '${f}'" >> "${RESTORE}"
    log "Sauvegarde   : ${f}"
  else
    echo "rm -f -- '${f}'" >> "${RESTORE}"
    log "Fichier neuf : ${f} (sera supprimé à la restauration)"
  fi
  echo "${f}" >> "${MODIFIED}"
}

init_restore() {
  cat > "${RESTORE}" <<'EOF'
#!/usr/bin/env bash
# Script de restauration généré automatiquement par degrade-security.sh
set -euo pipefail
[[ ${EUID} -ne 0 ]] && { echo "Lancez en root." >&2; exit 1; }
echo "Restauration de la configuration d'origine..."
EOF
  chmod +x "${RESTORE}"
}

init_restore
: > "${MODIFIED}"
log "=== Début de la dégradation - sauvegardes : ${BACKUP_DIR} ==="

# ----------------------------------------------------------------------
# 1. SSH : ouverture large du démon (Lynis : SSH-7408)
# ----------------------------------------------------------------------
SSHD_DROPIN="/etc/ssh/sshd_config.d/00-lynis-demo-insecure.conf"
backup_file "${SSHD_DROPIN}"
cat > "${SSHD_DROPIN}" <<'EOF'
# DEMO Lynis - configuration SSH volontairement NON sécurisée
PermitRootLogin yes
PasswordAuthentication yes
PermitEmptyPasswords yes
X11Forwarding yes
MaxAuthTries 10
LoginGraceTime 120
AllowTcpForwarding yes
ClientAliveInterval 0
EOF
log "SSH          : drop-in non sécurisé créé"
if sshd -t 2>/dev/null; then
  systemctl reload ssh 2>/dev/null || systemctl reload sshd 2>/dev/null || true
  echo "systemctl reload ssh 2>/dev/null || systemctl reload sshd 2>/dev/null || true" >> "${RESTORE}"
  log "SSH          : service rechargé"
else
  log "SSH          : ATTENTION, test de config échoué -> non rechargé"
fi

# ----------------------------------------------------------------------
# 2. login.defs : umask trop permissif (Lynis : AUTH-9328)
# ----------------------------------------------------------------------
LOGIN_DEFS="/etc/login.defs"
backup_file "${LOGIN_DEFS}"
sed -i -E 's/^(\s*UMASK\s+).*/\1000/' "${LOGIN_DEFS}"
grep -qE '^\s*UMASK\s+' "${LOGIN_DEFS}" || echo "UMASK 000" >> "${LOGIN_DEFS}"
log "login.defs   : UMASK fixé à 000 (recommandé : 027)"

# ----------------------------------------------------------------------
# 3. Paramètres noyau non durcis (Lynis : KRNL-6000)
# ----------------------------------------------------------------------
SYSCTL_DROPIN="/etc/sysctl.d/99-lynis-demo-insecure.conf"
backup_file "${SYSCTL_DROPIN}"
cat > "${SYSCTL_DROPIN}" <<'EOF'
# DEMO Lynis - paramètres noyau volontairement NON durcis
net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_redirects = 1
net.ipv4.conf.all.send_redirects = 1
net.ipv4.conf.all.accept_source_route = 1
net.ipv4.conf.all.log_martians = 0
net.ipv4.conf.default.accept_redirects = 1
net.ipv6.conf.all.accept_redirects = 1
kernel.sysrq = 1
kernel.dmesg_restrict = 0
kernel.kptr_restrict = 0
fs.suid_dumpable = 2
EOF
sysctl -p "${SYSCTL_DROPIN}" >/dev/null 2>&1 || true
log "sysctl       : drop-in non durci appliqué"
# Restauration : on supprime le fichier (backup_file) ET on réapplique des valeurs saines
cat >> "${RESTORE}" <<'EOF'
for kv in \
  "net.ipv4.ip_forward=0" \
  "net.ipv4.conf.all.accept_redirects=0" \
  "net.ipv4.conf.all.send_redirects=0" \
  "net.ipv4.conf.all.accept_source_route=0" \
  "net.ipv4.conf.all.log_martians=1" \
  "net.ipv4.conf.default.accept_redirects=0" \
  "net.ipv6.conf.all.accept_redirects=0" \
  "kernel.sysrq=0" \
  "kernel.dmesg_restrict=1" \
  "kernel.kptr_restrict=2" \
  "fs.suid_dumpable=0" ; do
  sysctl -w "$kv" >/dev/null 2>&1 || true
done
sysctl --system >/dev/null 2>&1 || true
EOF

# ----------------------------------------------------------------------
# 4. Bannières légales absentes (Lynis : BANN-7126 / BANN-7130)
# ----------------------------------------------------------------------
backup_file /etc/issue
backup_file /etc/issue.net
: > /etc/issue
: > /etc/issue.net
log "Bannières    : /etc/issue et /etc/issue.net vidées"

# ----------------------------------------------------------------------
# 5. Permissions dangereuses (Lynis : section File Permissions)
# ----------------------------------------------------------------------
# 5a. /etc/crontab en 0777
backup_file /etc/crontab
chmod 0777 /etc/crontab
log "Permissions  : /etc/crontab en 0777 (attendu : 0644)"

# 5b. fichier monde-inscriptible dans /etc
WW_FILE="/etc/lynis-demo-world-writable.conf"
backup_file "${WW_FILE}"
echo "# fichier de demo" > "${WW_FILE}"
chmod 0666 "${WW_FILE}"
log "Permissions  : ${WW_FILE} créé en 0666"

# 5c. répertoire 0777 sans sticky bit
WW_DIR="/opt/lynis-demo-shared"
mkdir -p "${WW_DIR}"
chmod 0777 "${WW_DIR}"
echo "rm -rf -- '${WW_DIR}'" >> "${RESTORE}"
echo "${WW_DIR}" >> "${MODIFIED}"
log "Permissions  : ${WW_DIR} créé en 0777 (sans sticky bit)"

# ----------------------------------------------------------------------
# 6. (OPTIONNEL) Désactivation d'AppArmor (Lynis : MACF-6208)
#     Décommentez le bloc ci-dessous SI vous voulez aussi cet écart.
#     Effet pleinement visible APRÈS un redémarrage de la VM.
# ----------------------------------------------------------------------
# if systemctl is-enabled apparmor >/dev/null 2>&1; then
#   systemctl disable --now apparmor >/dev/null 2>&1 || true
#   echo "systemctl enable --now apparmor >/dev/null 2>&1 || true" >> "${RESTORE}"
#   echo "service:apparmor" >> "${MODIFIED}"
#   log "AppArmor     : désactivé (effet complet après reboot)"
# fi

# ----------------------------------------------------------------------
# Fin
# ----------------------------------------------------------------------
echo 'echo "Restauration terminée. Un reboot est conseillé pour les paramètres noyau."' >> "${RESTORE}"

log "=== Dégradation terminée ==="
echo
echo "------------------------------------------------------------------"
echo " Fichiers / éléments modifiés :"
sed 's/^/   - /' "${MODIFIED}"
echo "------------------------------------------------------------------"
echo " Journal complet : ${CHANGELOG}"
echo " Pour analyser   : sudo lynis audit system"
echo " Pour tout annuler : sudo ${RESTORE}"
echo "------------------------------------------------------------------"