4.2 חולשת XSS הרצאה
Stored XSS, Reflected XSS, ו-DOM XSS¶
- חולשת XSS (Cross-Site Scripting) היא חולשת צד לקוח, אשר מאפשרת לתוקף להזריק קוד JavaScript זדוני לדפי אינטרנט באתר הנצפים על ידי משתמשים אחרים.
- קיימים שלושה סוגים עיקריים של XSS: Stored XSS, Reflected XSS, ו-DOM XSS.
Stored XSS¶
(הזרקת קוד זדוני המאוחסן בשרת)
ב-Stored XSS, הקוד הזדוני נשמר באופן קבוע בשרת ונשלח לכל המשתמשים שניגשים לדף הנגוע. בדרך כלל, הפגיעות מתרחשת באזורים שבהם משתמשים יכולים להכניס תוכן, כגון טפסי תגובות, פוסטים בפורומים או שדות פרופיל.
דמיינו שיש לנו את הקוד הבא:
<?php
// קוד פגיע - Stored XSS
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$comment = $_POST['comment'];
// שמירה בבסיס הנתונים ללא סינון
$stmt = $pdo->prepare("INSERT INTO comments (text) VALUES (?)");
$stmt->execute([$comment]);
}
// הצגת התגובות
$comments = $pdo->query("SELECT text FROM comments")->fetchAll();
foreach ($comments as $comment) {
echo "<div class='comment'>" . $comment['text'] . "</div>"; // פגיעות XSS
}
?>
דוגמה לפגיעות Stored XSS¶
משתמש מזין את התגובה הבאה בטופס תגובות באתר:
התגובה תישמר בdatabase.
עכשיו, כל משתמש שיגש לאתר, הphp ישלוף מהDB את התגובה שהוספנו שכאשר הphp ישלח אותה עם הhtml שהוא יוצר, התוסף לhtml את תגית הscript שיצרנו ותרוץ פקודת alert על המשתמש.
סכנות של XSS¶
אז הרצנו קוד javascript שלבחירתנו על כל האנשים שגלשו לאתר, מה זה עוזר לנו?
- נוכל לגנוב עוגיות של משתמשים (Cookies) לצורך הזהדהות עם המשתמש שלהם.
נוכל להגן על הקוד באמצעות שינוי הecho כך שנשתמש בפונקציהhtmlspecialcharsעל הקלט של המשתמש מהDB.
<?php foreach ($comments as $comment) { echo "<div class='comment'>" . htmlspecialchars($comment['text'], ENT_QUOTES, 'UTF-8') . "</div>"; } ?>
סוג הXSS הזה נקרא stored בגלל שאנחנו שומרים את הpayload בתוך הdb, כך שכל המשתמשים יהיו חשופים לחולשה.
Reflected XSS¶
(הזרקת קוד זדוני המוחזר מיד מהשרת)
ב-Reflected XSS, הקוד הזדוני אינו נשמר בשרת אלא נשלח כפרמטר בבקשה, ומוחזר ישירות למשתמש. זה קורה לרוב כאשר נתונים מועברים דרך ה-URL או פרמטרים של טופס ומוחזרים לדף ללא סינון נאות.
דוגמה לפגיעות Reflected XSS¶
משתמש מקבל קישור ממקור לא ידוע:
אם האתר מציג את ערך החיפוש ישירות על הדף ללא סינון, הקוד הזדוני ירוץ בכל פעם שמישהו ילחץ על הקישור.
סכנות Reflected XSS¶
-
תקיפות פישינג: הפנייה של המשתמשים לדף מזויף שנראה כמו האתר המקורי.
-
הזרקת קוד המאפשר גניבת נתוני התחברות. (גניבת עוגיות)
-
השתלת קוד המפנה את המשתמשים לאתרים זדוניים.
גם פה כדי להגן על המתקפה נוכל לשנות את הקוד כך:
<?php
$searchQuery = htmlspecialchars($_GET['q'], ENT_QUOTES, 'UTF-8');
echo "תוצאות חיפוש עבור: " . $searchQuery;
?>
DOM XSS¶
(הזרקת קוד באמצעות שינוי ה-DOM בדפדפן)
ב-DOM XSS, הקוד הזדוני מופעל על ידי שינוי ה-DOM של הדף ישירות בדפדפן, ללא מעורבות השרת. זה קורה כאשר האתר משתמש ב-JavaScript לטפל בקלט המשתמש בצורה לא מאובטחת.
דוגמה לפגיעות DOM XSS¶
נניח שיש קוד JavaScript שמכניס את ערך ה-URL לתוך הדף כך:
<script>
const userInput = window.location.hash.substring(1);
document.getElementById("output").innerHTML = userInput; // פגיעות DOM XSS
</script>
תוקף יכול לשלוח למשתמש קישור כמו:
כאשר המשתמש נכנס ללינק, הדף מריץ את הקוד הזדוני.
זה נקרא DOM XSS בגלל שבאמצעות קלט של המשתמש ניתן לשנות את הDOM של הHTML.
סכנות DOM XSS¶
-
עקיפת הגנות מבוססות שרת, כי הקוד מתבצע ישירות בצד הלקוח.
-
גניבת מידע דרך שינוי התוכן בדף.
-
התקפות פישינג מתוחכמות יותר.
כיצד להגן על מערכות מפני XSS?¶
✅ אימות וסינון קלט – לעולם לא להכניס קלט משתמש ישירות ל-HTML ללא סינון והסרת תווים מסוכנים.
✅ דרך אחת, Escape של פלט (Output Encoding) – שימוש ב-HTML entities למניעת הזרקת קוד. (כמו הפונקציה שהצגנו בפתרונות למעלה.)
✅ דרך שנייה, Content Security Policy (CSP) – הגדרת מדיניות אבטחה של הדפדפן שמגבילה את הרצת קוד JavaScript חיצוני. (נדבר בהמשך בהרחבה על הגנה זו.)
✅ הימנעות מ-innerHTML – שימוש ב-textContent או בפונקציות בטוחות אחרות להוספת טקסט לדף.
✅ שימוש ב-HTTPOnly Cookies – עוד הגנת דפדפן, משמשת הגנה מגניבת עוגיות- נדבר בהמשך בהרחבה על הגנה זו.
דוגמאות מתקדמות ל-XSS Payloads ודרכי עקיפה¶
Payloads בסיסיים ל-XSS¶
1. payload פשוט¶
2. גניבת Cookies:¶
3. Redirect למקום זדוני:¶
Payloads מתקדמים עם עקיפת הגנות¶
1. עקיפת htmlspecialchars (כאשר לא משתמשים ב-ENT_QUOTES):¶
הסבר: אם הקוד משתמש ב-
htmlspecialchars($input) ללא ENT_QUOTES, הוא לא יקודד את המרכאות.
2. שימוש ב-JavaScript URI:¶
3. שימוש בalert ללא תווים אסורים:¶
4. עקיפת סינון עם Base64:¶
הסבר:
atob('YWxlcnQoJ1hTUycp') מפענח ל-alert('XSS')
דוגמאות להגנות PHP ועקיפתן¶
1. הגנה בסיסית עם htmlspecialchars¶
<?php
$input = htmlspecialchars($_GET['input'], ENT_QUOTES, 'UTF-8');
echo <input value="<?php echo $input; ?>">;
?>
עקיפה: אם הפלט משמש בתוך מאפיין HTML:
Payload:
פיתרון: יש להשתמש ב-
htmlspecialchars גם עבור מאפיינים.
2. הגנה עם strip_tags¶
עקיפה:
הסבר: הפונקציה מסירה את
<script> אבל משאירה את ה-payload שלם.
3. הגנה עם regex¶
עקיפה:
או: