לדלג לתוכן

ניתוח JavaScript סטטי - תרגיל

הקדמה

בתרגיל זה תתרגלו טכניקות ניתוח JavaScript סטטי. התרגיל כולל ארבעה אתגרים שמכסים את כל הנושאים מההרצאה - מחילוץ נקודות קצה ועד שחזור קוד מקור מ-Source Maps.


אתגר 1 - חילוץ נקודות קצה API מ-Bundle

רקע

קיבלתם קובץ JavaScript שנבנה עם Webpack. הקובץ מכיל את כל הלוגיקה של אפליקציית ווב, כולל קריאות API.

משימות

  1. צרו את קובץ הדוגמה הבא ושמרו אותו כ-challenge1.js:
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n(0)}({0:function(e,t,n){var r=n(1),o=n(2);r.init(),o.loadData()},1:function(e,t){var API_BASE="https://api.internal.target.com/v2";e.exports={init:function(){fetch(API_BASE+"/auth/login",{method:"POST"}),fetch(API_BASE+"/users/me"),fetch(API_BASE+"/admin/dashboard"),fetch(API_BASE+"/admin/users/list"),fetch(API_BASE+"/admin/config/update",{method:"PUT"}),fetch(API_BASE+"/internal/metrics"),fetch(API_BASE+"/debug/stacktrace"),fetch(API_BASE+"/api/v1/legacy/export")}}},2:function(e,t){var SECRET_KEY="sk_live_4eC39HqLyjWDarjtT1zdp7dc";var FIREBASE_KEY="AIzaSyDOCAbC123dEf456GhI789jKl012-MnO";e.exports={loadData:function(){return fetch("/api/v3/products").then(function(e){return e.json()})}}}});
  1. השתמשו בסקריפט Python מההרצאה (או כתבו סקריפט משלכם) לחילוץ כל נתיבי ה-API מהקובץ
  2. השתמשו ב-js-beautify לפירמוט הקובץ ונתחו אותו ידנית
  3. מצאו את כל המפתחות והטוקנים שחשופים בקובץ

שאלות

  • כמה נקודות קצה API מצאתם?
  • אילו נקודות קצה הן בעלות סיכון גבוה (admin, debug, internal)?
  • אילו מפתחות/טוקנים נמצאו? לאילו שירותים הם שייכים?
  • מה משמעות מציאת נתיב /api/v1/legacy/export לצד נתיבי /v2 ו-/v3?

אתגר 2 - שחזור קוד מ-Source Maps

רקע

אתר הנמצא בבדיקה חושף source maps של אפליקציית React.

משימות

  1. הקימו אפליקציית React פשוטה עם Docker:
# docker-compose-sourcemap-lab.yml
version: "3.8"
services:
  react-app:
    image: node:18
    working_dir: /app
    volumes:
      - ./react-lab:/app
    ports:
      - "3001:3000"
    command: sh -c "npx create-react-app myapp --template typescript 2>/dev/null; cd myapp; npm start"
  1. לאחר שהאפליקציה רצה, בצעו:
  2. גלשו ל-http://localhost:3001
  3. פתחו את כלי הפיתוח (F12) ועברו לטאב Sources
  4. שימו לב ל-source maps שנטענו
  5. בדקו אם ניתן לגשת ישירות לקבצי .map

  6. נסו לשחזר את קוד המקור באמצעות הכלים שלמדנו:

# מצאו את שם קובץ ה-JS הראשי
curl -s http://localhost:3001 | grep -oP 'src="[^"]*\.js"'

# נסו לגשת ל-source map
curl -s http://localhost:3001/static/js/main.XXXX.js.map -o app.map

# שחזרו את הקוד
unwebpack-sourcemap app.map -o recovered/
  1. בדקו את הקוד ששוחזר - האם הוא מכיל את קוד המקור המלא?

שאלות

  • האם הצלחתם לגשת לקבצי Source Map?
  • מה מבנה התיקיות של הפרויקט ששוחזר?
  • אילו קבצים שוחזרו מכילים מידע שימושי לתוקף?

אתגר 3 - שימוש ב-LinkFinder

משימות

  1. התקינו את LinkFinder:
git clone https://github.com/GerbenJavado/LinkFinder.git
cd LinkFinder
pip3 install -r requirements.txt
  1. הריצו את LinkFinder על Juice Shop:
# ודאו ש-Juice Shop רץ על פורט 3000
python3 linkfinder.py -i http://localhost:3000 -d -o results.html
  1. פתחו את קובץ התוצאות (results.html) בדפדפן
  2. סננו את התוצאות ומצאו:
  3. נתיבי API
  4. כתובות URL חיצוניות
  5. נתיבים פנימיים

  6. הריצו ידנית על קבצי JS ספציפיים של Juice Shop:

# מצאו את קבצי ה-JS הראשיים
curl -s http://localhost:3000 | grep -oP 'src="[^"]*\.js"'

# הריצו LinkFinder על כל קובץ
python3 linkfinder.py -i "http://localhost:3000/main.js" -o cli
python3 linkfinder.py -i "http://localhost:3000/polyfills.js" -o cli
python3 linkfinder.py -i "http://localhost:3000/vendor.js" -o cli

שאלות

  • כמה נקודות קצה API מצאתם?
  • האם מצאתם נתיבים שנראים כמו פאנל ניהול?
  • האם מצאתם הפניות לשירותים חיצוניים?

אתגר 4 - מציאת נתיבי Admin בקוד React

רקע

אפליקציית React מודרנית מכילה ניתוב (routing) בצד הלקוח. כל הנתיבים - כולל נתיבי admin - מוגדרים בקוד ה-JavaScript.

משימות

  1. צרו את הקובץ הבא ושמרו אותו כ-challenge4_routes.js:
import React from "react";
import {BrowserRouter,Route,Switch} from "react-router-dom";
import Home from "./pages/Home";
import Login from "./pages/Login";
import Dashboard from "./pages/Dashboard";
import Profile from "./pages/Profile";
import AdminPanel from "./pages/admin/AdminPanel";
import UserManager from "./pages/admin/UserManager";
import SystemConfig from "./pages/admin/SystemConfig";
import AuditLog from "./pages/admin/AuditLog";
import ApiDocs from "./pages/dev/ApiDocs";
import DebugConsole from "./pages/dev/DebugConsole";
import FeatureFlags from "./pages/dev/FeatureFlags";
import BackupRestore from "./pages/admin/BackupRestore";
import SqlConsole from "./pages/admin/SqlConsole";

const isAdmin = () => localStorage.getItem("role") === "admin";
const isDev = () => localStorage.getItem("env") === "development";

export default function AppRouter() {
    return (
        <BrowserRouter>
            <Switch>
                <Route exact path="/" component={Home} />
                <Route path="/login" component={Login} />
                <Route path="/dashboard" component={Dashboard} />
                <Route path="/profile/:userId" component={Profile} />
                {isAdmin() && <Route path="/admin" component={AdminPanel} />}
                {isAdmin() && <Route path="/admin/users" component={UserManager} />}
                {isAdmin() && <Route path="/admin/config" component={SystemConfig} />}
                {isAdmin() && <Route path="/admin/audit" component={AuditLog} />}
                {isAdmin() && <Route path="/admin/backup" component={BackupRestore} />}
                {isAdmin() && <Route path="/admin/sql-console" component={SqlConsole} />}
                {isDev() && <Route path="/dev/api-docs" component={ApiDocs} />}
                {isDev() && <Route path="/dev/debug" component={DebugConsole} />}
                {isDev() && <Route path="/dev/feature-flags" component={FeatureFlags} />}
            </Switch>
        </BrowserRouter>
    );
}
  1. נתחו את הקובץ ומצאו:
  2. את כל הנתיבים המוגדרים
  3. נתיבים שמוגנים רק בצד הלקוח
  4. נתיבים מסוכנים במיוחד

  5. הסבירו למה ההגנה הבאה אינה מספקת:

{isAdmin() && <Route path="/admin/sql-console" component={SqlConsole} />}
  1. כתבו סקריפט שמחלץ אוטומטית את כל הנתיבים מקובץ ניתוב React/Vue/Angular

שאלות

  • כמה נתיבים מצאתם בסך הכל?
  • אילו נתיבים הכי מסוכנים אם ניתן לגשת אליהם ללא הרשאה?
  • למה בדיקת isAdmin() בצד הלקוח לא מספיקה?
  • מה הבעיה בנתיב /admin/sql-console?
  • כיצד הייתם בודקים האם ההגנה קיימת גם בצד השרת?

אתגר בונוס - מעבדות PortSwigger

בצעו את המעבדות הבאות ב-PortSwigger Web Security Academy:

  1. Information disclosure in version control history - חשיפת מידע מתיקיית .git
  2. Information disclosure on debug page - מציאת מידע רגיש בדפי debug
  3. Source code disclosure via backup files - מציאת קבצי גיבוי של קוד מקור
  4. Authentication bypass via information disclosure - עקיפת אותנטיקציה באמצעות מידע שנחשף

קישור: https://portswigger.net/web-security/information-disclosure/exploiting/lab-infoleak-via-backup-files


טיפ לסיכום

בעבודה אמיתית, ניתוח JavaScript הוא לרוב השלב הראשון בחקירה. לפני שאתם מתחילים לבדוק חולשות, השקיעו זמן במיפוי כל נקודות הקצה, המפתחות, והנתיבים שחבויים בקוד. המידע הזה יחסוך לכם שעות של ניחושים וסריקות עיוורות.