From 723374a71f83d60903f2ebc37a040fe27676544e Mon Sep 17 00:00:00 2001 From: Dxsk <43427519+dxsk@users.noreply.github.com> Date: Fri, 12 Jun 2026 00:29:03 +0200 Subject: [PATCH 1/7] feat(scan): add portscan, screenshot, nuclei, takeover & code-audit stages Fill the empty scan/exploit phases: naabu portscan, gowitness screenshots, nuclei vuln scan (proxy-routed), subdomain takeover (subzy with nuclei fallback), and white-box audit-code (trufflehog/gitleaks/semgrep/osv-scanner) over the recovered code/ zone. --- exegol/my-resources/bin/audit-code | 45 ++++++++++++++++++++++++ exegol/my-resources/bin/recon-portscan | 27 ++++++++++++++ exegol/my-resources/bin/recon-screenshot | 18 ++++++++++ exegol/my-resources/bin/scan-nuclei | 24 +++++++++++++ exegol/my-resources/bin/scan-takeover | 23 ++++++++++++ 5 files changed, 137 insertions(+) create mode 100644 exegol/my-resources/bin/audit-code create mode 100644 exegol/my-resources/bin/recon-portscan create mode 100644 exegol/my-resources/bin/recon-screenshot create mode 100644 exegol/my-resources/bin/scan-nuclei create mode 100644 exegol/my-resources/bin/scan-takeover diff --git a/exegol/my-resources/bin/audit-code b/exegol/my-resources/bin/audit-code new file mode 100644 index 0000000..af1ffee --- /dev/null +++ b/exegol/my-resources/bin/audit-code @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +set -euo pipefail +WS="${WORKSPACE:-$PWD}" +CODE="${1:-$WS/code}" +OUTD="$WS/scans/code" +mkdir -p "$OUTD" + +# White-box audit of recovered source / sourcemaps / beautified JS / loot. +[[ -d "$CODE" ]] || { echo "[!] no dir: $CODE"; exit 1; } +[[ -n "$(find "$CODE" -type f -print -quit 2>/dev/null)" ]] \ + || { echo "[!] $CODE is empty — run recon-sourcemaps / recon-loot first"; exit 1; } +echo "[*] auditing $CODE" + +# 1. Verified secret scan (trufflehog tests creds against their live APIs). +if command -v trufflehog >/dev/null 2>&1; then + trufflehog filesystem "$CODE" --results=verified,unknown --json \ + > "$OUTD/secrets_trufflehog.json" 2>/dev/null || true + echo "[+] trufflehog → $OUTD/secrets_trufflehog.json" +fi + +# 2. Regex secret scan (gitleaks). Pick the subcommand by capability: `dir` +# on v8.19+, `detect` on older builds. A non-zero exit just means leaks found. +if command -v gitleaks >/dev/null 2>&1; then + if gitleaks dir --help >/dev/null 2>&1; then + gitleaks dir "$CODE" -r "$OUTD/secrets_gitleaks.json" >/dev/null 2>&1 || true + else + gitleaks detect --no-git --source "$CODE" -r "$OUTD/secrets_gitleaks.json" >/dev/null 2>&1 || true + fi + echo "[+] gitleaks → $OUTD/secrets_gitleaks.json" +fi + +# 3. SAST (semgrep, registry "auto" ruleset). +if command -v semgrep >/dev/null 2>&1; then + semgrep scan --config auto --json -o "$OUTD/sast_semgrep.json" "$CODE" >/dev/null 2>&1 || true + echo "[+] semgrep → $OUTD/sast_semgrep.json" +fi + +# 4. SCA / vulnerable dependencies (osv-scanner v2 over any lockfile/manifest). +# Exit 1 = vulns found (or no lockfiles present), so swallow it. +if command -v osv-scanner >/dev/null 2>&1; then + osv-scanner scan source --recursive "$CODE" --format json --output "$OUTD/sca_osv.json" >/dev/null 2>&1 || true + echo "[+] osv-scanner → $OUTD/sca_osv.json" +fi + +echo "[+] audit done → $OUTD" diff --git a/exegol/my-resources/bin/recon-portscan b/exegol/my-resources/bin/recon-portscan new file mode 100644 index 0000000..a85f221 --- /dev/null +++ b/exegol/my-resources/bin/recon-portscan @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail +: "${DOMAIN:?load an engagement first (DOMAIN unset) — use: dl }" +OUT="${WORKSPACE:-$PWD}/recon" +PORTS="${WORKSPACE:-$PWD}/scans/ports" +mkdir -p "$PORTS" + +# Port scan the alive hosts (fallback: the raw subdomain list). +command -v naabu >/dev/null 2>&1 || { echo "[!] naabu not found"; exit 1; } +src="$OUT/subdomains_alive.txt" +[[ -s "$src" ]] || src="$OUT/subdomains.txt" +[[ -s "$src" ]] || { echo "[!] run recon-subs / recon-alive first"; exit 1; } + +# naabu wants bare hosts: strip scheme, path and any :port suffix. +sed -E 's#^[a-z]+://##; s#/.*$##; s#:[0-9]+$##' "$src" | sort -u > "$PORTS/hosts.txt" +echo "[*] naabu port scan ($(wc -l < "$PORTS/hosts.txt") hosts)" + +# PORTSCAN_NMAP=1 → naabu pipes discovered ports straight into nmap -sV. +if [[ "${PORTSCAN_NMAP:-0}" == "1" ]] && command -v nmap >/dev/null 2>&1; then + naabu -list "$PORTS/hosts.txt" -top-ports "${NAABU_TOP_PORTS:-1000}" -silent \ + -nmap-cli "nmap -sV -Pn -oN $PORTS/nmap.txt" 2>/dev/null | sort -u > "$PORTS/ports.txt" || true + echo "[+] nmap services → $PORTS/nmap.txt" +else + naabu -list "$PORTS/hosts.txt" -top-ports "${NAABU_TOP_PORTS:-1000}" -silent 2>/dev/null \ + | sort -u > "$PORTS/ports.txt" || true +fi +echo "[+] $(wc -l < "$PORTS/ports.txt" 2>/dev/null || echo 0) host:port → $PORTS/ports.txt" diff --git a/exegol/my-resources/bin/recon-screenshot b/exegol/my-resources/bin/recon-screenshot new file mode 100644 index 0000000..7c2ff4d --- /dev/null +++ b/exegol/my-resources/bin/recon-screenshot @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail +: "${DOMAIN:?load an engagement first (DOMAIN unset) — use: dl }" +OUT="${WORKSPACE:-$PWD}/recon" +SHOTS="$OUT/screenshots" +mkdir -p "$SHOTS" + +# Screenshot every alive host (gowitness v3: `scan file`). +command -v gowitness >/dev/null 2>&1 || { echo "[!] gowitness not found"; exit 1; } +[[ -s "$OUT/subdomains_alive.txt" ]] || { echo "[!] run recon-alive first"; exit 1; } + +echo "[*] gowitness screenshots" +gowitness scan file -f "$OUT/subdomains_alive.txt" -s "$SHOTS" \ + -t "${GOWITNESS_THREADS:-20}" -T "${GOWITNESS_TIMEOUT:-30}" \ + --write-csv --write-csv-file "$SHOTS/index.csv" >/dev/null 2>&1 || true + +n="$(find "$SHOTS" -maxdepth 1 -type f \( -name '*.jpeg' -o -name '*.png' \) 2>/dev/null | wc -l)" +echo "[+] $n screenshots → $SHOTS (index: $SHOTS/index.csv)" diff --git a/exegol/my-resources/bin/scan-nuclei b/exegol/my-resources/bin/scan-nuclei new file mode 100644 index 0000000..47486a3 --- /dev/null +++ b/exegol/my-resources/bin/scan-nuclei @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -euo pipefail +: "${DOMAIN:?load an engagement first (DOMAIN unset) — use: dl }" +OUT="${WORKSPACE:-$PWD}/recon" +VULN="${WORKSPACE:-$PWD}/scans/vuln" +mkdir -p "$VULN" + +# Vulnerability scan the alive hosts with nuclei. +command -v nuclei >/dev/null 2>&1 || { echo "[!] nuclei not found"; exit 1; } +src="$OUT/subdomains_alive.txt" +[[ -s "$src" ]] || { echo "[!] run recon-alive first"; exit 1; } + +# Conditional flags via an array (keeps UA header / proxy correctly quoted). +args=(-l "$src" + -severity "${NUCLEI_SEVERITY:-critical,high,medium}" + -rate-limit "${NUCLEI_RATE:-150}" + -stats -o "$VULN/nuclei.txt") +[[ -n "${UA:-}" ]] && args+=(-header "User-Agent: ${UA}") +# Route through the engagement proxy so findings are captured in mitmproxy. +[[ -n "${HTTP_PROXY:-}" ]] && args+=(-proxy "$HTTP_PROXY") + +echo "[*] nuclei scan ($(wc -l < "$src") targets, severity ${NUCLEI_SEVERITY:-critical,high,medium})" +nuclei "${args[@]}" 2>/dev/null || true +echo "[+] $(wc -l < "$VULN/nuclei.txt" 2>/dev/null || echo 0) findings → $VULN/nuclei.txt" diff --git a/exegol/my-resources/bin/scan-takeover b/exegol/my-resources/bin/scan-takeover new file mode 100644 index 0000000..5ee9931 --- /dev/null +++ b/exegol/my-resources/bin/scan-takeover @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -euo pipefail +: "${DOMAIN:?load an engagement first (DOMAIN unset) — use: dl }" +OUT="${WORKSPACE:-$PWD}/recon" +VULN="${WORKSPACE:-$PWD}/scans/vuln" +mkdir -p "$VULN" + +# Subdomain takeover check over the full subdomain list (dangling CNAMEs). +src="$OUT/subdomains.txt" +[[ -s "$src" ]] || { echo "[!] run recon-subs first"; exit 1; } + +if command -v subzy >/dev/null 2>&1; then + echo "[*] subzy takeover check ($(wc -l < "$src") subdomains)" + subzy run --targets "$src" --concurrency 100 --hide_fails --verify_ssl 2>/dev/null \ + | tee "$VULN/takeover.txt" >/dev/null || true +elif command -v nuclei >/dev/null 2>&1; then + echo "[*] nuclei takeover templates ($(wc -l < "$src") subdomains)" + nuclei -l "$src" -tags takeover -severity critical,high,medium \ + -o "$VULN/takeover.txt" 2>/dev/null || true +else + echo "[!] neither subzy nor nuclei found"; exit 1 +fi +echo "[+] takeover results → $VULN/takeover.txt" From 4a69160d3e3535976a9f2fce7288986c8ad6dc3f Mon Sep 17 00:00:00 2001 From: Dxsk <43427519+dxsk@users.noreply.github.com> Date: Fri, 12 Jun 2026 00:31:06 +0200 Subject: [PATCH 2/7] fix(recon): resolve httpx binary + harden recon-full recon-alive/recon-fingerprint called httpx-toolkit (Kali name); Exegol ships it as httpx, which broke the whole pipeline at the alive-check step. Resolve the binary at runtime (httpx-toolkit||httpx) and fail loudly if absent. Wire portscan/screenshot into recon-full and make enrichment steps best-effort. --- exegol/my-resources/bin/recon-alive | 5 ++++- exegol/my-resources/bin/recon-fingerprint | 5 ++++- exegol/my-resources/bin/recon-full | 15 ++++++++++----- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/exegol/my-resources/bin/recon-alive b/exegol/my-resources/bin/recon-alive index 3ff9693..3b233c0 100755 --- a/exegol/my-resources/bin/recon-alive +++ b/exegol/my-resources/bin/recon-alive @@ -5,7 +5,10 @@ OUT="${WORKSPACE:-$PWD}/recon" mkdir -p "$OUT" [[ -s "$OUT/subdomains.txt" ]] || { echo "[!] run recon-subs first"; exit 1; } +# httpx binary: Exegol ships it as `httpx`, Kali as `httpx-toolkit`. +HTTPX="$(command -v httpx-toolkit || command -v httpx || true)" +[[ -n "$HTTPX" ]] || { echo "[!] projectdiscovery httpx not found"; exit 1; } echo "[*] httpx alive check" -httpx-toolkit -l "$OUT/subdomains.txt" -mc 200 -ports 443,80,8080,8000,8888 -threads 200 2>/dev/null \ +"$HTTPX" -l "$OUT/subdomains.txt" -mc 200 -ports 443,80,8080,8000,8888 -threads 200 2>/dev/null \ | sort -u > "$OUT/subdomains_alive.txt" echo "[+] $(wc -l < "$OUT/subdomains_alive.txt") alive → $OUT/subdomains_alive.txt" diff --git a/exegol/my-resources/bin/recon-fingerprint b/exegol/my-resources/bin/recon-fingerprint index 0a30fc3..0aa7da5 100755 --- a/exegol/my-resources/bin/recon-fingerprint +++ b/exegol/my-resources/bin/recon-fingerprint @@ -5,7 +5,10 @@ OUT="${WORKSPACE:-$PWD}/recon"; mkdir -p "$OUT" # Technology fingerprint of the alive hosts. [[ -s "$OUT/subdomains_alive.txt" ]] || { echo "[!] run recon-alive first"; exit 1; } +# httpx binary: Exegol ships it as `httpx`, Kali as `httpx-toolkit`. +HTTPX="$(command -v httpx-toolkit || command -v httpx || true)" +[[ -n "$HTTPX" ]] || { echo "[!] projectdiscovery httpx not found"; exit 1; } echo "[*] tech fingerprint" -httpx-toolkit -l "$OUT/subdomains_alive.txt" -td -silent 2>/dev/null > "$OUT/tech.txt" || true +"$HTTPX" -l "$OUT/subdomains_alive.txt" -td -silent 2>/dev/null > "$OUT/tech.txt" || true if command -v whatweb >/dev/null 2>&1; then whatweb -i "$OUT/subdomains_alive.txt" --no-errors >> "$OUT/tech.txt" 2>/dev/null || true; fi echo "[+] tech → $OUT/tech.txt" diff --git a/exegol/my-resources/bin/recon-full b/exegol/my-resources/bin/recon-full index 4ad836d..4750711 100755 --- a/exegol/my-resources/bin/recon-full +++ b/exegol/my-resources/bin/recon-full @@ -5,12 +5,17 @@ OUT="${WORKSPACE:-$PWD}/recon" mkdir -p "$OUT" echo "[*] full recon pipeline for $DOMAIN" +# Core discovery steps: if these fail the rest has no input, so let them abort. recon-subs recon-alive +# Enrichment + scanning steps: best-effort, a single failure must not kill the run. recon-fingerprint || echo "[i] fingerprint step skipped" -recon-crawl -recon-urls || echo "[i] urls step skipped" -recon-loot || echo "[i] loot step skipped" -recon-extract || echo "[i] extract step skipped" -recon-sourcemaps || echo "[i] sourcemaps step skipped" +recon-portscan || echo "[i] portscan step skipped" +recon-screenshot || echo "[i] screenshot step skipped" +recon-crawl || echo "[i] crawl step skipped" +recon-urls || echo "[i] urls step skipped" +recon-loot || echo "[i] loot step skipped" +recon-extract || echo "[i] extract step skipped" +recon-sourcemaps || echo "[i] sourcemaps step skipped" echo "[+] done → $OUT" +echo "[i] next: scan-nuclei · scan-takeover · audit-code" From 3be08c39e1b5bdbe9c49285c7227a64dbfc24004 Mon Sep 17 00:00:00 2001 From: Dxsk <43427519+dxsk@users.noreply.github.com> Date: Fri, 12 Jun 2026 00:31:06 +0200 Subject: [PATCH 3/7] feat(exegol): deploy scan-/audit- scripts + workspace dirs deploy.sh now copies scan-* and audit-* alongside recon-*; new engagement tree gets recon/screenshots and scans/code. --- exegol/my-resources/deploy.sh | 8 +++++--- lib/engagement.sh | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/exegol/my-resources/deploy.sh b/exegol/my-resources/deploy.sh index af35271..18381ad 100755 --- a/exegol/my-resources/deploy.sh +++ b/exegol/my-resources/deploy.sh @@ -22,9 +22,11 @@ merge_block() { } mkdir -p "${DEST}/bin" -if compgen -G "${SRC}/bin/recon-*" >/dev/null; then - cp "${SRC}/bin/"recon-* "${DEST}/bin/" -fi +for prefix in recon- scan- audit-; do + if compgen -G "${SRC}/bin/${prefix}*" >/dev/null; then + cp "${SRC}/bin/${prefix}"* "${DEST}/bin/" + fi +done [[ -f "${SRC}/bin/dl" ]] && cp "${SRC}/bin/dl" "${DEST}/bin/" chmod +x "${DEST}/bin/"* 2>/dev/null || true diff --git a/lib/engagement.sh b/lib/engagement.sh index 2232ea4..f53c52a 100644 --- a/lib/engagement.sh +++ b/lib/engagement.sh @@ -55,7 +55,7 @@ cmd_new() { # 1. Workspace structure (code/ = white-box / source-map / JS audit zone) printf '%b\n' " ${DIM}[1/8]${RESET} ${DIM}Creating workspace...${RESET}" - mkdir -p "${ws}"/{recon/{passive,active},scans/{ports,web,vuln},code/{recovered,sources,sourcemaps,js,beautified},exploits/{pocs,payloads},loot/{credentials,data},logs,report/assets,replays/{recon,scan,exploit,post,report,monitor},keys} + mkdir -p "${ws}"/{recon/{passive,active,screenshots},scans/{ports,web,vuln,code},code/{recovered,sources,sourcemaps,js,beautified},exploits/{pocs,payloads},loot/{credentials,data},logs,report/assets,replays/{recon,scan,exploit,post,report,monitor},keys} # Default ACLs so files the root Exegol/proxy containers create in the # workspace stay editable from the host (your user keeps rwx by inheritance). if command -v setfacl >/dev/null 2>&1; then From 64fe99f35c3babb82f3229b2bb4800fcbdfc0406 Mon Sep 17 00:00:00 2001 From: Dxsk <43427519+dxsk@users.noreply.github.com> Date: Fri, 12 Jun 2026 00:31:06 +0200 Subject: [PATCH 4/7] feat(exegol): idempotent installer for missing recon/scan/audit tools load_user_setup installs what the base image lacks (xnLinkFinder, waymore, sourcemapper, urlfinder, subzy, osv-scanner) onto PATH. Best-effort: go tools skip cleanly when the toolchain is too old, covered by script fallbacks. --- .../fragments/load_user_setup.dotsec.sh | 76 +++++++++++++++---- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/exegol/my-resources/fragments/load_user_setup.dotsec.sh b/exegol/my-resources/fragments/load_user_setup.dotsec.sh index 08a3b35..5478ef9 100644 --- a/exegol/my-resources/fragments/load_user_setup.dotsec.sh +++ b/exegol/my-resources/fragments/load_user_setup.dotsec.sh @@ -1,15 +1,63 @@ # shellcheck shell=bash -# dotsec recon tooling — runs on first container start. Idempotent. -if ! command -v uv >/dev/null 2>&1; then - curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR=/usr/local/bin sh -fi -if ! command -v pnpm >/dev/null 2>&1; then - npm install -g pnpm 2>/dev/null || true -fi -if ! command -v unwebpack-sourcemap >/dev/null 2>&1; then - npm install -g unwebpack-sourcemap 2>/dev/null || true -fi -# url/endpoint harvesting helpers (ProjectDiscovery + LinkFinder are already in Exegol) -if ! command -v waybackurls >/dev/null 2>&1; then - go install github.com/tomnomnom/waybackurls@latest 2>/dev/null || true -fi +# dotsec offensive tooling installer — runs on first container start and on +# `dotsec exegol setup`. Idempotent and best-effort: a single failed install +# never aborts the container build. Tools already shipped by the Exegol image +# (subfinder/httpx/katana/naabu/nuclei/gowitness/ffuf/gau/semgrep/trufflehog/ +# gitleaks) are NOT reinstalled — only what the dotsec scripts need on top. +# +# go install writes to an asdf-managed GOPATH that is NOT on PATH, so binaries +# are forced into /usr/local/bin (on PATH, writable). go tools are best-effort: +# many now require go >= 1.23 while the base image may ship 1.22 — if the build +# fails the script falls back (scan-takeover→nuclei, sourcemaps→unwebpack, …). +_dotsec_gobin="/usr/local/bin" + +_dotsec_have() { command -v "$1" >/dev/null 2>&1; } + +_dotsec_pipx() { # _dotsec_pipx + _dotsec_have "$1" && return 0 + pipx install "$2" >/dev/null 2>&1 || true +} + +_dotsec_go() { # _dotsec_go (best-effort) + _dotsec_have "$1" && return 0 + GOBIN="$_dotsec_gobin" go install "$2" >/dev/null 2>&1 || true +} + +_dotsec_release() { # _dotsec_release + _dotsec_have "$1" && return 0 + local url + case "$(uname -m)" in + x86_64 | amd64) url="$2" ;; + aarch64 | arm64) url="$3" ;; + *) return 0 ;; + esac + if curl -fsSL "$url" -o "${_dotsec_gobin}/$1" 2>/dev/null; then + chmod +x "${_dotsec_gobin}/$1" 2>/dev/null || true + fi +} + +echo "[dotsec] provisioning recon/scan/audit tooling (idempotent)…" + +# ── base runtimes ─────────────────────────────────────── +_dotsec_have uv || curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR=/usr/local/bin sh +_dotsec_have pnpm || npm install -g pnpm >/dev/null 2>&1 || true + +# ── recon: JS endpoint extraction + sourcemap reconstruction ── +_dotsec_pipx xnLinkFinder xnLinkFinder +_dotsec_have unwebpack-sourcemap || npm install -g unwebpack-sourcemap >/dev/null 2>&1 || true +_dotsec_go sourcemapper github.com/denandz/sourcemapper@latest + +# ── recon: passive URL aggregation (recon-urls) ───────── +_dotsec_go waybackurls github.com/tomnomnom/waybackurls@latest +_dotsec_pipx waymore waymore +_dotsec_go urlfinder github.com/projectdiscovery/urlfinder/cmd/urlfinder@latest + +# ── scan: subdomain takeover (bonus — scan-takeover falls back to nuclei) ── +_dotsec_go subzy github.com/PentestPad/subzy@latest + +# ── code audit: SCA (audit-code; semgrep/trufflehog/gitleaks ship with Exegol) ── +_dotsec_release osv-scanner \ + https://github.com/google/osv-scanner/releases/latest/download/osv-scanner_linux_amd64 \ + https://github.com/google/osv-scanner/releases/latest/download/osv-scanner_linux_arm64 + +echo "[dotsec] tooling ready (go-built extras skipped if go < 1.23 — covered by fallbacks)." From 3115eb1145d15b5e563f643edd7b7e18b559f34e Mon Sep 17 00:00:00 2001 From: Dxsk <43427519+dxsk@users.noreply.github.com> Date: Fri, 12 Jun 2026 00:31:06 +0200 Subject: [PATCH 5/7] feat(exegol): shortcuts + history for scan/audit; rename httpx-toolkit --- exegol/my-resources/fragments/aliases.dotsec | 9 ++++++++- exegol/my-resources/fragments/history.dotsec | 9 +++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/exegol/my-resources/fragments/aliases.dotsec b/exegol/my-resources/fragments/aliases.dotsec index 2327419..cb4621a 100644 --- a/exegol/my-resources/fragments/aliases.dotsec +++ b/exegol/my-resources/fragments/aliases.dotsec @@ -1,5 +1,12 @@ # dotsec recon aliases (env-driven: needs $DOMAIN / an engagement loaded) alias dl='source /opt/my-resources/bin/dl' alias subs='subfinder -d "$DOMAIN" -all -recursive' -alias alive='httpx-toolkit -mc 200 -ports 443,80,8080,8000,8888 -threads 200' +alias alive='httpx -mc 200 -ports 443,80,8080,8000,8888 -threads 200' alias crawl='katana -d 5 -jc -kf -ps -pss waybackarchive,commoncrawl,alienvault' + +# dotsec phase shortcuts (each wraps a /opt/my-resources/bin script) +alias portscan='recon-portscan' +alias shots='recon-screenshot' +alias scan='scan-nuclei' +alias takeover='scan-takeover' +alias audit='audit-code' diff --git a/exegol/my-resources/fragments/history.dotsec b/exegol/my-resources/fragments/history.dotsec index 482f25f..9c4d41c 100644 --- a/exegol/my-resources/fragments/history.dotsec +++ b/exegol/my-resources/fragments/history.dotsec @@ -1,12 +1,17 @@ : 0:0;subfinder -d $DOMAIN -all -recursive > subdomains.txt -: 0:0;cat subdomains.txt | httpx-toolkit -mc 200 -l subdomains.txt -ports 443,80,8080,8000,8888 -threads 200 > subdomains_alive.txt +: 0:0;cat subdomains.txt | httpx -mc 200 -l subdomains.txt -ports 443,80,8080,8000,8888 -threads 200 > subdomains_alive.txt : 0:0;katana -u subdomains_alive.txt -d 5 -ps -pss waybackarchive,commoncrawl,alienvault -kf -jc -ef woff,css,png,svg,jpg,woff2,jpeg,gif -o allurls.txt : 0:0;cat allurls.txt | grep -E "\.js($|\?)" | sort -u > js.txt : 0:0;cat subdomains_alive.txt | gau > params.txt -: 0:0;cat js.txt | while read url; do python3 ~/tools/secretfinder/SecretFinder.py -i $url -o cli; done >> secrets.txt +: 0:0;xnLinkFinder -i js.txt -sf "$DOMAIN" -o endpoints.txt +: 0:0;trufflehog filesystem code/ --results=verified,unknown : 0:0;dirsearch -u https://$DOMAIN -e conf,config,bak,old,sql,json,js,zip,tar.gz : 0:0;feroxbuster -u https://$DOMAIN -w /usr/share/seclists/Discovery/Web-Content/big.txt -C 404,403,429,401,405,302,400,301 -t 50 : 0:0;nuclei -l subdomains_alive.txt -t ~/nuclei-templates/http/cves -severity critical,high,medium -c 100 : 0:0;ffuf -w /usr/share/seclists/Discovery/Web-Content/big.txt -u https://$DOMAIN/FUZZ -mc 200,403 -fs 0 : 0:0;sqlmap -u "https://$DOMAIN/?id=1" --level=5 --risk=3 -p id --dbs : 0:0;subzy run --targets subdomains.txt --concurrency 100 --hide_fails --verify_ssl +: 0:0;naabu -list subdomains_alive.txt -top-ports 1000 -silent +: 0:0;gowitness scan file -f subdomains_alive.txt --screenshot-path recon/screenshots --write-none +: 0:0;osv-scanner scan --recursive code/ +: 0:0;semgrep --config auto code/ From e0e1f5b580c2e87cba101db600f9da50e0f93a6b Mon Sep 17 00:00:00 2001 From: Dxsk <43427519+dxsk@users.noreply.github.com> Date: Fri, 12 Jun 2026 00:31:06 +0200 Subject: [PATCH 6/7] chore(ci): shellcheck the attack scripts + document scan/audit stages Extend pre-commit + make lint to exegol/my-resources/bin and deploy.sh (these escaped linting, which let the httpx-toolkit regression through). README documents the scan/audit stages and the installer. --- .pre-commit-config.yaml | 2 +- Makefile | 2 +- README.md | 14 ++++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 133d6c4..77ceb26 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: name: shellcheck entry: shellcheck -x language: system - files: '^(bin/dotsec|bin/dotsec-build|lib/.*\.sh|tests/integration-smoke\.sh|tests/stubs/.*|\.github/scripts/.*\.sh)$' + files: '^(bin/dotsec|bin/dotsec-build|lib/.*\.sh|tests/integration-smoke\.sh|tests/stubs/.*|\.github/scripts/.*\.sh|exegol/my-resources/bin/[^/]+|exegol/my-resources/deploy\.sh)$' - id: bats name: bats entry: bats tests/ diff --git a/Makefile b/Makefile index 5fd035f..199eb88 100644 --- a/Makefile +++ b/Makefile @@ -131,7 +131,7 @@ test: ## Run bats tests @bats tests/ lint: ## shellcheck all bash (uses .shellcheckrc) - @shellcheck -x bin/dotsec bin/dotsec-build lib/*.sh tests/integration-smoke.sh && echo "[+] shellcheck clean" + @shellcheck -x bin/dotsec bin/dotsec-build lib/*.sh tests/integration-smoke.sh exegol/my-resources/bin/* exegol/my-resources/deploy.sh && echo "[+] shellcheck clean" smoke: ## Docker integration smoke (requires docker + make build) @bash tests/integration-smoke.sh diff --git a/README.md b/README.md index 8759be4..fe8d14b 100644 --- a/README.md +++ b/README.md @@ -130,22 +130,28 @@ The project ships a `my-resources` bundle deployed (merged) to `~/.exegol/my-res via `make exegol-setup` (also run by `make install`). The bundle includes: -- **bin/** scripts: `recon-subs`, `recon-alive`, `recon-crawl`, `recon-loot`, `recon-sourcemaps`, `recon-full`, `dl` +- **recon** scripts: `recon-subs`, `recon-alive`, `recon-fingerprint`, `recon-portscan`, `recon-screenshot`, `recon-crawl`, `recon-urls`, `recon-loot`, `recon-extract`, `recon-sourcemaps`, `recon-full`, `dl` +- **scan** scripts: `scan-nuclei` (vuln scan), `scan-takeover` (dangling CNAME; subzy → nuclei fallback) +- **audit** scripts: `audit-code` (trufflehog + gitleaks + semgrep + osv-scanner over the `code/` zone) - Shell aliases and preloaded history +- `load_user_setup.sh`: idempotent installer for the tools the scripts need that the base image lacks (xnLinkFinder, waymore, sourcemapper, osv-scanner, …) ```bash make exegol-setup # deploy/merge bundle to ~/.exegol/my-resources/ ``` Scripts run **inside** the Exegol container, driven by engagement env vars (`$DOMAIN`, `$WORKSPACE`). -Example in a loaded engagement window: +Typical flow in a loaded engagement window: ```bash -recon-full +recon-full # discovery → portscan → screenshots → crawl → loot → JS extract +scan-nuclei # vulnerability scan of the alive hosts (routed through the proxy) +scan-takeover # subdomain takeover check +audit-code # white-box audit of recovered source / sourcemaps ``` On first container start, Exegol auto-runs `/opt/my-resources/setup/load_user_setup.sh`. -To trigger it manually: +To trigger it manually (also installs missing tooling): ```bash dotsec exegol setup From f24e0eb7020a183ded0b2346323bbad82c2fc81e Mon Sep 17 00:00:00 2001 From: Dxsk <43427519+dxsk@users.noreply.github.com> Date: Fri, 12 Jun 2026 00:49:07 +0200 Subject: [PATCH 7/7] fix(scan): make new stage scripts executable (100755) --- exegol/my-resources/bin/audit-code | 0 exegol/my-resources/bin/recon-portscan | 0 exegol/my-resources/bin/recon-screenshot | 0 exegol/my-resources/bin/scan-nuclei | 0 exegol/my-resources/bin/scan-takeover | 0 5 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 exegol/my-resources/bin/audit-code mode change 100644 => 100755 exegol/my-resources/bin/recon-portscan mode change 100644 => 100755 exegol/my-resources/bin/recon-screenshot mode change 100644 => 100755 exegol/my-resources/bin/scan-nuclei mode change 100644 => 100755 exegol/my-resources/bin/scan-takeover diff --git a/exegol/my-resources/bin/audit-code b/exegol/my-resources/bin/audit-code old mode 100644 new mode 100755 diff --git a/exegol/my-resources/bin/recon-portscan b/exegol/my-resources/bin/recon-portscan old mode 100644 new mode 100755 diff --git a/exegol/my-resources/bin/recon-screenshot b/exegol/my-resources/bin/recon-screenshot old mode 100644 new mode 100755 diff --git a/exegol/my-resources/bin/scan-nuclei b/exegol/my-resources/bin/scan-nuclei old mode 100644 new mode 100755 diff --git a/exegol/my-resources/bin/scan-takeover b/exegol/my-resources/bin/scan-takeover old mode 100644 new mode 100755