Content Security Policy

Joe Medley
Joe Medley

מודל האבטחה של האינטרנט מבוסס על למדיניות המקור הזהה. קוד פגישה מ-https://mybank.com צריכה להיות גישה רק אל https://mybank.com נתונים, ואסור בהחלט לאפשר גישה של https://evil.example.com אף פעם. כל מקור נשמר בנפרד משאר האינטרנט, וכך מפתחים "ארגז חול" שבו אפשר לבנות ולשחק. בתיאוריה, זה מעולה. לחשבון בפועל, תוקפים מצאו דרכים חכמות לעקוף את המערכת.

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

הסקירה הזו מדגישה הגנה שיכולה להפחית באופן משמעותי את הסיכון ההשפעה של התקפות XSS בדפדפנים מודרניים: Content Security Policy (CSP).

אמ;לק

  • אפשר להשתמש ברשימות היתרים כדי לומר ללקוח מה מותר ומה אסור.
  • כאן תוכלו לראות אילו הוראות זמינות.
  • ללמוד אילו מילות מפתח הם משתמשים.
  • קוד מוטבע ו-eval() נחשבים מזיקים.
  • לפני שאוכפים את רמות המדיניות, דווחו לשרת על הפרות מדיניות.

רשימות היתרים של מקורות

הבעיה שבה מנצלת התקפות XSS היא היכולת של הדפדפן להבחין בין סקריפט שנכלל באפליקציה לסקריפט שכבר שהוחדר באופן זדוני על ידי צד שלישי. לדוגמה, לחצן Google +1 בכותרת בחלק התחתון של הדף הזה נטען ומפעיל קוד מתוך https://apis.google.com/js/plusone.js בהקשר של מקור הדף הזה. רביעי נותנים אמון בקוד הזה, אבל אנחנו לא יכולים לצפות שהדפדפן יבין בעצמו את הקוד של apis.google.com זה מגניב, ואילו הקוד מ-apis.evil.example.com סביר להניח שלא. הדפדפן מוריד ומפעיל כל קוד בדף ללא קשר למקור.

במקום לסמוך באופן עיוור על כלמה שהשרת מספק, CSP מגדיר כותרת ה-HTTP Content-Security-Policy, שמאפשרת ליצור רשימת היתרים מקורות של תוכן מהימן, ומורה לדפדפן רק להפעיל או לעבד את המשאבים האלה מהמקורות האלה. גם אם התוקף יכול למצוא ישר להחדרת סקריפט, הסקריפט לא יתאים לרשימת ההיתרים, ולכן הוא לא בוצעה.

אנחנו סומכים על apis.google.com שתספק קוד תקף, ואנחנו סומכים על עצמנו לעשות את אותו הדבר, בואו נגדיר מדיניות שמאפשרת לסקריפט לפעול רק כאשר מגיע מאחד משני המקורות האלה:

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

פשוט, נכון? כפי שבטח ניחשת, script-src היא הוראה שולט בקבוצה של הרשאות הקשורות לסקריפט עבור דף מסוים. פירטנו 'self' כמקור חוקי אחד לסקריפט ו-https://apis.google.com בתור מקור אחר. הדפדפן מוריד ומפעיל JavaScript כראוי מ- apis.google.com ב-HTTPS, וכן ממקור הדף הנוכחי.

