לדלג לתוכן

חקירת API ומיפוי - תרגיל

הקדמה

בתרגיל זה תתרגלו חקירת API מתקדמת - מציאת תיעוד נסתר, ביצוע אינטרוספקציה ב-GraphQL, מיפוי גרסאות API, וגילוי נקודות קצה שאינן מתועדות.


חלק א - גילוי תיעוד Swagger

משימה 1 - מציאת קובצי Swagger נסתרים

  1. צרו קובץ רשימת נתיבים של Swagger:
cat > swagger_paths.txt << 'EOF'
swagger.json
swagger.yaml
swagger/
swagger-ui/
swagger-ui.html
swagger/v1/swagger.json
swagger/v2/swagger.json
api-docs
api-docs.json
api-docs/
openapi.json
openapi.yaml
openapi/v1.json
openapi/v2.json
openapi/v3.json
v1/api-docs
v2/api-docs
v3/api-docs
docs
docs/api
redoc
api/swagger.json
api/v1/swagger.json
api/v2/swagger.json
.well-known/openapi.json
api/docs
api/spec
api/schema
graphql
graphiql
EOF
  1. הריצו סריקה נגד Juice Shop:
ffuf -u "http://localhost:3000/FUZZ" -w swagger_paths.txt -mc 200,301,302 -o swagger_scan.json
  1. בדקו את התוצאות - האם נמצא קובץ תיעוד?

  2. בדקו גם נתיבים עם סיומות:

ffuf -u "http://localhost:3000/api/FUZZ" -w swagger_paths.txt -mc 200,301,302

משימה 2 - ניתוח תיעוד API

אם מצאתם קובץ Swagger, נתחו אותו:

# הורדת וניתוח
curl -s "http://localhost:3000/api-docs" | python3 -m json.tool > api_docs.json

# חילוץ נקודות קצה
python3 -c "
import json
with open('api_docs.json') as f:
    spec = json.load(f)
for path in sorted(spec.get('paths', {}).keys()):
    methods = list(spec['paths'][path].keys())
    print(f'{path}: {methods}')
"

שאלות

  • האם מצאתם קובץ תיעוד API?
  • כמה נקודות קצה מתועדות?
  • האם יש נקודות קצה שנראות רגישות (admin, debug, internal)?

חלק ב - אינטרוספקציה של GraphQL

משימה 3 - חקירת GraphQL

  1. הפעילו את מעבדת GraphQL הפגיעה:
docker run -d -p 5013:5013 dolevf/damned-vulnerable-graphql-application
  1. ודאו שהשירות רץ:
curl -s "http://localhost:5013/graphql" -X POST \
     -H "Content-Type: application/json" \
     -d '{"query": "{ __typename }"}'
  1. בצעו שאילתת אינטרוספקציה:
curl -s -X POST "http://localhost:5013/graphql" \
     -H "Content-Type: application/json" \
     -d '{"query": "{ __schema { types { name kind fields { name type { name kind ofType { name } } args { name type { name } } } } } }"}' | python3 -m json.tool > introspection.json
  1. נתחו את הסכמה:
# הצגת כל הטיפוסים (ללא טיפוסי מערכת)
python3 -c "
import json
with open('introspection.json') as f:
    data = json.load(f)
types = data['data']['__schema']['types']
for t in types:
    if not t['name'].startswith('__') and t.get('fields'):
        print(f'\nType: {t[\"name\"]}')
        for f in t['fields']:
            fname = f['name']
            ftype = f['type'].get('name') or f['type'].get('ofType', {}).get('name', '?')
            args = [a['name'] for a in f.get('args', [])]
            args_str = f'({', '.join(args)})' if args else ''
            print(f'  - {fname}{args_str}: {ftype}')
"

משימה 4 - ניצול GraphQL

  1. מתוך הסכמה שגיליתם, נסו:
  2. לקבל רשימת כל המשתמשים
  3. לקרוא הודעות פרטיות
  4. לבצע מוטציה שמשנה הרשאות

  5. נסו שאילתות batch:

curl -s -X POST "http://localhost:5013/graphql" \
     -H "Content-Type: application/json" \
     -d '[
       {"query": "{ user(id: 1) { username } }"},
       {"query": "{ user(id: 2) { username } }"},
       {"query": "{ user(id: 3) { username } }"}
     ]'
  1. נסו שאילתות עם depth גבוה (Nested Queries):
{
  users {
    username
    friends {
      username
      friends {
        username
        friends {
          username
        }
      }
    }
  }
}

שאלות

  • אילו טיפוסים מצאתם בסכמה?
  • האם הצלחתם לגשת לנתונים רגישים?
  • האם יש הגבלת עומק שאילתות (query depth limiting)?
  • האם batch queries עובדות?

חלק ג - מיפוי גרסאות API

משימה 5 - גילוי גרסאות API

  1. כתבו סקריפט שבודק גרסאות API:
# api_version_scan.py
import requests

base_url = "http://localhost:3000"
endpoints = ["/users", "/products", "/orders", "/admin", "/config"]
versions = ["", "/api", "/api/v1", "/api/v2", "/api/v3", "/rest", "/rest/v1"]

for version in versions:
    for endpoint in endpoints:
        url = f"{base_url}{version}{endpoint}"
        try:
            resp = requests.get(url, timeout=5, verify=False)
            if resp.status_code != 404:
                print(f"[{resp.status_code}] {url} (length: {len(resp.text)})")
        except:
            pass
  1. הריצו את הסקריפט נגד Juice Shop:
python3 api_version_scan.py
  1. השוו בין תגובות גרסאות שונות - האם גרסה ישנה חושפת מידע נוסף?

משימה 6 - בדיקת הבדלים בין גרסאות

  1. עבור כל זוג גרסאות שמצאתם, השוו את התגובות:
# דוגמה
curl -s "http://localhost:3000/api/Users" | python3 -m json.tool > v1_users.json
curl -s "http://localhost:3000/rest/user/login" | python3 -m json.tool > rest_login.json
  1. בדקו האם גרסאות שונות מחזירות שדות שונים

חלק ד - גילוי נקודות קצה לא מתועדות

משימה 7 - סריקה מתקדמת

  1. צרו רשימת מילים ממוקדת API:
cat > api_wordlist.txt << 'EOF'
users
user
admin
login
logout
register
signup
password
reset
forgot
profile
settings
config
configuration
debug
test
health
status
info
version
metrics
stats
logs
audit
backup
export
import
upload
download
search
query
token
session
auth
authenticate
authorize
role
permission
secret
key
api-key
webhook
callback
notify
email
send
verify
confirm
activate
deactivate
delete
remove
update
create
list
get
post
put
patch
flag
feature
internal
private
public
docs
swagger
schema
graphql
EOF
  1. סרקו עם ffuf:
# סריקת נקודות קצה ישירות
ffuf -u "http://localhost:3000/api/FUZZ" -w api_wordlist.txt -mc all -fc 404

# סריקת נקודות קצה עם REST
ffuf -u "http://localhost:3000/rest/FUZZ" -w api_wordlist.txt -mc all -fc 404
  1. עבור כל נקודת קצה שמצאתם, בדקו שיטות HTTP שונות:
# בדיקת שיטות HTTP
for method in GET POST PUT DELETE PATCH OPTIONS; do
    status=$(curl -s -o /dev/null -w "%{http_code}" -X $method "http://localhost:3000/api/ENDPOINT")
    echo "[$status] $method /api/ENDPOINT"
done

משימה 8 - בדיקת אותנטיקציה

  1. עבור כל נקודת קצה רגישה שמצאתם, בדקו:
# ללא אותנטיקציה
curl -s "http://localhost:3000/api/admin/users"

# עם כותרות מזויפות
curl -s "http://localhost:3000/api/admin/users" -H "X-Forwarded-For: 127.0.0.1"
curl -s "http://localhost:3000/api/admin/users" -H "Authorization: Bearer null"

# עם פרמטרים מיוחדים
curl -s "http://localhost:3000/api/admin/users?admin=true"
curl -s "http://localhost:3000/api/admin/users?debug=1"

חלק ה - כתיבת סקריפט מיפוי מלא

משימה 9 - סקריפט API Mapper

כתבו סקריפט Python שמבצע מיפוי API מלא:

# api_mapper.py - שלד
import requests
import json

class APIMapper:
    def __init__(self, base_url):
        self.base_url = base_url
        self.endpoints = []
        self.session = requests.Session()
        self.session.verify = False

    def check_swagger(self):
        """בדיקת קיום תיעוד Swagger"""
        # השלימו
        pass

    def check_graphql(self):
        """בדיקת קיום GraphQL"""
        # השלימו
        pass

    def scan_endpoints(self, wordlist_path):
        """סריקת נקודות קצה"""
        # השלימו
        pass

    def test_methods(self, endpoint):
        """בדיקת שיטות HTTP מותרות"""
        # השלימו
        pass

    def check_auth(self, endpoint):
        """בדיקת אותנטיקציה"""
        # השלימו
        pass

    def report(self):
        """הצגת דוח סופי"""
        # השלימו
        pass

if __name__ == "__main__":
    mapper = APIMapper("http://localhost:3000")
    mapper.check_swagger()
    mapper.check_graphql()
    mapper.scan_endpoints("api_wordlist.txt")
    mapper.report()

השלימו את הפונקציות והריצו נגד Juice Shop.


מעבדות PortSwigger מומלצות

בצעו את המעבדות הבאות:

  1. Exploiting an API endpoint using documentation - ניצול API דרך תיעוד נגיש
  2. Finding and exploiting an unused API endpoint - מציאת נקודת קצה לא בשימוש
  3. Exploiting a mass assignment vulnerability - ניצול חולשת mass assignment
  4. Accessing a GraphQL API using introspection (אם זמינה) - אינטרוספקציה של GraphQL

קישור: https://portswigger.net/web-security/api-testing


שאלות סיכום

  1. מה ההבדל בין REST API ל-GraphQL מבחינת משטח תקיפה?
  2. למה חשוב לבדוק גרסאות API ישנות?
  3. כיצד שאילתת אינטרוספקציה יכולה לחשוף מידע רגיש?
  4. מה הם הסיכונים של API ללא אותנטיקציה?
  5. כיצד ניתן לגלות נקודות קצה שאינן מתועדות?