first commit
This commit is contained in:
parent
883dd76931
commit
2e22667181
17 changed files with 889 additions and 5 deletions
34
tools/config-scan/README.md
Normal file
34
tools/config-scan/README.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# config-scan
|
||||
|
||||
Détecte les fichiers de configuration et surfaces sensibles
|
||||
accidentellement exposés publiquement sur la preprod.
|
||||
|
||||
## Principe
|
||||
|
||||
Émet des `GET` sur une liste de chemins courants (`/.git/HEAD`,
|
||||
`/.env`, `/appsettings.json`, `/swagger`, `/openapi.json`, etc.) et
|
||||
signale tout ce qui répond 200 (exposé) ou 401/403 (présent mais
|
||||
protégé — bonne pratique confirmant l'existence, à garder sous
|
||||
œil).
|
||||
|
||||
## Lancement
|
||||
|
||||
```bash
|
||||
./scan.sh
|
||||
```
|
||||
|
||||
## Sortie
|
||||
|
||||
- stdout : chemins notables (200 en vert = exposé, 403 en jaune).
|
||||
- `output/config-scan.log` : une ligne par chemin testé
|
||||
(`horodatage \t code \t taille \t chemin`).
|
||||
|
||||
## Actions typiques
|
||||
|
||||
- `/.git/HEAD` en 200 → dépôt git servi statiquement : bloquer
|
||||
l'accès aux répertoires `.*` au niveau du reverse proxy.
|
||||
- `/appsettings*.json` en 200 → fuite potentielle de chaînes de
|
||||
connexion / secrets : déplacer hors racine web, servir hors du
|
||||
static.
|
||||
- `/swagger` exposé en production → désactiver en prod, garder en
|
||||
preprod uniquement derrière auth.
|
||||
99
tools/config-scan/scan.sh
Executable file
99
tools/config-scan/scan.sh
Executable file
|
|
@ -0,0 +1,99 @@
|
|||
#!/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."
|
||||
Loading…
Add table
Add a link
Reference in a new issue