שגיאה במסוף: טעינת הסקריפט 'http://evil.example.com/evil.js' נדחתה. מאחר שהוא מפר את ההוראה הבאה של Content Security Policy: script-src 'self' https://apis.google.com

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

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

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

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

  • ההגדרה base-uri מגבילה את כתובות ה-URL שיכולות להופיע ברכיב <base> של הדף.
  • ב-child-src תוכלו לראות את כתובות ה-URL של העובדים ואת התוכן של המסגרות המוטמעות. עבור דוגמה: child-src https://youtube.com תאפשר הטמעת סרטונים מ- מ-YouTube, אבל לא ממקורות אחרים.
  • connect-src מגביל את המקורות שאפשר להתחבר אליהם (דרך XHR, WebSockets ו-EventSource).
  • החלק font-src מציין את המקורות שיכולים להציג גופנים באינטרנט. אתר Google ניתן להפעיל גופנים דרך font-src https://themes.googleusercontent.com.
  • ב-form-action מפורטות נקודות קצה (endpoints) תקינות שאפשר לשלוח מתגי <form>.
  • frame-ancestors מציין את המקורות שיכולים להטמיע את הדף הנוכחי. ההוראה הזו חלה על התגים <frame>, <iframe>, <embed> ו-<applet>. לא ניתן להשתמש בהוראה זו בתגי <meta> והיא חלה רק על אתרים שאינם HTML במשאבי אנוש.
  • frame-src הוצא משימוש ברמה 2, אבל שוחזר ברמה 3. אחרת כיום, הוא עדיין יחזור אל child-src כמו קודם.
  • ההגדרה img-src מגדירה את המקורות שמהם אפשר לטעון את התמונות.
  • ההגדרה media-src מגבילה את המקורות שמורשים להעביר וידאו ואודיו.
  • object-src מאפשר שליטה על Flash ויישומי פלאגין אחרים.
  • plugin-types מגביל את סוגי יישומי הפלאגין שדף יכול להפעיל.
  • report-uri מציין כתובת URL שאליה הדפדפן ישלח דוחות כאשר שהופרה מדיניות אבטחת התוכן. לא ניתן להשתמש בהוראה הזו ב-<meta> התגים.
  • style-src הוא המקביל של script-src לגיליונות סגנונות.
  • upgrade-insecure-requests מורה לסוכני המשתמש לשכתב סכמות של כתובות URL, מעבר ל-HTTP ל-HTTPS. ההוראה הזו מיועדת לאתרים עם מספר גדול של את כתובות האתרים הישנות שצריך לשכתב.
  • worker-src היא הוראה של CSP ברמה 3 שמגבילה את כתובות ה-URL שעלולות להיות נטענים כעובדים, כעובדים משותפים או כ-Service Worker. החל מיולי 2017, כולל הטמעות מוגבלות.

כברירת מחדל, ההוראות פתוחות. אם לא מגדירים מדיניות ספציפית עבור נניח font-src, וההנחיה הזו פועלת כברירת מחדל למרות שציינת את * כמקור התקף (לדוגמה, אפשר לטעון גופנים בכל מקום, ללא הגבלה).

כדי לשנות את התנהגות ברירת המחדל הזו אפשר לציין default-src של Google. ההוראה הזו מגדירה את ברירות המחדל עבור הוראות שלא צוינו. בדרך כלל, הכלל הזה חל על כל הוראה מסתיים ב--src. אם המדיניות default-src מוגדרת לערך https://example.com, והניסיון לא ייכשל כדי לציין הוראת font-src, אפשר לטעון גופנים https://example.com, ובשום מקום אחר. ציינתם רק script-src ב מהדוגמאות הקודמות, כלומר אפשר לטעון תמונות, גופנים וכו' כל מקור.

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

  • base-uri
  • form-action
  • frame-ancestors
  • plugin-types
  • report-uri
  • sandbox

אפשר להשתמש בהוראות האלה בכמה שיותר או מעט מהן ספציפי לאפליקציה, פשוט לרשום כל אחת מהן בכותרת ה-HTTP, מפרידה באמצעות נקודה ופסיק. חשוב לכלול את הכול. למשאבים הנדרשים מסוג מסוים בהוראה בודדת. אם כתבתם: משהו כמו script-src https://host1.com; script-src https://host2.com המערכת פשוט תתעלם מההוראה השנייה. משהו כמו בדוגמה הבאה לציין בצורה נכונה את שני המקורות כחוקיים:

script-src https://host1.com https://host2.com

לדוגמה, אם יש לך אפליקציה שטוענת את כל המשאבים שלה רשת להעברת תוכן (למשל, https://cdn.example.net), ויודעים שאתם לא צריכים תוכן ממוסגר או יישומי פלאגין, המדיניות שלך עשויה להיראות משהו כמו:

Content-Security-Policy: default-src https://cdn.example.net; child-src 'none'; object-src 'none'

פרטי ההטמעה

יוצגו לך כותרות X-WebKit-CSP ו-X-Content-Security-Policy במקומות שונים ומדריכים באינטרנט. מעכשיו והלאה, צריך להתעלם מהקידומת הזו כותרות עליונות. דפדפנים מודרניים (למעט IE) תומכים בקבצים ללא קידומת הכותרת Content-Security-Policy. זו הכותרת שבה צריך להשתמש.

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

רשימת המקורות בכל הוראה גמישה. ניתן לציין מקורות לפי סכימה (data:, https:) או טווח ספציפי של שמות מארח בלבד (example.com, שתואם לכל מקור במארח הזה: כל סכימה, כל יציאה) אל URI מוגדר במלואו (https://example.com:443, שתואם רק ל-HTTPS, בלבד) example.com, ורק יציאה 443). אפשר להשתמש בתווים כלליים לחיפוש, אבל רק כסכימה, יציאה, או במיקום השמאלי ביותר של שם המארח: *://*.example.com:* תואמים לכל תת-הדומיינים של example.com (אבל לא את example.com עצמו), באמצעות כל סכימה, בכל יציאה.

רשימת המקורות מקבלת גם ארבע מילות מפתח:

  • כמו שאפשר לצפות, 'none' לא תואם לכלום.
  • 'self' תואם למקור הנוכחי, אבל לא לתתי-הדומיין שלו.
  • 'unsafe-inline' מאפשר JavaScript ו-CSS מוטבעים. (ניגש לנושא הזה נוסיף עוד פרטים.)
  • 'unsafe-eval' מאפשר מנגנונים של המרת טקסט ל-JavaScript, כמו eval. (נקבל גם כאן.)

למילות המפתח האלה צריך להוסיף מירכאות יחידות. לדוגמה, script-src 'self' (עם מירכאות) מאשר הפעלה של JavaScript מהמארח הנוכחי. script-src self (ללא מירכאות) מאפשר JavaScript משרת בשם "self" (ולא המארח הנוכחי), שסביר להניח שזו לא מה שהתכוונת.

הרצה בארגז חול

יש עוד הוראה אחת שכדאי לדבר עליה: sandbox. במידה מועטה שונות מאלה שבדקנו, מכיוון שיש הגבלות על פעולות הדף יכול לדרוש במקום משאבים שהדף יכול לטעון. אם קיימת ההוראה sandbox, הדף נחשב כאילו הוא נטען בתוך <iframe> עם המאפיין sandbox. פעולה זו יכולה לכלול מגוון רחב של השפעה על הדף: אילוץ הדף למקור ייחודי ומניעת צורה שליחה של תכנים, בין היתר. הוא קצת חורג מהיקף המאמר הזה, אבל אפשר למצוא פרטים מלאים על מאפיינים חוקיים של ארגז חול (sandboxing) "Sandboxing" של מפרט ה-HTML5.

מטא תג

מנגנון המסירה המועדף ל-CSP הוא כותרת HTTP. עם זאת, המדיניות יכולה להיות שימושית, כדי להגדיר מדיניות בדף ישירות בתגי העיצוב. עושים זאת באמצעות תג <meta> עם מאפיין http-equiv:

<meta
  http-equiv="Content-Security-Policy"
  content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'"
/>

לא ניתן להשתמש באפשרות הזו עבור frame-ancestors, report-uri או sandbox.

קוד מוטבע נחשב מזיק

צריך להיות ברור ש-CSP מבוסס על המקורות ברשימת ההיתרים, כי דרך חד-משמעית להורות לדפדפן לטפל בקבוצות ספציפיות של משאבים כמו שהם מקובלים, ולדחות את השאר. אי אפשר להשתמש ברשימות היתרים שמבוססות על מקור. עם זאת, ניתן לפתור את האיום הגדול ביותר שנובע ממתקפות XSS: החדרת סקריפט מוטבע. אם תוקף יכול להחדיר תג סקריפט שמכיל ישירות תוכן זדוני כלשהו מטען ייעודי (payload) (<script>sendMyDataToEvilDotCom();</script>), לדפדפן אין מנגנון שלפיו אפשר להבדיל בינו לבין תג סקריפט מוטבע. CSP פותר את הבעיה הזו על ידי חסימה מלאה של סקריפט מוטבע: זו הדרך היחידה לוודא זאת.

החסימה הזו כוללת לא רק סקריפטים שמוטמעים ישירות בתגי script, אלא גם גורמים המטפלים באירועים מוטבעים, ו-javascript: כתובות URL. צריך להעביר את התוכן של script תגים בקובץ חיצוני, ומחליפים javascript: כתובות URL ואת <a ... onclick="[JAVASCRIPT]"> בקריאות addEventListener() מתאימות. לדוגמה, אפשר לשכתב את הדברים הבאים מ:

<script>
  function doAmazingThings() {
    alert('YOU AM AMAZING!');
  }
</script>
<button onclick="doAmazingThings();">Am I amazing?</button>

משהו כמו:

<!-- amazing.html -->
<script src="amazing.js"></script>
<button id="amazing">Am I amazing?</button>

<div style="clear:both;"></div>
// amazing.js
function doAmazingThings() {
  alert('YOU AM AMAZING!');
}
document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('amazing').addEventListener('click', doAmazingThings);
});

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

המערכת מתייחסת לסגנון בתוך השורה באותו אופן: גם במאפיין style וגם במאפיין style יש לאחד את התגים לגיליונות סגנון חיצוניים כדי להגן מפני מגוון של חכם באופן מפתיע שיטות לזליגת נתונים ששירות CSS מאפשר.

אם נדרשים סקריפט וסגנון מוטבעים, אפשר להפעיל אותם על ידי הוספה של 'unsafe-inline' כמקור מותר ב-script-src או ב-style-src של Google. אפשר גם להשתמש בגיבובים (hash) או בצפנים חד-פעמיים (ראו בהמשך), אבל מומלץ שלא לעשות זאת. חסימה של סקריפט מוטבע היא השיפור הגדול ביותר בתחום האבטחה שמספק CSP, וגם חסימת סגנון מוטבע גם מקשה את האפליקציה שלך. מדובר במידה מועטה כדי להבטיח שדברים יפעלו כראוי לאחר העברת כל הקוד לא רשמי, אבל זה שילוב שכדאי לעשות.

אם אתם חייבים להשתמש בו לגמרי,

רמת ה-CSP ברמה 2 מאפשרת תאימות לאחור לסקריפטים מוטבעים להוסיף לרשימת ההיתרים סקריפטים ספציפיים מוטבעים, באמצעות צופן קריפטוגרפי (מספר פעם אחת) או לבצע גיבוב (hash). למרות שזה אולי מסורבל, הוא מועיל בתנועת צביטה.

כדי להשתמש בצפנים חד-פעמיים, צריך לתת לתג הסקריפט מאפיין צופן חד-פעמי (nonce). הערך צריך להתאים לאחד מופיע ברשימת המקורות המהימנים. לדוגמה:

<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
  // Some inline code I can't remove yet, but need to asap.
</script>

עכשיו מוסיפים את הצופן החד-פעמי (nonce) להוראה script-src שמצורף למילת המפתח nonce-.

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

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

גיבובים פועלים באותה שיטה. במקום להוסיף קוד לתג הסקריפט, יוצרים גיבוב SHA של הסקריפט עצמו ומוסיפים אותו להוראה script-src. לדוגמה, נניח שהדף מכיל:

<script>
  alert('Hello, world.');
</script>

המדיניות תכלול את הפרטים הבאים:

Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='

חשוב לציין כאן כמה דברים. הקידומת sha*- מציינת את האלגוריתם שיוצר את הגיבוב. בדוגמה שלמעלה, נעשה שימוש ב-sha256-. CSP גם יש תמיכה ב-sha384- וב-sha512-. כשיוצרים את הגיבוב, אין לכלול את התג <script> תגים. גם אותיות רישיות ורווחים לבנים, כולל בתחילת או רווח לבן בסוף.

חיפוש Google בנושא יצירת גיבובי SHA יוביל אותך לפתרונות מספר השפות. ב-Chrome בגרסה 40 ואילך, אפשר לפתוח את כלי הפיתוח ואז לטעון מחדש את הדף. הכרטיסייה 'מסוף' תכלול הודעות שגיאה עם גיבוב (hash) מסוג SHA256 לכל אחד מהסקריפטים המוטבעים.

גם ההערכה

גם כשתוקף לא יכול להחדיר את הסקריפט ישירות, הוא יכול להערים על משתמשים שהאפליקציה שלכם ממירה טקסט פנימי ל-JavaScript להפעלה. ולהוציא אותו מטעמם. eval(), חדשה Function() , setTimeout([string], ...), ו- setInterval([string], ...) הם כל הווקטורים שדרכם הוחדרו טקסט עלול לגרום למשהו זדוני באופן בלתי צפוי. ברירת המחדל של CSP תגובה לסיכון הזה היא לחסום לחלוטין את כל הווקטורים האלה.

יש לכך לא מעט השפעות על אופן הפיתוח של האפליקציות:

  • צריך לנתח JSON דרך JSON.parse המובנה במקום להסתמך על eval. פעולות JSON נייטיב זמינות בכל דפדפן מאז IE8, בטוחה לחלוטין.
  • חשוב לכתוב מחדש את כל השיחות מסוג setTimeout או setInterval שנשלחות באמצעות פונקציות בתוך השורה ולא מחרוזות. לדוגמה:
setTimeout("document.querySelector('a').style.display = 'none';", 10);

עדיף לכתוב כך:

setTimeout(function () {
  document.querySelector('a').style.display = 'none';
}, 10);
  • מומלץ להימנע מיצירה של תבניות בזמן ריצה: ספריות רבות ליצירת תבניות משתמשות ב-new Function() באופן חופשי כדי לזרז את יצירת התבניות בזמן הריצה. אלה של תכנות דינמי, אבל היא בסיכון של לבדוק טקסט זדוני. חלק מה-frameworks תומכות ב-CSP מחוץ לאריזה, חוזרים למנתחת חזקה בהיעדר eval. הוראת ng-csp של AngularJS ודוגמה טובה לכך.

עם זאת, עדיף להשתמש בשפה ליצירת תבניות מראש (Handlebars עושה, למשל). הרכבה מראש של התבניות יכולה לשפר את חוויית המשתמש מהר יותר מההטמעה המהירה ביותר של סביבת זמן הריצה, והיא גם בטוחה יותר. אם הערך הוא ו- רשתות הטקסט ל-JavaScript שלו חיוניות לאפליקציה שלך, ניתן להפעיל אותם על ידי הוספה של 'unsafe-eval' כמקור מותר ב-script-src אבל מאוד לא מומלץ לעשות זאת. חסימת היכולת לבצע מחרוזות מקשות הרבה יותר על התוקף לבצע באתר שלכם.

דיווח

היכולת של CSP לחסום משאבים לא מהימנים בצד הלקוח היא יתרון ענק בשביל אבל כדאי להוסיף סוג כלשהו של התראה נשלחים בחזרה לשרת כדי שתוכלו לזהות ולסגור באגים שמאפשרים החדרה זדונית מלכתחילה. כדי לעשות זאת, אפשר להורות דפדפן POST מדווח למיקום כלשהו על הפרת מדיניות בפורמט JSON שמצוין בהוראה report-uri.

Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;

הדוחות האלה ייראו בערך כך:

{
  "csp-report": {
    "document-uri": "http://example.org/page.html",
    "referrer": "http://evil.example.com/",
    "blocked-uri": "http://evil.example.com/evil.js",
    "violated-directive": "script-src 'self' https://apis.google.com",
    "original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
  }
}

המידע הזה כולל קטע מידע טוב שיעזור לכם לאתר את הסיבה הספציפית להפרה, כולל הדף שבו ההפרה התרחש (document-uri), הגורם המפנה של הדף (שימו לב שבניגוד ל-HTTP), בשדה הכותרת, המפתח לא מאוית בצורה שגויה), המשאב שהפר את המדיניות של הדף (blocked-uri), ההוראה הספציפית שהוא הפר (violated-directive), והמדיניות המלאה של הדף (original-policy).

דוח בלבד

אם אתם רק מתחילים להשתמש ב-CSP, כדאי להעריך את הנתונים של האפליקציה שלך לפני ההשקה של מדיניות דרקונית למשתמשים שלך. כצעד בדרך לפריסה מלאה, ניתן לבקש מהדפדפן לעקוב מדיניות, דיווח על הפרות אך לא אכיפה של ההגבלות. במקום שליחת כותרת Content-Security-Policy, שליחת הכותרת Content-Security-Policy-Report-Only.

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

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

שימוש בעולם האמיתי

אפשר להשתמש ב-CSP 1 ב-Chrome, ב-Safari וב-Firefox, אבל הוא מוגבל מאוד ב-IE 10. אפשר לראות פרטים ספציפיים בכתובת caniuse.com. CSP ברמה 2 זמין ב-Chrome מאז גרסה 40. אתרים גדולים כמו Twitter ו-Facebook פרסו את הכותרת (כדאי לקרוא את המקרה לדוגמה של Twitter), והתקן כבר מוכן כדי שתוכלו לפרוס באתרים שלכם.

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

