Last active
August 25, 2025 22:14
-
-
Save namishelex01/fee1214458f610b0e291bb42c1271b71 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# bb-min-setup.sh — Minimal bug bounty setup for Raspberry Pi 5 (Raspberry Pi OS 64‑bit, ARM64) | |
# Focus: web app recon + vuln discovery ONLY (no pentest/forensics/heavy stuff). | |
# PEP 668 safe (pipx / per-tool venvs). Prefers official linux_arm64 binaries to avoid Go-compat hiccups. | |
# Idempotent: safe to re-run. | |
set -euo pipefail | |
if [[ $EUID -eq 0 ]]; then | |
echo "Run as a normal user (will sudo as needed), not root." >&2 | |
exit 1 | |
fi | |
log() { printf "\n==> %s\n" "$*"; } | |
apt_i(){ sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends "$@"; } | |
ensure_line(){ local L="$1" F="$2"; grep -qxF "$L" "$F" 2>/dev/null || echo "$L" >> "$F"; } | |
SHELL_RC="$HOME/.bashrc" | |
TOOLS="$HOME/tools" | |
BIN="$HOME/.local/bin" | |
VENVS="$HOME/venvs" | |
mkdir -p "$TOOLS" "$BIN" "$VENVS" "$HOME/wordlists" | |
log "System update + tiny base deps" | |
sudo apt-get update -y | |
sudo apt-get -y full-upgrade | |
apt_i git curl wget ca-certificates jq unzip tar xz-utils \ | |
build-essential pkg-config \ | |
python3 python3-venv python3-pip pipx \ | |
golang ripgrep | |
# PATHs | |
ensure_line 'export GOPATH="$HOME/go"' "$SHELL_RC" | |
ensure_line 'export PATH="$PATH:$HOME/go/bin:$HOME/.local/bin"' "$SHELL_RC" | |
export GOPATH="$HOME/go" | |
export PATH="$PATH:$HOME/go/bin:$BIN" | |
# pipx path (PEP 668 friendly) | |
python3 -m pipx ensurepath 2>/dev/null || true | |
export PATH="$HOME/.local/bin:$PATH" | |
# --- Helpers --------------------------------------------------------------- | |
# Install a GitHub release asset that matches a pattern and place the binary at $BIN/<dst> | |
install_from_release() { | |
# owner repo dst_name pattern | |
local owner="$1" repo="$2" dst="$3" pattern="$4" | |
local api="https://api.github.com/repos/$owner/$repo/releases/latest" | |
local tag asset_url name tmp | |
tag="$(curl -fsSL "$api" | jq -r .tag_name)" | |
if [[ -z "$tag" || "$tag" == "null" ]]; then | |
echo " [!] Could not determine latest tag for $owner/$repo" >&2 | |
return 1 | |
fi | |
asset_url="$(curl -fsSL "https://api.github.com/repos/$owner/$repo/releases/tags/$tag" \ | |
| jq -r --arg pat "$pattern" '.assets[] | select(.name|test($pat)) | .browser_download_url' | head -n1)" | |
if [[ -z "$asset_url" ]]; then | |
echo " [!] No asset matched '$pattern' for $owner/$repo@$tag" >&2 | |
return 1 | |
fi | |
tmp="$(mktemp -d)" | |
curl -fsSL "$asset_url" -o "$tmp/asset" | |
# Detect archive type; extract and find the binary | |
if file "$tmp/asset" | grep -qi 'gzip compressed data'; then | |
tar -xzf "$tmp/asset" -C "$tmp" | |
elif file "$tmp/asset" | grep -qi 'Zip archive data'; then | |
unzip -q "$tmp/asset" -d "$tmp" | |
else | |
# maybe it's a raw binary | |
mv "$tmp/asset" "$tmp/$dst" | |
fi | |
# Find candidate binary in extracted dir | |
local binpath | |
binpath="$(find "$tmp" -maxdepth 2 -type f -name "$dst" -o -name "$dst-linux" 2>/dev/null | head -n1)" | |
if [[ -z "$binpath" ]]; then | |
# some projects ship as <name>_linux_arm64 or similar | |
binpath="$(find "$tmp" -maxdepth 2 -type f -perm -111 | grep -E "/$dst(_linux.*|)$" || true)" | |
fi | |
if [[ -z "$binpath" ]]; then | |
echo " [!] Could not locate $dst inside release asset for $owner/$repo" >&2 | |
rm -rf "$tmp"; return 1 | |
fi | |
install -m 0755 "$binpath" "$BIN/$dst" | |
rm -rf "$tmp" | |
echo " [+] Installed $dst -> $BIN/$dst" | |
} | |
# Minimal Go version compare (returns 0 if have >= need) | |
go_meets() { | |
local need="$1" | |
local have | |
have="$(go version 2>/dev/null | awk '{print $3}' | sed 's/go//')" | |
[[ -z "$have" ]] && return 1 | |
printf '%s\n' "$need" "$have" | sort -V | tail -n1 | grep -qx "$have" | |
} | |
# Install a tool: prefer GitHub linux_arm64 binary; if unavailable, try `go install` | |
install_tool_bin_first() { | |
# owner repo bin_name pattern go_pkg | |
local owner="$1" repo="$2" binname="$3" pattern="$4" gopkg="$5" | |
if command -v "$binname" >/dev/null 2>&1; then | |
echo " [-] $binname already installed" | |
return 0 | |
fi | |
echo " [*] Trying binary install for $binname..." | |
if install_from_release "$owner" "$repo" "$binname" "$pattern"; then | |
return 0 | |
fi | |
if [[ -n "$gopkg" ]]; then | |
echo " [*] Fallback to go install: $gopkg" | |
go install -v "$gopkg" || { | |
echo " [!] Failed to install $binname via go. Skipping." >&2 | |
return 1 | |
} | |
fi | |
} | |
# Helper to install a repo tool into its own venv and add a wrapper | |
mkpytool () { | |
local name="$1" repo="$2" entry="$3" | |
local root="$VENVS/$name" | |
if ! command -v "$name" >/dev/null 2>&1; then | |
log "Installing $name (venv)" | |
if [[ ! -d "$root" ]]; then | |
python3 -m venv "$root" | |
"$root/bin/pip" install --upgrade pip wheel setuptools >/dev/null | |
git -C "$TOOLS" clone --depth=1 "$repo" "$TOOLS/$name" | |
if [[ -f "$TOOLS/$name/requirements.txt" ]]; then | |
"$root/bin/pip" install -r "$TOOLS/$name/requirements.txt" >/dev/null | |
fi | |
cat > "$BIN/$name" <<EOF | |
#!/usr/bin/env bash | |
exec "$root/bin/python" "$TOOLS/$name/$entry" "\$@" | |
EOF | |
chmod +x "$BIN/$name" | |
fi | |
fi | |
} | |
# --- Core installs --------------------------------------------------------- | |
log "Installing core *binary-first* tools (ARM64 releases where possible)" | |
# Per your request: ALWAYS binary for subfinder (no Go build to avoid v2.8.0 Go>=1.24 issue) | |
install_from_release "projectdiscovery" "subfinder" "subfinder" 'linux_arm64\.(tar\.gz|zip)$' || { | |
echo "[!] Subfinder binary install failed." >&2; exit 1; | |
} | |
# ProjectDiscovery: try binaries first, then `go install` fallback | |
install_tool_bin_first "projectdiscovery" "httpx" "httpx" 'linux_arm64\.(tar\.gz|zip)$' "github.com/projectdiscovery/httpx/cmd/httpx@latest" | |
install_tool_bin_first "projectdiscovery" "naabu" "naabu" 'linux_arm64\.(tar\.gz|zip)$' "github.com/projectdiscovery/naabu/v2/cmd/naabu@latest" | |
install_tool_bin_first "projectdiscovery" "katana" "katana" 'linux_arm64\.(tar\.gz|zip)$' "github.com/projectdiscovery/katana/cmd/katana@latest" | |
install_tool_bin_first "projectdiscovery" "nuclei" "nuclei" 'linux_arm64\.(tar\.gz|zip)$' "github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest" | |
# ffuf (binary-first) | |
install_tool_bin_first "ffuf" "ffuf" "ffuf" 'linux_arm64\.(tar\.gz|zip)$' "github.com/ffuf/ffuf/v2@latest" | |
# gau (binary-first), repo: lc/gau (v2 has releases) | |
install_tool_bin_first "lc" "gau" "gau" 'linux_arm64\.(tar\.gz|zip)$' "github.com/lc/gau/v2/cmd/gau@latest" | |
# dalfox (binary-first) | |
install_tool_bin_first "hahwul" "dalfox" "dalfox" 'linux_arm64\.(tar\.gz|zip)$' "github.com/hahwul/dalfox/v2@latest" | |
# Tools that usually compile fine against older Go (source-first) | |
# If you hit version issues later, we can swap to binary patterns or pin versions. | |
go install github.com/tomnomnom/waybackurls@latest || true | |
go install github.com/tomnomnom/anew@latest || true | |
go install github.com/tomnomnom/qsreplace@latest || true | |
# subzy (binary-first if available; otherwise go) | |
install_tool_bin_first "LukaSikic" "subzy" "subzy" 'linux_arm64\.(tar\.gz|zip)$' "github.com/LukaSikic/subzy@latest" | |
# kxss (source-first; small tool) | |
go install github.com/Emoe/kxss@latest || true | |
log "Installing minimal Python CLI tools with pipx (isolated)" | |
pipx install arjun >/dev/null 2>&1 || true | |
pipx install uro >/dev/null 2>&1 || true | |
pipx install dirsearch >/dev/null 2>&1 || true | |
log "Installing small repo-based helpers into their own venvs" | |
mkpytool "secretfinder" "https://github.com/m4ll0k/SecretFinder.git" "SecretFinder.py" | |
mkpytool "corsy" "https://github.com/s0md3v/Corsy.git" "corsy.py" | |
log "Nuclei templates" | |
nuclei -update-templates || true | |
log "Installing sqlmap via apt" | |
apt_i sqlmap | |
log "Fetching lean wordlists (avoid full SecLists to stay small)" | |
if [[ ! -f "$HOME/wordlists/raft-small-directories.txt" ]]; then | |
curl -fsSL -o "$HOME/wordlists/raft-small-directories.txt" \ | |
https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/raft-small-directories.txt | |
fi | |
if [[ ! -f "$HOME/wordlists/common.txt" ]]; then | |
curl -fsSL -o "$HOME/wordlists/common.txt" \ | |
https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/common.txt | |
fi | |
if [[ ! -f "$HOME/wordlists/params-small.txt" ]]; then | |
curl -fsSL -o "$HOME/wordlists/params-small.txt" \ | |
https://raw.githubusercontent.com/assetnote/wordlists/master/data/parameters/minimal-params.txt | |
fi | |
log "Creating tiny workflow wrappers in ~/.local/bin" | |
cat > "$BIN/bb-subenum" <<'EOF' | |
#!/usr/bin/env bash | |
# Usage: bb-subenum example.com > subs.txt | |
set -euo pipefail | |
domain="${1:?domain required}" | |
subfinder -silent -all -d "$domain" | anew | |
EOF | |
chmod +x "$BIN/bb-subenum" | |
cat > "$BIN/bb-probe" <<'EOF' | |
#!/usr/bin/env bash | |
# Usage: cat subs.txt | bb-probe > hosts.json | |
set -euo pipefail | |
httpx -silent -follow-redirects -status-code -title -tech-detect -json | |
EOF | |
chmod +x "$BIN/bb-probe" | |
cat > "$BIN/bb-crawl" <<'EOF' | |
#!/usr/bin/env bash | |
# Usage: jq -r '.[].url' hosts.json | bb-crawl > urls.txt | |
set -euo pipefail | |
katana -silent -jc -fx -ef woff,woff2,png,jpg,jpeg,gif,svg,ttf -ps -kf | |
EOF | |
chmod +x "$BIN/bb-crawl" | |
cat > "$BIN/bb-urls" <<'EOF' | |
#!/usr/bin/env bash | |
# Usage: echo example.com | bb-urls > allurls.txt | |
set -euo pipefail | |
gau -subs | anew | uro | |
EOF | |
chmod +x "$BIN/bb-urls" | |
cat > "$BIN/bb-nuclei" <<'EOF' | |
#!/usr/bin/env bash | |
# Usage: jq -r '.[].url' hosts.json | bb-nuclei | |
set -euo pipefail | |
nuclei -silent -rl 50 -c 50 -severity low,medium,high,critical | |
EOF | |
chmod +x "$BIN/bb-nuclei" | |
cat > "$BIN/bb-xss" <<'EOF' | |
#!/usr/bin/env bash | |
# Usage: cat urls.txt | bb-xss | |
set -euo pipefail | |
rg -N 'https?://.*\?.*=.*' -o | anew | dalfox pipe --silence --skip-bav -o dalfox-results.txt | |
echo "dalfox-results.txt written." | |
EOF | |
chmod +x "$BIN/bb-xss" | |
cat > "$BIN/bb-dirs" <<'EOF' | |
#!/usr/bin/env bash | |
# Usage: bb-dirs https://target.tld [wordlist] | |
set -euo pipefail | |
url="${1:?URL required}" | |
wordlist="${2:-$HOME/wordlists/raft-small-directories.txt}" | |
ffuf -u "$url/FUZZ" -w "$wordlist" -mc 200,204,301,302,307,401,403 -fs 0 | |
EOF | |
chmod +x "$BIN/bb-dirs" | |
cat > "$BIN/bb-params" <<'EOF' | |
#!/usr/bin/env bash | |
# Usage: bb-params https://target.tld | |
set -euo pipefail | |
url="${1:?Base URL required}" | |
arjun -u "$url" -w "$HOME/wordlists/params-small.txt" -oT - | |
EOF | |
chmod +x "$BIN/bb-params" | |
log "Shell quality-of-life" | |
ensure_line 'alias ll="ls -alF"' "$SHELL_RC" | |
ensure_line '# Bug bounty GOPATH and local bin' "$SHELL_RC" | |
ensure_line 'export PATH="$PATH:$HOME/go/bin:$HOME/.local/bin"' "$SHELL_RC" | |
log "Health check (quick versions)" | |
check_bin () { printf "%-12s: " "$1"; if command -v "$1" >/dev/null 2>&1; then "$1" -version 2>/dev/null | head -n1 || echo "installed"; else echo "missing"; fi; } | |
for b in subfinder httpx naabu katana nuclei ffuf gau waybackurls anew subzy qsreplace dalfox kxss sqlmap dirsearch arjun secretfinder corsy; do | |
check_bin "$b" || true | |
done | |
echo | |
log "Done. Open a new shell or 'source ~/.bashrc' to refresh PATH." | |
echo "Wordlists: $HOME/wordlists" | |
echo "Tools: $TOOLS" | |
echo "Wrappers: $BIN" | |
echo "Tip: run 'nuclei -update-templates' occasionally." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment