אתגר CTF - צד לקוח - תרגיל¶
סקירה כללית¶
האתגר הזה מורכב מארבעה שלבים שמשלבים את כל הטכניקות שנלמדו בפרק 4. כל שלב מבוסס על השלב הקודם. המטרה הסופית היא לגנוב את ה-flag מחשבון ה-admin.
שלב 1: הbypass CSP והרצת XSS¶
תיאור¶
אתר הבלוג https://target-blog.ctf מאפשר הוספת תגובות. התגובות מנוקות עם DOMPurify ומוצגות בדף. האתר משתמש ב-CSP הבא:
Content-Security-Policy: default-src 'none'; script-src 'self' https://cdnjs.cloudflare.com 'nonce-{RANDOM}'; style-src 'self'; img-src *; connect-src 'self'; frame-src 'none'; base-uri 'self'
משימה¶
הריצו alert(document.domain) בדף הבלוג.
רמזים¶
- בדקו אילו ספריות נטענות מ-cdnjs
- חפשו ספריית JavaScript שמאפשרת template injection
- זכרו - DOMPurify מאפשר HTML אבל חוסם event handlers
- שלבו CDN bypass עם template injection
שאלות מנחות¶
- מה הגרסה של AngularJS שזמינה ב-cdnjs?
- האם AngularJS sandbox escape עובד בגרסה הזו?
- איזה attribute צריך כדי להפעיל AngularJS על אלמנט?
- האם DOMPurify מאפשר את ה-attributes האלה?
שלב 2: הpollution פרוטוטייפ להסלמה ל-Stored XSS¶
תיאור¶
אחרי שמצאתם XSS ב-self context, אתם צריכים להפוך אותו ל-stored XSS שישפיע על משתמשים אחרים. האתר כולל מערכת "תגובות" שמשתמשת ב-API הבא:
// the client code
async function loadComments(postId) {
let response = await fetch('/api/comments/' + postId);
let comments = await response.json();
let config = {};
comments.forEach(function(comment) {
mergeConfig(config, comment.metadata || {});
});
comments.forEach(function(comment) {
renderComment(comment, config);
});
}
function mergeConfig(target, source) {
for (let key in source) {
if (typeof source[key] === 'object' && source[key] !== null) {
if (!target[key]) target[key] = {};
mergeConfig(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
function renderComment(comment, config) {
let div = document.createElement('div');
div.className = 'comment';
let template = config.commentTemplate || '<b>{author}</b>: {text}';
let html = template.replace('{author}', escapeHtml(comment.author))
.replace('{text}', escapeHtml(comment.text));
div.innerHTML = html;
document.getElementById('comments').appendChild(div);
}
משימה¶
השתמשו בpollution פרוטוטייפ דרך metadata של תגובה כדי לשנות את commentTemplate ולהזריק XSS ל-stored context.
רמזים¶
- הפונקציה
mergeConfigפגיעה לpollution פרוטוטייפ - שדה
metadataשל תגובה מגיע מה-API - אם תשלחו תגובה עם metadata שמכיל
__proto__, תוכלו לזהם אתObject.prototype config.commentTemplateייקרא מהפרוטוטייפ אם לא מוגדר ישירות
שאלות מנחות¶
- מה ה-JSON שצריך לשלוח ב-POST לפי API?
- איך ה-template שלכם יכול לכלול XSS אם
escapeHtmlמופעל על author ו-text? - האם יש חלק ב-template שלא עובר escape?
שלב 3: שיבוש DOM לשיבוש הגדרות האפליקציה¶
תיאור¶
ה-admin panel באתר משתמש בקוד הבא לטעינת הגדרות:
// admin.js
(function() {
let appConfig = window.APP_CONFIG || {};
let apiEndpoint = appConfig.apiEndpoint || '/api';
let adminPanel = appConfig.adminPanelUrl || '/admin';
// loading admin data
fetch(apiEndpoint + '/admin/data', {
credentials: 'include',
headers: {
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
}
})
.then(function(r) { return r.json(); })
.then(function(data) {
document.getElementById('admin-data').textContent = JSON.stringify(data);
});
// loading an additional script
if (appConfig.extraScript) {
let s = document.createElement('script');
s.src = appConfig.extraScript;
document.body.appendChild(s);
}
})();
משימה¶
השתמשו ב-DOM clobbering (דרך ה-stored XSS מהשלב הקודם) כדי:
1. לשבש את window.APP_CONFIG
2. לגרום לטעינת סקריפט מהשרת שלכם
3. הסקריפט שלכם יאסוף את ה-CSRF token מהדף
רמזים¶
- הזריקו HTML שיוצר אלמנטים עם
id="APP_CONFIG" - השתמשו ב-collection clobbering (שני אלמנטי
<a>עם אותו id) appConfig.extraScriptצריך להחזיר URL - השתמשו ב-<a>עםhref
שאלות מנחות¶
- איזה HTML payload ידרוס
window.APP_CONFIG.extraScript? - האם DOMPurify מאפשר אלמנטי
<a>עםidו-href? - מה הסקריפט שלכם צריך לעשות אחרי שנטען?
שלב 4: הinjection CSS לexfiltration CSRF Token של ה-admin¶
תיאור¶
אחרי שלב 3, אתם צריכים את ה-CSRF token של ה-admin כדי לבצע פעולת "Export All Data" שמחזירה את ה-flag. ה-CSRF token נמצא ב:
ה-CSP מגביל סקריפטים, אבל style-src 'self' מאפשר CSS מהאתר עצמו. יש נקודת injection ב-CSS:
משימה¶
- השתמשו בinjection CSS כדי לחלץ את ה-CSRF token תו אחר תו
- השתמשו ב-token כדי לשלוח בקשת POST ל-
/admin/export - קבלו את ה-flag
רמזים¶
- הזריקו CSS דרך פרמטר ה-color
- השתמשו ב-attribute selectors על meta tag
- צרו שרת שמקבל את התווים ומחזיר CSS חדש
- השתמשו ב-
@importלטעינה סדרתית
שאלות מנחות¶
- איך אפשר להפוך meta tag ל-visible כדי שהדפדפן יטען background?
- מה ה-CSS payload שיחלץ את התו הראשון?
- איך מפעילים את הexfiltration מהדפדפן של ה-admin?
משאבים נוספים¶
מעבדות PortSwigger מומלצות¶
| מעבדה | נושא | רמה |
|---|---|---|
| CSP bypass | הbypass CSP | Expert |
| Prototype pollution to XSS | הpollution פרוטוטייפ | Practitioner |
| DOM clobbering | שיבוש DOM | Expert |
| DOM XSS via postMessage | הexploit postMessage | Practitioner |
| WebSocket vulnerabilities | תקיפות WebSocket | Practitioner |
אתגרי HackTheBox ו-CTF¶
| אתגר | תיאור |
|---|---|
| HackTheBox - CSP Bypass challenges | אתגרי bypass CSP ברמות שונות |
| XSS Game by Google | אתגרי XSS מרמת מתחיל עד מתקדם |
| alert(1) to win | אתגרי XSS מתקדמים |
| Cure53 XSS challenges | אתגרי mXSS ו-DOM clobbering |
| CTFtime.org - Web challenges | אתגרי CTF בתחום web |
טיפים כלליים לפתרון¶
מתודולוגיה¶
1. review the source code carefully
2. identify the CSP and find weaknesses
3. find all the sinks (innerHTML, eval, location, etc.)
4. find all the sources (URL params, postMessage, WebSocket, etc.)
5. map the data flow from source to sink
6. look for gadgets (prototype pollution, DOM clobbering)
7. build the exploitation chain step by step
8. test each step separately before combining them
כלים שימושיים¶
- Burp Suite - intercepting and manipulating traffic
- DevTools Console - testing payloads
- DevTools Application > Service Workers - monitoring SW
- CSP Evaluator - analyzing the CSP policy
- DOMPurify test page - testing payloads against DOMPurify
שגיאות נפוצות¶
- שכחה לקודד (encode) תווים מיוחדים ב-URL
- אי התחשבות ב-Content-Type של תגובות
- אי בדיקה שה-payload עובר DOMPurify
- שכחה שצריך HTTPS ל-Service Workers
- אי התחשבות ב-SameSite cookies