תרחיש לדוגמה מס' 1: ווידג'טים של רשתות חברתיות

  • לחצן 1+ של Google כולל סקריפט מ-https://apis.google.com, ומטמיע <iframe> מ- https://plusone.google.com נדרשת מדיניות שכוללת את שני הפרטים האלה מקורות כדי להטמיע את הלחצן. מדיניות מינימלית היא script-src https://apis.google.com; child-src https://plusone.google.com. צריך גם כדי לוודא שקטע ה-JavaScript ש-Google מספקת יישלף לתוך בקובץ JavaScript חיצוני. אם הייתה לכם מדיניות שמבוססת על רמה 1 באמצעות frame-src רמה 2 דרשה לשנות אותו ל-child-src. הפעולה הזו לא נחוצה יותר ב-CSP ברמה 3.

  • לחצן הלייק של Facebook יש מספר אפשרויות הטמעה. מומלץ להמשיך עם גרסה אחת (<iframe>) כי היא נמצאת בארגז חול בטוח משאר האתר. הוא נדרשת הוראת child-src https://facebook.com כדי לפעול באופן תקין. הערה שכברירת מחדל, הקוד <iframe> ש-Facebook מספק טוען כתובת URL, //facebook.com. משנים את ההגדרה כדי לציין HTTPS באופן מפורש: https://facebook.com אין סיבה להשתמש ב-HTTP אם אין חובה לעשות זאת.

  • לחצן הציוץ ב-Twitter מסתמכת על גישה לסקריפט ולמסגרת, ששניהם מתארחים בכתובת https://platform.twitter.com. (Twitter מספקת גם כתובת אתר יחסית באמצעות default; לערוך את הקוד כך שיציין HTTPS כשמעתיקים/מדביקים אותו באופן מקומי.) הכול יהיה מוכן במסגרת script-src https://platform.twitter.com; child-src https://platform.twitter.com, כל עוד צריך להזיז את קטע הקוד של JavaScript ש-Twitter מספק לקובץ JavaScript חיצוני.

  • לפלטפורמות אחרות יש דרישות דומות, ואפשר להתייחס אליהן באופן דומה. מומלץ פשוט להגדיר default-src של 'none' ולבחון את המסוף שלך לקבוע אילו משאבים תצטרכו להפעיל כדי שהווידג'טים יפעלו.

קל לכלול כמה ווידג'טים: פשוט משלבים את המדיניות ולזכור למזג את כל המשאבים מאותו סוג לתוך של Google. אם רוצים להשתמש בכל שלושת הווידג'טים של הרשתות החברתיות, המדיניות הייתה כך:

script-src https://apis.google.com https://platform.twitter.com; child-src https://plusone.google.com https://facebook.com https://platform.twitter.com

תרחיש לדוגמה מס' 2: ללא 'ביטול נעילה עם טביעת אצבע'

נניח שאתם מנהלים אתר בנקאי ואתם רוצים לוודא רק המשאבים שכתבתם בעצמכם יכולים להיטען. במקרה הזה, להתחיל במדיניות ברירת מחדל שחוסמת לגמרי את כל התוכן (default-src 'none'), ולהתפתח משם.

נניח שהבנק טוען את כל התמונות, הסגנון והסקריפטים מ-CDN https://cdn.mybank.net, ומתחבר דרך XHR אל https://api.mybank.com/ אל למשוך למטה קטעי נתונים שונים. נעשה שימוש במסגרות, אך רק בדפים מקומיים באתר (ללא מקורות של צד שלישי). אין Flash באתר, אין גופנים, אין תוספות. כותרת ה-CSP המגבילה ביותר שאנחנו יכולים לשלוח היא:

Content-Security-Policy: default-src 'none'; script-src https://cdn.mybank.net; style-src https://cdn.mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com; child-src 'self'

תרחיש לדוגמה מס' 3: SSL בלבד

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

Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'

למרות שהשדה https: מצוין ב-default-src, הסקריפט והסגנון ההוראות לא יורשות באופן אוטומטי את המקור הזה. כל הוראה מוחלטת מחליפה את ברירת המחדל של סוג המשאב הספציפי הזה.

העתיד

Content Security Policy רמה 2 היא המלצה למועמד. קבוצת העבודה בנושא אבטחת אפליקציות אינטרנט של W3C כבר התחיל לעבוד על האיטרציה הבאה של המפרט, רמה 3 של Content Security Policy.

אם אתם מתעניינים בדיון על התכונות האלה, לעיין בארכיונים של רשימת התפוצה public-webappsec@, או להצטרף בעצמכם.

משוב