Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist, same-site referer bypass, Blackbox-Exporter allowed bot, and all new exporters, cheat sheets, and automation scripts.
This commit is contained in:
@@ -0,0 +1,354 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#########################################################################################
|
||||
#### file-permissions-audit.sh — Find world-writable files, SUID/SGID binaries, ####
|
||||
#### and files owned by nobody or with no valid owner ####
|
||||
#### ####
|
||||
#### Author: Phil Connor ####
|
||||
#### Contact: contact@mylinux.work ####
|
||||
#### License: MIT ####
|
||||
#### Version 1.00 ####
|
||||
#### ####
|
||||
#### Usage: ####
|
||||
#### ./file-permissions-audit.sh ####
|
||||
#### ./file-permissions-audit.sh --scan-dirs /usr /bin /home ####
|
||||
#### ####
|
||||
#### See --help for all options. ####
|
||||
#########################################################################################
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ── Defaults ──────────────────────────────────────────────────────────
|
||||
SCAN_DIRS="${SCAN_DIRS:-/usr /bin /sbin /var /opt /home /tmp}"
|
||||
EXCLUDE_PATHS=()
|
||||
VERBOSE="${VERBOSE:-false}"
|
||||
COLOR="${COLOR:-auto}"
|
||||
|
||||
# ── State ─────────────────────────────────────────────────────────────
|
||||
SCRIPT_NAME="$(basename "$0")"
|
||||
readonly SCRIPT_NAME
|
||||
COUNT_WORLD_WRITABLE=0
|
||||
COUNT_SUID=0
|
||||
COUNT_SGID=0
|
||||
COUNT_NOBODY=0
|
||||
COUNT_UNOWNED=0
|
||||
|
||||
# ── Colors ────────────────────────────────────────────────────────────
|
||||
setup_colors() {
|
||||
if [[ "$COLOR" == "never" ]]; then
|
||||
RED="" YELLOW="" CYAN="" BOLD="" DIM="" RESET=""
|
||||
return
|
||||
fi
|
||||
if [[ "$COLOR" == "always" ]] || [[ -t 1 ]]; then
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[0;33m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
DIM='\033[2m'
|
||||
RESET='\033[0m'
|
||||
else
|
||||
RED="" YELLOW="" CYAN="" BOLD="" DIM="" RESET=""
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Logging ───────────────────────────────────────────────────────────
|
||||
log() { echo -e "${CYAN}[INFO]${RESET} $*"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${RESET} $*" >&2; }
|
||||
err() { echo -e "${RED}[ERROR]${RESET} $*" >&2; }
|
||||
verbose() { if [[ "$VERBOSE" == "true" ]]; then echo -e "${DIM}[DEBUG]${RESET} $*"; fi; }
|
||||
|
||||
# ── Helpers ───────────────────────────────────────────────────────────
|
||||
section_header() {
|
||||
echo ""
|
||||
echo -e " ${BOLD}${CYAN}── $1 ──${RESET}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
build_exclude_args() {
|
||||
local args=()
|
||||
for path in "${EXCLUDE_PATHS[@]+"${EXCLUDE_PATHS[@]}"}"; do
|
||||
args+=(-not -path "${path}/*")
|
||||
done
|
||||
# Always exclude /proc and /sys
|
||||
args+=(-not -path "/proc/*" -not -path "/sys/*")
|
||||
echo "${args[@]}"
|
||||
}
|
||||
|
||||
get_file_info() {
|
||||
local file="$1"
|
||||
local octal symbolic owner group ftype
|
||||
|
||||
octal=$(stat -c '%a' "$file" 2>/dev/null || echo "????")
|
||||
symbolic=$(stat -c '%A' "$file" 2>/dev/null || echo "??????????")
|
||||
owner=$(stat -c '%U' "$file" 2>/dev/null || echo "UNKNOWN")
|
||||
group=$(stat -c '%G' "$file" 2>/dev/null || echo "UNKNOWN")
|
||||
|
||||
if [[ -d "$file" ]]; then
|
||||
ftype="dir"
|
||||
elif [[ -L "$file" ]]; then
|
||||
ftype="link"
|
||||
else
|
||||
ftype="file"
|
||||
fi
|
||||
|
||||
echo "${octal} ${symbolic} ${owner}:${group} ${ftype}"
|
||||
}
|
||||
|
||||
print_file_entry() {
|
||||
local color="$1"
|
||||
local file="$2"
|
||||
local info
|
||||
info=$(get_file_info "$file")
|
||||
local octal symbolic ownership ftype
|
||||
octal=$(echo "$info" | awk '{print $1}')
|
||||
symbolic=$(echo "$info" | awk '{print $2}')
|
||||
ownership=$(echo "$info" | awk '{print $3}')
|
||||
ftype=$(echo "$info" | awk '{print $4}')
|
||||
|
||||
printf " %b%-4s %-11s %-20s %-6s%b %s\n" "$color" "$octal" "$symbolic" "$ownership" "$ftype" "$RESET" "$file"
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# SCAN FUNCTIONS
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
scan_world_writable() {
|
||||
section_header "World-Writable Files & Directories"
|
||||
|
||||
printf " ${BOLD}%-4s %-11s %-20s %-6s${RESET} %s\n" "PERM" "MODE" "OWNER:GROUP" "TYPE" "PATH"
|
||||
printf " %s\n" "$(printf '%.0s─' {1..78})"
|
||||
|
||||
local count=0
|
||||
local exclude_args
|
||||
exclude_args=$(build_exclude_args)
|
||||
|
||||
for dir in $SCAN_DIRS; do
|
||||
[[ -d "$dir" ]] || continue
|
||||
# shellcheck disable=SC2086
|
||||
while IFS= read -r file; do
|
||||
[[ -z "$file" ]] && continue
|
||||
print_file_entry "$CYAN" "$file"
|
||||
count=$((count + 1))
|
||||
done < <(find "$dir" -xdev -perm -0002 -not -type l $exclude_args 2>/dev/null)
|
||||
done
|
||||
|
||||
COUNT_WORLD_WRITABLE=$count
|
||||
echo ""
|
||||
log "Found ${count} world-writable entries"
|
||||
}
|
||||
|
||||
scan_suid() {
|
||||
section_header "SUID Binaries"
|
||||
|
||||
printf " ${BOLD}%-4s %-11s %-20s %-6s${RESET} %s\n" "PERM" "MODE" "OWNER:GROUP" "TYPE" "PATH"
|
||||
printf " %s\n" "$(printf '%.0s─' {1..78})"
|
||||
|
||||
local count=0
|
||||
local exclude_args
|
||||
exclude_args=$(build_exclude_args)
|
||||
|
||||
for dir in $SCAN_DIRS; do
|
||||
[[ -d "$dir" ]] || continue
|
||||
# shellcheck disable=SC2086
|
||||
while IFS= read -r file; do
|
||||
[[ -z "$file" ]] && continue
|
||||
local owner
|
||||
owner=$(stat -c '%U' "$file" 2>/dev/null || echo "UNKNOWN")
|
||||
local color="$YELLOW"
|
||||
if [[ "$owner" == "root" ]]; then
|
||||
color="$RED"
|
||||
fi
|
||||
print_file_entry "$color" "$file"
|
||||
count=$((count + 1))
|
||||
done < <(find "$dir" -xdev -type f -perm -4000 $exclude_args 2>/dev/null)
|
||||
done
|
||||
|
||||
COUNT_SUID=$count
|
||||
echo ""
|
||||
log "Found ${count} SUID binaries"
|
||||
}
|
||||
|
||||
scan_sgid() {
|
||||
section_header "SGID Binaries"
|
||||
|
||||
printf " ${BOLD}%-4s %-11s %-20s %-6s${RESET} %s\n" "PERM" "MODE" "OWNER:GROUP" "TYPE" "PATH"
|
||||
printf " %s\n" "$(printf '%.0s─' {1..78})"
|
||||
|
||||
local count=0
|
||||
local exclude_args
|
||||
exclude_args=$(build_exclude_args)
|
||||
|
||||
for dir in $SCAN_DIRS; do
|
||||
[[ -d "$dir" ]] || continue
|
||||
# shellcheck disable=SC2086
|
||||
while IFS= read -r file; do
|
||||
[[ -z "$file" ]] && continue
|
||||
print_file_entry "$YELLOW" "$file"
|
||||
count=$((count + 1))
|
||||
done < <(find "$dir" -xdev -type f -perm -2000 $exclude_args 2>/dev/null)
|
||||
done
|
||||
|
||||
COUNT_SGID=$count
|
||||
echo ""
|
||||
log "Found ${count} SGID binaries"
|
||||
}
|
||||
|
||||
scan_nobody() {
|
||||
section_header "Files Owned by nobody/nogroup"
|
||||
|
||||
printf " ${BOLD}%-4s %-11s %-20s %-6s${RESET} %s\n" "PERM" "MODE" "OWNER:GROUP" "TYPE" "PATH"
|
||||
printf " %s\n" "$(printf '%.0s─' {1..78})"
|
||||
|
||||
local count=0
|
||||
local exclude_args
|
||||
exclude_args=$(build_exclude_args)
|
||||
|
||||
for dir in $SCAN_DIRS; do
|
||||
[[ -d "$dir" ]] || continue
|
||||
# shellcheck disable=SC2086
|
||||
while IFS= read -r file; do
|
||||
[[ -z "$file" ]] && continue
|
||||
print_file_entry "$YELLOW" "$file"
|
||||
count=$((count + 1))
|
||||
done < <(find "$dir" -xdev \( -user nobody -o -group nogroup \) $exclude_args 2>/dev/null)
|
||||
done
|
||||
|
||||
COUNT_NOBODY=$count
|
||||
echo ""
|
||||
log "Found ${count} files owned by nobody/nogroup"
|
||||
}
|
||||
|
||||
scan_unowned() {
|
||||
section_header "Files With No Valid Owner"
|
||||
|
||||
printf " ${BOLD}%-4s %-11s %-20s %-6s${RESET} %s\n" "PERM" "MODE" "OWNER:GROUP" "TYPE" "PATH"
|
||||
printf " %s\n" "$(printf '%.0s─' {1..78})"
|
||||
|
||||
local count=0
|
||||
local exclude_args
|
||||
exclude_args=$(build_exclude_args)
|
||||
|
||||
for dir in $SCAN_DIRS; do
|
||||
[[ -d "$dir" ]] || continue
|
||||
# shellcheck disable=SC2086
|
||||
while IFS= read -r file; do
|
||||
[[ -z "$file" ]] && continue
|
||||
print_file_entry "$RED" "$file"
|
||||
count=$((count + 1))
|
||||
done < <(find "$dir" -xdev \( -nouser -o -nogroup \) $exclude_args 2>/dev/null)
|
||||
done
|
||||
|
||||
COUNT_UNOWNED=$count
|
||||
echo ""
|
||||
log "Found ${count} files with no valid owner"
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# SUMMARY
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
print_summary() {
|
||||
echo ""
|
||||
echo -e " ${BOLD}══════════════════════════════════════════${RESET}"
|
||||
echo -e " ${BOLD}Permissions Audit Summary${RESET}"
|
||||
echo -e " ${BOLD}══════════════════════════════════════════${RESET}"
|
||||
echo ""
|
||||
|
||||
printf " %-30s %b\n" "World-writable:" "${CYAN}${COUNT_WORLD_WRITABLE}${RESET}"
|
||||
printf " %-30s %b\n" "SUID binaries:" "${RED}${COUNT_SUID}${RESET}"
|
||||
printf " %-30s %b\n" "SGID binaries:" "${YELLOW}${COUNT_SGID}${RESET}"
|
||||
printf " %-30s %b\n" "Owned by nobody/nogroup:" "${YELLOW}${COUNT_NOBODY}${RESET}"
|
||||
printf " %-30s %b\n" "No valid owner:" "${RED}${COUNT_UNOWNED}${RESET}"
|
||||
|
||||
local total=$((COUNT_WORLD_WRITABLE + COUNT_SUID + COUNT_SGID + COUNT_NOBODY + COUNT_UNOWNED))
|
||||
echo ""
|
||||
printf " %-30s %d\n" "Total findings:" "$total"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# USAGE
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
${SCRIPT_NAME} — Audit file permissions for security issues
|
||||
|
||||
USAGE:
|
||||
${SCRIPT_NAME} [OPTIONS]
|
||||
|
||||
OPTIONS:
|
||||
--scan-dirs DIRS Space-separated directories to scan
|
||||
(default: /usr /bin /sbin /var /opt /home /tmp)
|
||||
--exclude-path PATH Exclude a path from scanning (repeatable)
|
||||
--verbose Enable debug output
|
||||
--no-color Disable colored output
|
||||
--help Show this help
|
||||
|
||||
ENVIRONMENT VARIABLES:
|
||||
SCAN_DIRS Directories to scan (default: /usr /bin /sbin /var /opt /home /tmp)
|
||||
|
||||
EXAMPLES:
|
||||
# Full audit with defaults
|
||||
./file-permissions-audit.sh
|
||||
|
||||
# Scan specific directories
|
||||
./file-permissions-audit.sh --scan-dirs "/usr /home /opt"
|
||||
|
||||
# Exclude paths
|
||||
./file-permissions-audit.sh --exclude-path /home/build --exclude-path /var/cache
|
||||
|
||||
# Pipe-friendly output
|
||||
./file-permissions-audit.sh --no-color | tee audit-report.txt
|
||||
EOF
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# ARGUMENT PARSING
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--scan-dirs)
|
||||
SCAN_DIRS="$2"; shift 2 ;;
|
||||
--exclude-path)
|
||||
EXCLUDE_PATHS+=("$2"); shift 2 ;;
|
||||
--verbose)
|
||||
VERBOSE="true"; shift ;;
|
||||
--no-color)
|
||||
COLOR="never"; shift ;;
|
||||
--help|-h)
|
||||
setup_colors
|
||||
usage
|
||||
exit 0 ;;
|
||||
*)
|
||||
err "Unknown option: $1"
|
||||
echo "Run ${SCRIPT_NAME} --help for usage" >&2
|
||||
exit 1 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# MAIN
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
setup_colors
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}File Permissions Audit — $(hostname -f 2>/dev/null || hostname)${RESET}"
|
||||
echo -e "${DIM}$(date '+%Y-%m-%d %H:%M:%S %Z')${RESET}"
|
||||
echo -e "${DIM}Scanning: ${SCAN_DIRS}${RESET}"
|
||||
|
||||
scan_world_writable
|
||||
scan_suid
|
||||
scan_sgid
|
||||
scan_nobody
|
||||
scan_unowned
|
||||
print_summary
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user