first commit
This commit is contained in:
parent
883dd76931
commit
2e22667181
17 changed files with 889 additions and 5 deletions
147
lib/common.sh
Normal file
147
lib/common.sh
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
#!/usr/bin/env bash
|
||||
# common.sh — bibliothèque partagée des outils de pentest preprod.
|
||||
#
|
||||
# Fournit : chargement de la cible (targets.env), vérification
|
||||
# d'autorisation (scope), client HTTP (curl) avec journalisation,
|
||||
# sortie colorée, gestion du délai entre requêtes.
|
||||
#
|
||||
# Toutes les fonctions supposent que TARGET_BASE_URL est défini.
|
||||
# Charger avec : source "$(dirname "$0")/../lib/common.sh"
|
||||
# depuis un outil sous tools/<nom>/, ou adapter COMMON_SH ci-dessous.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# --- Couleurs (désactivées si pas de TTY) -------------------------------
|
||||
if [[ -t 1 ]]; then
|
||||
C_RED=$'\033[31m'; C_GREEN=$'\033[32m'; C_YELLOW=$'\033[33m'
|
||||
C_CYAN=$'\033[36m'; C_DIM=$'\033[2m'; C_RESET=$'\033[0m'
|
||||
else
|
||||
C_RED=""; C_GREEN=""; C_YELLOW=""; C_CYAN=""; C_DIM=""; C_RESET=""
|
||||
fi
|
||||
|
||||
info() { printf '%s[INFO]%s %s\n' "$C_CYAN" "$C_RESET" "$*"; }
|
||||
ok() { printf '%s[OK]%s %s\n' "$C_GREEN" "$C_RESET" "$*"; }
|
||||
warn() { printf '%s[WARN]%s %s\n' "$C_YELLOW" "$C_RESET" "$*"; }
|
||||
err() { printf '%s[ERR]%s %s\n' "$C_RED" "$C_RESET" "$*" >&2; }
|
||||
die() { err "$*"; exit 1; }
|
||||
|
||||
# --- Chargement de la cible --------------------------------------------
|
||||
# Résout le répertoire racine de la suite (parent du dossier tools/).
|
||||
# Usage depuis tools/<outil>/script.sh : COMMON_SH pointe sur ../../lib
|
||||
suite_root() {
|
||||
# $BASH_SOURCE[0] = ce fichier (lib/common.sh) → racine = son parent
|
||||
local this; this="${BASH_SOURCE[0]}"
|
||||
local dir; dir="$(cd "$(dirname "$this")" && pwd)"
|
||||
printf '%s' "$(dirname "$dir")"
|
||||
}
|
||||
|
||||
# Charge targets.env. Refuse de tourner sans fichier de cible.
|
||||
# Argument optionnel : chemin vers un targets.env alternatif.
|
||||
load_target() {
|
||||
local env_file="${1:-$(suite_root)/targets.env}"
|
||||
[[ -f "$env_file" ]] \
|
||||
|| die "Aucun fichier de cible trouvé ($env_file). Copiez targets.example.env → targets.env et renseignez vos valeurs."
|
||||
# shellcheck disable=SC1090
|
||||
source "$env_file"
|
||||
|
||||
[[ -n "${TARGET_BASE_URL:-}" ]] \
|
||||
|| die "targets.env: TARGET_BASE_URL est requis."
|
||||
[[ -n "${TARGET_SCOPE_ACK:-}" ]] \
|
||||
|| die "targets.env: TARGET_SCOPE_ACK doit valoir 'yes' (confirmation que la cible vous appartient et que le test est autorisé)."
|
||||
[[ "$TARGET_SCOPE_ACK" == "yes" ]] \
|
||||
|| die "targets.env: TARGET_SCOPE_ACK != 'yes'. Outil bloqué tant que l'autorisation n'est pas confirmée."
|
||||
|
||||
# Hôtes autorisés. Par défaut : l'hôte de TARGET_BASE_URL. Si
|
||||
# TARGET_ALLOWED_HOSTS est défini (liste séparée par espaces), il
|
||||
# étend le périmètre — utile quand la preprod a plusieurs hôtes
|
||||
# (ex : Yavsc.Org / Yavsc.Api / Yavsc.Blogs). Voir docs/scope.md.
|
||||
local base_host; base_host="$(printf '%s' "$TARGET_BASE_URL" \
|
||||
| sed -E 's#^[a-zA-Z]+://##; s#/.*$##; s#:.*$##')"
|
||||
# Construction + déduplication (l'hôte de base peut aussi figurer
|
||||
# dans TARGET_ALLOWED_HOSTS).
|
||||
local -A _seen=()
|
||||
AUTHORIZED_HOSTS=()
|
||||
for h in "$base_host" ${TARGET_ALLOWED_HOSTS:-}; do
|
||||
[[ -n "$h" && -z "${_seen[$h]:-}" ]] || continue
|
||||
_seen[$h]=1
|
||||
AUTHORIZED_HOSTS+=( "$h" )
|
||||
done
|
||||
export TARGET_BASE_URL TARGET_ALLOWED_HOSTS AUTHORIZED_HOSTS
|
||||
}
|
||||
|
||||
# Vérifie qu'une URL donnée appartient bien au périmètre autorisé.
|
||||
# Empêche un outil de dériver vers un tiers par maladresse.
|
||||
assert_in_scope() {
|
||||
local url="$1"
|
||||
local host; host="$(printf '%s' "$url" \
|
||||
| sed -E 's#^[a-zA-Z]+://##; s#/.*$##; s#:.*$##')"
|
||||
local h
|
||||
for h in "${AUTHORIZED_HOSTS[@]}"; do
|
||||
[[ "$host" == "$h" || "$host" == *".$h" ]] && return 0
|
||||
done
|
||||
die "Hors périmètre : $host (autorisé : ${AUTHORIZED_HOSTS[*]}). Abandon."
|
||||
}
|
||||
|
||||
# --- Client HTTP -------------------------------------------------------
|
||||
# Globales positionnées par http_probe. Initialisées ici pour ne pas
|
||||
# déclencher set -u au premier appel.
|
||||
LAST_CODE=""
|
||||
LAST_BODY=""
|
||||
|
||||
# http_probe METHOD URL [curl-args...]
|
||||
# Émet une requête et positionne les globales LAST_CODE (code HTTP, ou
|
||||
# "000" si curl a échoué) et LAST_BODY (chemin d'un fichier temporaire
|
||||
# contenant le corps de la réponse, ou "" si échec).
|
||||
#
|
||||
# IMPORTANT : ne PAS appeler dans une substitution de commande
|
||||
# (code=$(http_probe ...)) : la substitution s'exécute dans un
|
||||
# sous-shell et les globales ne remonteraient pas. Appeler
|
||||
# directement, puis lire $LAST_CODE / $LAST_BODY, et appeler
|
||||
# drop_body une fois le corps traité.
|
||||
http_probe() {
|
||||
local method="$1"; shift
|
||||
local url="$1"; shift
|
||||
assert_in_scope "$url"
|
||||
local code body_file
|
||||
body_file="$(mktemp)"
|
||||
code="$(set +e; curl -s -o "$body_file" -w '%{http_code}' \
|
||||
-X "$method" \
|
||||
--connect-timeout "${CURL_TIMEOUT:-10}" \
|
||||
--max-time "${CURL_MAX_TIME:-30}" \
|
||||
"$@" "$url")"
|
||||
local rc=$?
|
||||
if [[ $rc -ne 0 ]]; then
|
||||
warn "curl a échoué (rc=$rc) sur $method $url"
|
||||
rm -f "$body_file"
|
||||
LAST_CODE="000"
|
||||
LAST_BODY=""
|
||||
return 0
|
||||
fi
|
||||
if [[ "${VERBOSE:-0}" == "1" ]]; then
|
||||
printf '%s%s %s%s → %s%s\n' "$C_DIM" "$method" "$url" "$C_RESET" "$C_CYAN" "$code"
|
||||
[[ -s "$body_file" ]] && head -c 200 "$body_file" && printf '\n---\n'
|
||||
fi
|
||||
LAST_CODE="$code"
|
||||
LAST_BODY="$body_file"
|
||||
}
|
||||
|
||||
drop_body() { [[ -n "${LAST_BODY:-}" ]] && rm -f "$LAST_BODY"; LAST_BODY=""; }
|
||||
|
||||
# Renvoie les URL de base (une par hôte autorisé) en conservant le
|
||||
# schéma de TARGET_BASE_URL. Les scanners itèrent dessus pour couvrir
|
||||
# tout le périmètre multi-hôtes.
|
||||
each_scope_url() {
|
||||
local scheme; scheme="$(printf '%s' "$TARGET_BASE_URL" \
|
||||
| sed -E 's#://.*$##')"
|
||||
[[ -z "$scheme" ]] && scheme="https"
|
||||
local h
|
||||
for h in "${AUTHORIZED_HOSTS[@]}"; do
|
||||
printf '%s://%s\n' "$scheme" "$h"
|
||||
done
|
||||
}
|
||||
|
||||
# Délai entre requêtes (anti-DoS involontaire). Pacing obligatoire.
|
||||
pace() {
|
||||
local d="${REQUEST_DELAY:-0}"
|
||||
[[ "$d" != "0" ]] && sleep "$d"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue