security-tools/tools/config-scan/scan.sh
2026-09-24 18:11:03 +01:00

99 lines
No EOL
2.9 KiB
Bash
Executable file

#!/usr/bin/env bash
# scan.sh — recherche les fichiers de configuration et éléments sensibles
# accidentellement exposés sur la preprod.
#
# USAGE
# ./scan.sh [targets.env]
#
# Vérifie la présence et la lisibilité de chemins courants :
# - dépôts git exposés (/.git/...)
# - fichiers d'env / settings (.env, appsettings.json, web.config)
# - surfaces de doc API (swagger, openapi)
# - répertoires de listing
#
# Journalise dans $OUTPUT_DIR/config-scan.log. Signale tout ce qui
# répond 200 (ou 403 = présent mais protégé) pour un passage en revue.
COMMON_SH="$(cd "$(dirname "$0")/../.." && pwd)/lib/common.sh"
# shellcheck disable=SC1091
source "$COMMON_SH"
load_target "${1:-}"
mkdir -p "${OUTPUT_DIR:-./output}"
LOG="${OUTPUT_DIR:-./output}/config-scan.log"
: > "$LOG"
# Chemins à tester (relatifs à TARGET_BASE_URL). Pas de cible tierce.
PATHS=(
"/.git/HEAD"
"/.git/config"
"/.env"
"/.env.local"
"/appsettings.json"
"/appsettings.Development.json"
"/appsettings.Production.json"
"/web.config"
"/connectionstrings.json"
"/swagger"
"/swagger/v1/swagger.json"
"/swagger/index.html"
"/openapi.json"
"/openapi/v1.json"
"/robots.txt"
"/.well-known/openid-configuration"
"/elmah.axd"
"/trace.axd"
"/wp-config.php"
"/server-status"
"/.DS_Store"
"/backup"
"/.vscode"
)
info "Scan de ${#PATHS[@]} chemins sur ${#AUTHORIZED_HOSTS[@]} hôte(s) du périmètre"
info "Journal : $LOG"
# Endpoints **intentionnellement publics** (un 200 est normal, pas une
# fuite) : la discovery OIDC d'IdentityServer, requise par les clients
# (PostIt) pour se connecter.
EXPECTED_PUBLIC=(
"/.well-known/openid-configuration"
"/.well-known/jwks"
)
is_expected_public() {
local p="$1"
local e
for e in "${EXPECTED_PUBLIC[@]}"; do [[ "$e" == "$p" ]] && return 0; done
return 1
}
while IFS= read -r base; do
info "→ $base"
for p in "${PATHS[@]}"; do
url="${base}${p}"
# http_probe gère déjà assert_in_scope.
http_probe GET "$url"
code="$LAST_CODE"
size=0
[[ -n "$LAST_BODY" && -s "$LAST_BODY" ]] && size=$(wc -c < "$LAST_BODY")
printf '%s\t%s\t%s\t%8d\t%s\n' "$(date -Is)" "$base" "$code" "$size" "$p" >> "$LOG"
case "$code" in
200)
if is_expected_public "$p"; then
ok "200 $base$p (${size} o) — public attendu (OIDC discovery)"
else
ok "200 $base$p (${size} o) — EXPOSÉ, à corriger"
fi
;;
401|403) warn "$code $base$p — présent mais protégé" ;;
301|302) warn "$code $base$p — redirection (vérifier la cible)" ;;
404) ;;
*) warn "$code $base$p" ;;
esac
drop_body
pace
done
done < <(each_scope_url)
info "Terminé. Voir $LOG."