הטמעת ניפוי באגים ב-CSP ובסוגים מהימנים בכלי הפיתוח ל-Chrome

Kateryna Prokopenko
Kateryna Prokopenko
Alfonso Castaño
Alfonso Castaño

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

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

מהי מדיניות אבטחת תוכן?

מדיניות אבטחת תוכן (CSP) מאפשרת להגביל התנהגויות מסוימות באתר כדי להגביר את האבטחה. לדוגמה, אפשר להשתמש ב-CSP כדי לא לאפשר סקריפטים מוטבעים או כדי לא לאפשר את השימוש ב-eval. שניהם מצמצמים את שטח ההתקפה של מתקפות Cross-Site Scripting (XSS). מבוא מפורט ל-CSP זמין כאן.

מדיניות CSP חדשה במיוחד היא המדיניות בנושא סוגים מהימנים(TT), שמאפשרת לבצע ניתוח דינמי שיכול למנוע באופן שיטתי קבוצה גדולה של מתקפות באמצעות הזרקה באתרים. כדי להשיג זאת, TT תומך באתר בניהול קוד JavaScript שלו כדי לאפשר הקצאה של סוגים מסוימים בלבד של דברים ל-DOM sinks כגון innerHTML.

אתר יכול להפעיל מדיניות אבטחת תוכן על ידי הכללת כותרת HTTP מסוימת. לדוגמה, הכותרת content-security-policy: require-trusted-types-for 'script'; trusted-types default מפעילה את מדיניות TT של דף.

כל מדיניות יכולה לפעול באחד מהמצבים הבאים:

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

הטמעה של בעיות שקשורות למדיניות אבטחת התוכן בכרטיסייה בעיות

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

  1. הגדרת סיפורי משתמשים. לזהות קבוצת סיפורי משתמשים בממשק הקצה של כלי הפיתוח, שבה מוסבר איך מפתח אתרים יצטרך לחקור את הבעיה.
  2. הטמעה בממשק קצה. בהתאם לסיפורי המשתמשים, מזהים אילו פרטים נדרשים לחקירת הבעיה בממשק הקצה (למשל, בקשה קשורה, שם של קובץ cookie, שורה בסקריפט או בקובץ HTML וכו').
  3. זיהוי בעיות. זיהוי המקומות בדפדפן שבהם ניתן לזהות את הבעיה ב-Chrome ולמכשיר כדי לדווח על הבעיה, כולל המידע הרלוונטי משלב (2).
  4. שומרים את הבעיות ומציגים אותן. מאחסנים את הבעיות במקום מתאים ומגדירים אותן כזמינות לכלי הפיתוח לאחר הפתיחה
  5. עיצוב הטקסט של הבעיות. תנסח הסברים שיעזרו למפתח האתרים להבין, ומה שחשוב יותר, לתקן את הבעיה

שלב 1: הגדרת סיפורי משתמשים לגבי בעיות ב-CSP

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


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


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

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

שלב 2: הטמעה דרך ממשק הקצה

הפכנו את התובנה הזו לטיוטה הראשונה של המידע שרצינו להעמיד לרשות כלי הפיתוח דרך פרוטוקול כלי הפיתוח ל-Chrome (CDP):

בהמשך מופיע הקטע מ-third_party/blink/public/devtools_protocol/browser_protocol.pdl

 type ContentSecurityPolicyIssueDetails extends object
   properties
     # The url not included in allowed sources.
     optional string blockedURL
     # Specific directive that is violated, causing the CSP issue.
     string violatedDirective
     boolean isReportOnly
     ContentSecurityPolicyViolationType contentSecurityPolicyViolationType
     optional AffectedFrame frameAncestor
     optional SourceCodeLocation sourceCodeLocation
     optional DOM.BackendNodeId violatingNodeId

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

export interface ContentSecurityPolicyIssueDetails {
  /**
  * The url not included in allowed sources.
  */
  blockedURL?: string;
  /**
  * Specific directive that is violated, causing the CSP issue.
  */
  violatedDirective: string;
  isReportOnly: boolean;
  contentSecurityPolicyViolationType: ContentSecurityPolicyViolationType;
  frameAncestor?: AffectedFrame;
  sourceCodeLocation?: SourceCodeLocation;
  violatingNodeId?: DOM.BackendNodeId;
}

שנית, וכמובן יותר חשוב מכך, אנחנו יוצרים ספריית C++ מההגדרה שמטפלת ביצירה ושליחה של מבני הנתונים האלה מהשרת העורפי של C++ Chromium אל ממשק הקצה של DevTools. בספרייה הזו, ניתן ליצור אובייקט ContentSecurityPolicyIssueDetails באמצעות הקטע הבא של קוד C++:

protocol::Audits::ContentSecurityPolicyIssueDetails::create()
  .setViolatedDirective(d->violated_directive)
  .setIsReportOnly(d->is_report_only)
  .setContentSecurityPolicyViolationType(BuildViolationType(
      d->content_security_policy_violation_type)))
  .build();

לאחר שקבענו איזה מידע אנחנו רוצים להציג, היה עלינו לבדוק מאיפה משיגים את המידע הזה ב-Chromium.

שלב 3: זיהוי בעיות

כדי שהמידע יהיה זמין לפרוטוקול Chrome DevTools Protocol (CDP) בפורמט המתואר בקטע הקודם, היה עלינו למצוא את המקום שבו המידע היה זמין בפועל בקצה העורפי. למרבה המזל, לקוד ה-CSP כבר היה צוואר בקבוק ששימש למצב דוחות בלבד, והצלחנו להתחבר אליו: ContentSecurityPolicy::ReportViolation מדווח על בעיות לנקודת קצה (endpoint) של דיווח (אופציונלית) שניתן להגדיר בכותרת ה-HTTP של CSP. רוב המידע שרצינו לדווח עליו כבר היה זמין, ולכן לא היה צורך בשינויים גדולים בקצה העורפי כדי שהכלים שלנו יפעלו.

שלב 4: שמירה והצגה של הבעיות

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

בזאת הסתיימה העבודה העורפית, ועכשיו היה עלינו להתמקד בהצגת הבעיה בממשק הקצה.

שלב 5: עיצוב הטקסט של הבעיות

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

בדרך כלל צוות כלי הפיתוח יתחיל עם טיוטה כללית של מה שהוא חושב:


## Header
Content Security Policy: include all sources of your resources in content security policy header to improve the functioning of your site

## General information
Even though some sources are included in the content security policy header, some resources accessed by your site like images, stylesheets or scripts originate from sources not included in content security policy directives.

Usage of content from not included sources is restricted to strengthen the security of your entire site.

## Specific information

### VIOLATED DIRECTIVES
`img-src 'self'`

### BLOCKED URLs
https://imgur.com/JuXCo1p.jpg

## Specific information
https://web.dev/strict-csp/

אחרי איטרציה, הגענו אל:

ALT_TEXT_HERE

כמו שאפשר לראות, שיתוף הצוות עם DevRel ועם DevRel הופך את התיאור לברור ומדויק יותר!

אפשר למצוא את הבעיות ב-CSP בדף גם בכרטיסייה שמוקדשת ספציפית להפרות של מדיניות CSP.

ניפוי באגים בעיות בסוגים מהימנים

עבודה עם TT בקנה מידה גדול יכולה להיות מאתגרת ללא הכלים למפתחים הנכונים.

הדפסת מסופים משופרת

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

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

הטיפול בהתאמה אישית הזה בוצע ב-V8 מסיבות היסטוריות, אבל לגישה כזו יש חסרונות חשובים. קיימים אובייקטים רבים שמחייבים הצגה בהתאמה אישית, אבל הסוג שלהם זהה ברמת ה-JS. מאחר ש-V8 הוא JS טהור, הוא לא יכול להבחין בין מושגים שתואמים ל-Web API, כגון 'סוג מהימן'. לכן, V8 צריך לבקש מההטמעה (Blink) שלו עזרה כדי להבדיל ביניהן.

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

  • לכל כלי הטמעה יכולה להיות אפשרות ליצור תיאורים משלו
  • הרבה יותר קל ליצור תיאור באמצעות Blink API
  • למצמוץ יש גישה להגדרה המקורית של האובייקט. לכן, אם אנחנו משתמשים ב-.toString() כדי ליצור את התיאור, אין סיכון שהאפליקציה .toString() תוגדר מחדש.

הפרת זכויות יוצרים (במצב דיווח בלבד)

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

כלי הפיתוח כבר תומכים במגוון רחב של נקודות עצירה (breakpoint), כך שהארכיטקטורה ניתנת להרחבה. כדי להוסיף סוג חדש של נקודת עצירה (breakpoint), צריך לבצע שינויים בקצה העורפי (Blink), ב-CDP ובממשק הקצה. אנחנו צריכים להציג פקודת CDP חדשה, שנקרא אותה setBreakOnTTViolation. הפקודה הזו תשמש את הקצה העורפי כדי לקבוע איזה סוג של הפרות TT הוא צריך לפרוץ. הקצה העורפי, ובמיוחד InspectorDOMDebuggerAgent, יספק "בדיקה" (onTTViolation()) שייקרא בכל פעם שיש הפרה שקשורה ל-TT. לאחר מכן, InspectorDOMDebuggerAgent יבדוק אם ההפרה הזו צריכה להפעיל נקודת עצירה (breakpoint). אם זה המצב, תישלח הודעה לממשק הקצה כדי להשהות את הביצוע.

מה נעשה ומה השלב הבא?

מאז שהבעיות המתוארות כאן מוצגות, הכרטיסייה בעיות עברה כמה שינויים:

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

הורדת הערוצים של התצוגה המקדימה

כדאי להשתמש ב-Chrome Canary, Dev או Beta כדפדפן הפיתוח בברירת מחדל. ערוצי התצוגה המקדימה האלה נותנים לך גישה לתכונות החדשות של כלי הפיתוח, בודקים ממשקי API מתקדמים של פלטפורמת האינטרנט ומוצאים בעיות באתר לפני שהמשתמשים יגלו אותן!

יצירת קשר עם צוות כלי הפיתוח ל-Chrome

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

  • שלחו לנו הצעה או משוב דרך crbug.com.
  • כדי לדווח על בעיה בכלי הפיתוח, לוחצים על אפשרויות נוספות   עוד   > עזרה > דיווח על בעיות בכלי הפיתוח בכלי הפיתוח.
  • אפשר לשלוח ציוץ אל @ChromeDevTools.
  • אפשר לכתוב תגובות לגבי 'מה חדש' בסרטוני YouTube בכלי הפיתוח או בסרטונים ב-YouTube בקטע 'טיפים לשימוש בכלי הפיתוח'.