#!/bin/bash # 23 - Client-Side & JavaScript Security # Tests: clickjacking, content-type sniffing, CSP headers, CSRF token exposure, # prototype pollution via API, DOM XSS reflection vectors, SRI, service worker paths SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../config.sh" OUT_FILE="$OUT/23_client_side_js.txt" echo "=== 23. Client-Side & JavaScript Security ===" | tee "$OUT_FILE" echo "Target: $TARGET" | tee -a "$OUT_FILE" echo "" | tee -a "$OUT_FILE" W() { printf '%s' "$1" | python3 -c "import sys,urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip()))"; } do_test() { local label="$1"; shift local code code=$(curl -sk -o /dev/null -w '%{http_code}' "$@") printf '[%s] %s\n' "$code" "$label" | tee -a "$OUT_FILE" } do_test_headers() { local label="$1"; shift local out out=$(curl -sk -D - -o /dev/null "$@") local code=$(echo "$out" | head -1 | grep -oP '\d{3}' | head -1) printf '[%s] %s\n' "$code" "$label" | tee -a "$OUT_FILE" # Print security-relevant headers echo "$out" | grep -iE '^(x-frame-options|content-security-policy|x-content-type-options|cache-control|referrer-policy|permissions-policy|cross-origin|vary):' | sed 's/^/ /' | tee -a "$OUT_FILE" } # ── 1. Clickjacking / X-Frame-Options ───────────────────────────────────────── echo "--- Clickjacking / Framing Controls ---" | tee -a "$OUT_FILE" do_test_headers "Main page framing headers" -A "$BROWSER_UA" "$TARGET/" do_test_headers "Encrypt page framing headers" -A "$BROWSER_UA" "$TARGET/crypt.php" do_test_headers "Admin page framing headers" -A "$BROWSER_UA" "$TARGET/admin/" echo "" | tee -a "$OUT_FILE" # ── 2. Content-Type Sniffing (X-Content-Type-Options) ───────────────────────── echo "--- Content-Type Sniffing ---" | tee -a "$OUT_FILE" do_test_headers "Static JS asset headers" -A "$BROWSER_UA" "$TARGET/dist/assets/index.js" 2>/dev/null || \ do_test_headers "CSS asset headers" -A "$BROWSER_UA" "$TARGET/css/homepage.css" do_test_headers "API JSON response headers" -A "$BROWSER_UA" \ -H 'Content-Type: application/json' \ -d '{"test":"x"}' \ "$API_TARGET/status" echo "" | tee -a "$OUT_FILE" # ── 3. MIME-type confusion — serve JS as text/plain ─────────────────────────── echo "--- MIME Confusion / Content Sniffing Attack ---" | tee -a "$OUT_FILE" do_test "Script with Accept: text/plain (MIME sniff probe)" \ -A "$BROWSER_UA" -H "Accept: text/plain" "$TARGET/js/crypt.js" 2>/dev/null || \ do_test "CSS with Accept: text/plain" \ -A "$BROWSER_UA" -H "Accept: text/plain" "$TARGET/css/homepage.css" echo "" | tee -a "$OUT_FILE" # ── 4. Reflected parameter — DOM XSS reflection ─────────────────────────────── echo "--- DOM XSS / Reflected Parameter Vectors ---" | tee -a "$OUT_FILE" XSS_FRAG=$(W "") XSS_IMG=$(W "") XSS_SVG=$(W "") do_test "XSS via ?q= param" -A "$BROWSER_UA" "$TARGET/?q=$XSS_FRAG" do_test "XSS via ?redirect= param" -A "$BROWSER_UA" "$TARGET/?redirect=$XSS_FRAG" do_test "XSS via ?msg= param" -A "$BROWSER_UA" "$TARGET/?msg=$XSS_IMG" do_test "XSS via ?error= param" -A "$BROWSER_UA" "$TARGET/?error=$XSS_SVG" do_test "XSS via ?page= param" -A "$BROWSER_UA" "$TARGET/?page=$XSS_FRAG" do_test "XSS via ?url= param (possible open redirect)" -A "$BROWSER_UA" "$TARGET/?url=$(W 'javascript:alert(1)')" echo "" | tee -a "$OUT_FILE" # ── 5. Open Redirect ────────────────────────────────────────────────────────── echo "--- Open Redirect ---" | tee -a "$OUT_FILE" do_test "Open redirect ?next=//evil.com" -A "$BROWSER_UA" "$TARGET/?next=$(W '//evil.com')" do_test "Open redirect ?redirect=https://evil.com" -A "$BROWSER_UA" "$TARGET/?redirect=$(W 'https://evil.com')" do_test "Open redirect ?return_url=//evil.com" -A "$BROWSER_UA" "$TARGET/?return_url=$(W '//evil.com')" echo "" | tee -a "$OUT_FILE" # ── 6. Prototype Pollution via JSON API ─────────────────────────────────────── echo "--- Prototype Pollution (API JSON body) ---" | tee -a "$OUT_FILE" do_test "Prototype pollution __proto__" \ -A "$BROWSER_UA" -X POST -H 'Content-Type: application/json' \ -d '{"__proto__":{"isAdmin":true},"data":"test"}' \ "$API_TARGET/encrypt" do_test "Prototype pollution constructor.prototype" \ -A "$BROWSER_UA" -X POST -H 'Content-Type: application/json' \ -d '{"constructor":{"prototype":{"isAdmin":true}},"data":"test"}' \ "$API_TARGET/encrypt" do_test "Prototype pollution via nested __proto__" \ -A "$BROWSER_UA" -X POST -H 'Content-Type: application/json' \ -d '{"a":{"__proto__":{"x":1}},"data":"test"}' \ "$API_TARGET/encrypt" echo "" | tee -a "$OUT_FILE" # ── 7. CSRF token / SameSite exposure ───────────────────────────────────────── echo "--- CSRF / Cookie Security ---" | tee -a "$OUT_FILE" CSRF_HEADERS=$(curl -sk -D - -o /dev/null -A "$BROWSER_UA" "$TARGET/") echo "Cookie flags on main page:" | tee -a "$OUT_FILE" echo "$CSRF_HEADERS" | grep -i 'set-cookie:' | sed 's/^/ /' | tee -a "$OUT_FILE" # Check if no cookies → no issue; if cookies present, check for HttpOnly/Secure/SameSite if echo "$CSRF_HEADERS" | grep -qi 'set-cookie:'; then echo "$CSRF_HEADERS" | grep -i 'set-cookie:' | grep -viE '(httponly|secure|samesite)' | \ sed 's/^/ [WARN] Missing security flag: /' | tee -a "$OUT_FILE" else echo " [OK] No Set-Cookie on main page (stateless/API)" | tee -a "$OUT_FILE" fi # CSRF — cross-origin POST with no CSRF token do_test "Cross-origin POST (no Origin header - CSRF simulation)" \ -X POST -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'action=test&data=csrf_test' \ "$TARGET/" do_test "Cross-origin POST with foreign Origin header" \ -X POST -H 'Origin: https://evil.com' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'action=test&data=csrf_test' \ "$TARGET/" echo "" | tee -a "$OUT_FILE" # ── 8. Service Worker / PWA paths ───────────────────────────────────────────── echo "--- Service Worker / PWA Paths ---" | tee -a "$OUT_FILE" do_test "Service worker path /sw.js" -A "$BROWSER_UA" "$TARGET/sw.js" do_test "Service worker path /service-worker.js" -A "$BROWSER_UA" "$TARGET/service-worker.js" do_test "PWA manifest /manifest.json" -A "$BROWSER_UA" "$TARGET/manifest.json" do_test "PWA manifest /manifest.webmanifest" -A "$BROWSER_UA" "$TARGET/manifest.webmanifest" do_test "Worker /worker.js" -A "$BROWSER_UA" "$TARGET/worker.js" echo "" | tee -a "$OUT_FILE" # ── 9. Subresource Integrity check ──────────────────────────────────────────── echo "--- Subresource Integrity (SRI) ---" | tee -a "$OUT_FILE" PAGE_HTML=$(curl -sk -A "$BROWSER_UA" "$TARGET/") SCRIPT_COUNT=$(echo "$PAGE_HTML" | grep -c ']+src="https?://(?!${TARGET_HOST_ESCAPED})[^"]+' | wc -l) printf ' Script tags: %d | With SRI integrity attr: %d | External (non-${TARGET_HOST}): %d\n' \ "$SCRIPT_COUNT" "$SRI_COUNT" "$EXTERNAL_SCRIPTS" | tee -a "$OUT_FILE" if [ "$EXTERNAL_SCRIPTS" -gt 0 ]; then echo " [WARN] External scripts found without SRI:" | tee -a "$OUT_FILE" echo "$PAGE_HTML" | grep -oP ']+src="https?://(?!${TARGET_HOST_ESCAPED})[^"]+"[^>]*>' | sed 's/^/ /' | tee -a "$OUT_FILE" else echo " [OK] No cross-origin scripts detected" | tee -a "$OUT_FILE" fi echo "" | tee -a "$OUT_FILE" # ── 10. Referrer-Policy & Permissions-Policy ────────────────────────────────── echo "--- Referrer-Policy / Permissions-Policy ---" | tee -a "$OUT_FILE" MAIN_HEADERS=$(curl -sk -D - -o /dev/null -A "$BROWSER_UA" "$TARGET/") for HDR in Referrer-Policy Permissions-Policy Feature-Policy Cross-Origin-Opener-Policy Cross-Origin-Embedder-Policy; do VAL=$(echo "$MAIN_HEADERS" | grep -i "^$HDR:" | head -1) if [ -n "$VAL" ]; then echo " [OK] $VAL" | tee -a "$OUT_FILE" else echo " [MISS] $HDR not set" | tee -a "$OUT_FILE" fi done echo "" | tee -a "$OUT_FILE" # ── 11. Source map exposure ──────────────────────────────────────────────────── echo "--- Source Map Exposure ---" | tee -a "$OUT_FILE" # Find JS assets from page JS_ASSETS=$(echo "$PAGE_HTML" | grep -oP 'src="(/[^"]+\.js)"' | grep -oP '"/[^"]+' | tr -d '"' | head -5) for JS in $JS_ASSETS; do MAP_URL="${TARGET}${JS}.map" MAP_CODE=$(curl -sk -o /dev/null -w '%{http_code}' -A "$BROWSER_UA" "$MAP_URL") printf ' [%s] %s\n' "$MAP_CODE" "${JS}.map" | tee -a "$OUT_FILE" done do_test "Direct .map probe /js/crypt.js.map" -A "$BROWSER_UA" "$TARGET/js/crypt.js.map" echo "" | tee -a "$OUT_FILE" echo "=== 23. Client-Side JS Security COMPLETE ===" | tee -a "$OUT_FILE"