את פרוטוקול הHTTP – Hypertext Transfer Protocol כולנו מכירים. בעזרת פרוטוקול זה ניתן להעביר את דפי הHTML והאובייקטים הקיימים בהם ברשת האינטרנט וברשתות האינטראנט (רשתות אינטרנט פרטיות). לכל בקשת HTTP שנשלחת מצד הלקוח (הדפדפן) ותגובת HTTP שנשלחת מצד השרת כמענה לבקשת הדפדפן מצורפים כותרות הבקשה (Headers). כותרות אלו מכילות מידע רב על הלקוח והשרת, כאשר האחרון זה מה שבעיקר מעניין אותנו. בעזרת כותרות התגובה (response Headers) יכול תוקף פוטנציאלי להשיג מידע רב על השרת, מה שיסייע לו בהכנת הסביבה לתקיפה ובמיקוד תקיפתו. לדוגמה: אם הheader X-Powered-By המציג את שפת צד השרת המשמשת את האתר + גרסת השפה הפועלת באתר אינו מוסתר, יכול התוקף, בפרט אם גרסת השפה אינה מעודכנת, לחפש פגיעויות שנמצאו באותה גרסה ובכך למצוא את הדרך לתקוף את האתר.
בעקבות כך, על מתכנתי האתר להסתיר את הheaders הרגישים מיוזמתם ולצמצמם את הסיכון האפשרי. אם הדבר לא נעשה ע"י מתכנתי האתר, הרי שבאתר ישנה פרצת אבטחה. לפרצה זו קוראים information disclosure, כלומר – אינפורמציה גלויה על המערכת. חשיפת הheaders כחלק מהinforamtion disclouser אומנם לא נחשבת לפריצה חמורה, אך מן הראוי להימנע ממנה ולא להפוך את העבודה לקלה יותר עבור האקרים זדוניים.
במאמר הבא אציג לפניכם את הרשימה המלאה של הrespinse headers + הסבר על כל header וheader ודוגמה למימוש שלו. בסופו של המאמר אציג את הheaders שחושפים אותנו לinformation disclosure ואת הדרך להסיר את התצוגה של הheaders בשפות צד השרת השונות.
ראשית, כיצד אנו יכולים לראות את הresponse headers של האתר בו אנו גולשים?
למעשה, כל תוכנה המאפשרת לנו לנתח את חבילות הHTTP שאנו מעבירים, תאפשר לנו גם לראות את כלל הheadeers שהועברו. במקרה הזה, אנו לא ננדוד הרחק ונשתמש בכלי המפתחים של דפדפן chrome.נלחץ דאבל-קליק ומיד לאחר מכן על inspact (בדוק), לחילופין – נשתמש בקיצור המקלדת המיועד עבור כך (ctrl+shift+i). כעת תוצג לנו לשוניות הchrome development tool.
נבחר בלשונית network שתציג לנו את חבילות המידע שעוברות ביננו לבין הצד שרת, נלחץ על ctrl+r ל'הקלטת' החבילות והצגתן. כעת אם נלחץ על אחת החבילות, נוכל לראות תחת הלשונית headers את הresponse headers ואת הrequest headers.
שם הheader | תיאור | דוגמה |
---|---|---|
Accept-Ranges | טווח (range) זוהי בקשה אפשרית של הלקוח מצד השרת להציג בפניו רק חלק מקובץ במקום את הקובץ השלם. לדוגמה, אם לקוח זקוק רק ל10Bays של קובץ בעל 70MB, הוא יכול לבקש מהשרת לקזז את הטווח ולהביא לו רק את ה10bays האחרונים. לשונית הAccept-ranges מציין האם השרת תומך באפשרות זו או לא. | Accept-Ranges: bytes
Accept-Range: none |
Accept-Patch | Patch זוהי בקשת HTTP המאפשרת לצד הלקוח לבקש מצד השרת שינוי משאבים חלקי. לדוגמא, בעת שינוי שדה ספציפי של טופס, במקום שהשרת יצטרך לשלוח לצד הלקוח את כל הטופס מחדש (בקשת PUT), הוא מעדכן באופן ספציפי את השדה. Accept-Patch מציין אלו סוגי מדיה השרת מסוגל להבין וממילא באלו PATCH אפשרי. במידה והשרת מקבל בקשה לסוג מדיה שאינו מבין, הוא יחזיר סטטוס תגובה 415 ויציין בAccept-Patch את המדיות שכן נתמכות | Accept-Patch: application/merge-patch+json |
Access-Control-Allow-Origin | מציין אילו שרתים יוכלו לבקש מידע ולקבלו, במסגרת הCORS (התגברות על הsame-origin policy ושליחת בקשת ajax לקריאת נתונים). אם שני המושגים האחרונים לא נהירים לכם, מומלץ שתעצרו לרגע ותקראו עליהם | * :Access-Control-Allow-Origin |
Access-Control-Allow-Credentials | מציין האם לחשוף את הלקוח כחלק תגובת השרת, במסגרת הCORS, גם לקוד הjavascript של הדף. אם השדה מכיל את הערך True, הדפדפן יוכל להיחשף לקוד הjavascript. חשוב לציין שגם אם הערך הוא True, ע"מ להיחשף לjavascript, הדפדפן צריך לשלוח בבקשה גם את הRequest.certificates (לרוב מדובר במזהה הCookie) | Access-Control-Allow-Credentials: true |
Access-Control-Expose-Headers | מציין אלו headers יוכלו לעבור במסגרת הCORS כחלק מתגובה לבקשת הajax. כברירת מחדל, רק שישה headers, הנחשבים לבטוחים יכולים לעבור. אם אנו רוצים להתיר זאת לheaders נוספים, אנו צריכים לציין את שמותיהם תחת שדה זה | Access-Control-Expose-Headers: X-Kuma-Revision |
Access-Control-Allow-Methods | מציין את צורות שליחת המידע המותרות, כאשר משתמשים בCROS. נשלח כתגובה לבקשת preflight הנשלחת קודם לבקשת ajax במסגרת הCORS ובודקת מול השרת את מאפייני הCORS בהם הוא משתמש | Access-Control-Allow-Methods: POST, GET |
Access-Control-Allow-Headers | מציין את הheaders המותרים בשליחת בקשה לשרת במסגרת הCROS. גם שדה זה נשלח כתגובה לבקשת preflight הנשלחת קודם לבקשת ajax במסגרת הCORS ובודקת מול השרת את מאפייני הCORS בהם הוא משתמש. שדה זה רלוונטי בעיקר אם הלקוח משתמש בכותרת Access-Control-Request-Headers המיידעת את השרת קודם שליחת הבקשה אלו headers הלקוח עשוי לשלוח | Access-Control-Allow-Headers: X-Custom-Header |
Access-Control-Max-Age | מציינת כמה זמן (בשניות) ניתן לשמור את הheaders שנשלחו כתגובה לבקשת הprefilght ולפעול על-פיהם, כלומר: הערכים של הכותרות Access-Control-Allow-Methods וAccess-Control-Allow-Headers | Access-Control-Max-Age: 600 |
Age | הזמן בשניות שהאובייקט היה במטמון, לפני שהוצג לנו. אם השדה מכיל 0 בדיוק, ככל הנראה מדובר באובייקט שנלקח ישירות משרת המקור. | Age: 51125 |
Allow | שיטות שליחת המידע הנתמכות ע"י השרת. כשהשרת מחזיר סטטוס תגובה 405, כלומר – מתודה שאינה מורשית. ניתן להסתכל בheader זה ע"מ לראות אלו שיטות כן נתמכות | Allow: GET, POST |
Alt-Svc | מציין שרתים חילופיים שאיתם ניתן להגיע למידע, או פרוטוקולים שונים על אותו שרת. יכיל פעמים רבות גם את הערך ma המסמן כמה זמן השרת החילופי יישאר פעיל | ;Alt-Svc: h2=":443"; ma=259200 |
Cache-Control | מכיל הוראות למטמון, כיצד לשמור את המידע אם בכלל | Cache-Control: must-revalidate |
Connection | מציין האם החיבור יישאר פתוח לאחר סיום קבלת המשאב. במקום לפתוח חיבור חדש בכל שליחת בקשה ותגובה, ניתן להשאיר את החיבור פתוח ובו לשלוח עוד בקשות/תגובות | Connection: keep-alive Connection: close |
Content-Disposition | מציין את צורת העיבוד של התגובה שחזרה: האם התגובה תוצג כחלק מדף האינטרנט או שתרד למחשב היעד כקובץ מצורף. לheader זה קיים מימוש נוסף בהודעות MIME, אך לא מדובר במימוש הסטנדרטי ולא נתייחס למימוש זה | "Content-Disposition: attachment; filename="cool.html |
Content-Encoding | מציג אלו קידודים הוחלו על המידע. ההמלצה היא לדחוס נתונים ככל האפשר ולכן להשתמש בשדה זה, אך סוגים מסוימים של משאבים, כגון תמונות jpeg, כבר דחוסים. לפעמים, שימוש בדחיסה נוספת אינו מפחית את גודל חבילת המידע ואף יכול להאריך את גודלה. | Content-Encoding: gzip |
Content-Language | מציג לדוברי איזו שפה המידע שבדף האינטרנט מיועד. אם מצויין אנגלית, זהו לא בהכרח שהדף הוא באנגלית. ייתכן שהוא בעברית, אך הוא מיועד לדוברי אנגלית. כלומר: הדגש הוא למי המידע מיועד ולא באיזו שפה המידע נכתב | Content-Language: en |
Content-Length | גודל המידע שנשלח מצד השרת בחבילת הHTTP, בבתים (bytes). | content-length: 6553 |
Content-MD5 | משמשת שרתים כדי לספק בדיקת אמינות ותקינות הודעות לגוף ההודעה, בעזרת גיבוב המידע עם אלגוריתם הגיבוב הפופולרי (והלא הכי מאובטח אגב) MD5 והשוואת הפלט בזמן שליחת המידע ולאחר קבלתה אצל הלקוח | ==Content-MD5: Q7h1Y3ogSW51KwDIBMA5IQ |
Content-Type | שדה המציין את פורמט המידע שנשלח מצד השרת. שדה חשוב מאד | Content-Type: text/html |
Date | התאריך והשעה בהם נוצרה התגובה שנשלחה בחבילת המידע ע"י צד השרת | Date: Wed, 16 Oct 2020 07:28:00 GMT |
Delta-Base | מציין את תג הבסיס של קידוד הדלתא של האובייקט, אם ישנו שימוש בקידוד זה. קידוד דלתא מאפשר שינוי ערכים ספציפיים באובייקטים ובכך מצמצם את רוחב הפס הנדרש בעדכון האובייקט כולו מחדש. | "Delta-Base: "abc |
ETag | מכיל מזהה לגרסה הספציפית של האובייקט ובכך מאפשר למטמונים להיות יעילים יותר ולחסוך רוחב פס, מכיוון ששרת האינטרנט אינו צריך לשלוח תגובה מלאה מחדש אם התוכן לא השתנה | "ETag: "33a64df551425fcc58e4d42a148795d9f25f89d6 |
Expires | מציג את התאריך והשעה שלאחריהן נחשב שעבר זמנה של חבילת המידע שנשלחה ע"י השרת והיא כבר לא תהיה רלוונטית | Expires: Wed, 21 Oct 2020 07:28:00 GMT |
Last-Modified | בכותרת זו השרת מציין את התאריך והשעה שבהם הוא מאמין שהמשאב שונה לאחרונה. מטרתו לקבוע לקבוע אם משאב שהתקבל השתנה ויש צורך לשולחו מחדש. פחות מדוייק מETag | Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT |
Link | בכותרת זו השרת מציין ללקוח לינקים שיכילו מידע נוסף אודות המשאב שהתבקש מהשרת | link:<https://example.com>; rel="preconnect" |
Location | בכותרת זו השרת מציין לאן להפנות מחדש את הלקוח, אם הייתה גישה למשאב בלתי מורשה, או כל סיבה אחרת. לדוגמה: אם משתמש לא רשום מנסה להיכנס למתחם של משתמשים רשומים, הוא יופנה עם location לדף ההתחברות | Location: /index.html |
P3P | מטרתו של שדה זה היא לציין את מדיניות הP3P הנהוגה ע"י השרת. P3P זהו פרוטוקול מיושן המאפשר לאתרים להכריז על השימוש המיועד שלהם במידע שהם אוספים על הגולשים ובכך לאפשר לגולשים לבחור האם הם מסכימים למסירת המידע הזה ובהתאם לכך לנהל את מעברי הcookies בין הדפדפן לשרת. שדה זה כבר אינו בשימוש בשל חוסר אפקטיביות ובעיות שונות. עם-זאת, אתרים רבים, כמו google וfacebook משתמשות בו עם טקסט שמסביר מדוע הם לא יכולים להשתמש בו, זאת ע"מ להערים על הדפדפן התומכים במדיניות הP3P, כביכול המדיניות ממומשת ובכך לקבל גישה לעוגיות צד שלישי | p3p: CP="This is not a P3P policy! See example.com for more info." |
Proxy-Authenticate | מגדירה את שיטת האימות שיש להשתמש בה בכדי לקבל גישה למשאב שמאחורי שרת proxy. בעזרת שיטות אימות זו מאמת הלקוח את הבקשה מול שרת הproxy ומאפשר לו להעביר את הבקשה הלאה. header זה מגיע יחד עם סטטוס 407 המציין כי חסרים אישורי אימות לשרת הproxy | Proxy-Authenticate: Basic |
Retry-After | header שרלוונטי במקרים שהשרת מחזיר סטטוס 503 (שירות לא זמין), 429 (יותר מדיי בקשות) ו301 (העברה לדף אחר). מטרתו לציין כמה זמן יש לחכות עד לביצוע ניסיון מחדש (או במקרה של סטטוס 301: ביצוע ההפניה) לאתר | Retry-After: Wed, 21 Oct 2015 07:28:00 GMT |
Server | header המציין את פרטיו של השרת | Server: Apache/2.4.1 (Unix) |
Set-Cookie | משמש לשליחת אסימוני Cookie מהשרת לדפדפן, במטרה שישמשו את הדפדפן לאימות מול השרת. כדי לשלוח מספר Cookie, יש לשלוח מספר כותרות של אסימוני Cookie באותה התגובה | Set-Cookie: sessionId=38afes7a8 |
Strict-Transport-Security | header המממש את פרוטוקול HSTS ומודיע לדפדפנים כי יש לגשת אליו רק באמצעות HTTPS, כאשר כל ניסיון התחברות ב- HTTP יופנה אוטומטית לHTTPS. בערך של הheader (עיין דוגמה) מצויין משך הזמן שיש לשמור על הHTTPS והכללת סאב-דומיינים | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload |
Trailer | מאפשר לשולח לכלול שדות נוספים בסוף חבילות המידע ע"מ לספק מטא-נתונים נוספים | Trailer: Max-Forwards |
Transfer-Encoding | בשדה זה צד השרת מציין את צורת הקידוד המשמשת להעברת גוף החבילה בבטחה למשתמש (הקידוד שנועד עבור העברת הנתונים, לא את הקידוד שמוחל על הנתונים בלי קשר להעברתם, קידוד אשר נשלח תחת Content-Encoding) | Transfer-Encoding: gzip |
Tk | נועד לציין את סטטוס המעקב שהוחל מצד צד השרת על בקשת הלקוח. יכול להכיל כתשעה ערכים של מצבים אפשריים | Tk:N |
Vary | מטרתה לקבוע כיצד להתאים כותרות בקשה עתידיות, ע"מ להחליט אם ניתן להשתמש במטמון במקום לבקש תגובה חדשה מהשרת. לדוגמא, אם הערך שנציין בכותרת זו יהיה User-Agent, אנו קובעים לדפדפן לקחת בחשבון את header זה כבסיס להחלטה האם להשתמש במטמון או לא, שכן אם לדוגמא האתר מגיש תוכן שונה למשתמשים ניידים, על הדפדפן להיזהר לא להציג לו את המטמון של משתמשים אחרים | Vary: User-Agent |
Via | מטרתו להודיע ללקוח על שרתי הפרוקסי דרכם הועברה התגובה. מבצע למעשה פעולה דומה לפעולה של הכותרת Via הנשלחת ע"י הלקוח, רק בכיוון ההפוך | Via: 1.0 fred, 1.1 p.example.net |
Warning | שדה זה מציין בעיות שהתגלו במהלך שליחת ההודעה. במקרה של יותר משגיאה אחת, הכותרת תופיע יותר מפעם אחת | Warning: 110 anderson/1.3.37 "Response is stale" |
WWW-Authenticate | כותרת שנשלחת יחד עם סטטוס התגובה 401 (גישה שאינה מורשת) ומגדירה את שיטת האימות שיש להשתמש בה בכדי לקבל גישה למשאב. | WWW-Authenticate: Basic realm="Access to the staging site", charset="UTF-8" |
X-Frame-Options | שדה חשוב מאד שמציין האם יתאפשר לאתרים אחרים לבצע iframe על האתר שלנו. בעזרת חסימת האפשרות בכותרת זו אנו מונעים מתקפות clickjacking | X-Frame-Options: DENY |
Content-Security-Policy | עוד כותרת חשובה שמציינת האם האתר תומך בCSP. הCSP זוהי השיטה הטובה ביותר למניעת xss, בעזרת חסימת אפשרות טעינת סקריפטים שנטענים באתר עצמו או שיובאו ממקורות שלא צויין בכותרת זו שיש להתיר טעינת סקריפטים מהם. | Content-Security-Policy: default-src https: 'unsafe-eval' 'unsafe-inline'; object-src 'none' |
Refresh | כותרת המשמשת לציון זמן נתון (בשניות) לאחריו על הדף לרענן את עצמו או להפנות את את הגולש לדף אחר. מהווה תחליף לשימוש בMeta refresh | Refresh: 5; url=https://www.cyber-eliya.com |
Timing-Allow-Origin | משמש לציון המקורות המורשים לקרוא את ערכי התכונות שנלקחו מתכונות ה- API של תזמון משאבים (תכונה שנועדה לציין את משך הזמן לטעינת משאבים) | * :Timing-Allow-Origin |
Status | מציין את סטטוס תגובת השרת. טווח התגובות הוא החל מ100 ועד ל599, כאשר הסטטוס הסטנדרטי במקרה של הצלחה בקבלת התגובה הוא 200 | status: 200 ok |
X-Powered-By | מציין את שפת צד השרת (לדוגמא ASP.NET, PHP וכו') | X-Powered-By: PHP/7.0 |
X-Content-Duration | רלוונטי רק עבור דפדנים המשתמשים במנוע התצוגה Gecko (כגון firefox) ומטרתו לציין את משך הזמן הוידאו/אודיו אשר נשלח מצד השרת בשניות, ע"מ ליידע את הדפדפן, שיפעל בהתאם בעת ההצגה למשתמש | X-Content-Duration: 92.6 |
X-Content-Type-Options | משמשת את השרת כדי לציין כי אין לשנות את סוגי ה- MIME (הפורמטים של המסמך) המפורסמים בכותרות Type-Content. מטרתו למנוע מהשרת לבצע רחרוח וניסיון לאתר באופן עצמאי את סוג הcontent-type | X-Content-Type-Options: nosniff |
X-XSS-Protection | מטרתו למנוע ביצוע מתקפות Cross Site Scripting באתר, בעזרת מניעת טעינה של דפים כאשר הדפדפן מזהה xss | X-XSS-Protection: 1; mode=block |
X-Request-ID, X-Correlation-ID | מטרתו לבצע תיאום בין צד הלקוח לצד השרת בשליחת חבילות מידע, כך שאם תהיה שגיאה, יוכל השרת לטפל בה באופן מהיר ומדויק יותר. הלקוח שולח בתחילת השיחה ערך X-Request שצד השרת יישלח מעתה יחד עם כל חבילה, ובמקרה של שגיאה, שולח צד הלקוח לצד השרת את המזהה המדובר, כך שצד השרת יוכל לזהות את השיחה באופן מהיר יותר | X-Request-ID: od951erd6-02f7-4d3f-242b-61434e8cde5 |
X-UA-Compatible | מציין באיזו גרסה של הדפדפן יש להשתמש עבור עיבוד הנתונים. נועד בעיקר עבור תאימות לאור | X-UA-Compatible: IE = 9 |
אלו headers חשובים לנו מבחינת אבטחת מידע?
כפי שציינתי בהקדמה, ישנם heasers רבים שחשובים מאד לאבטחת המידע באתר שלנו. חלקם – בכך שנסיר אותם או נשנה את תוכנם, ע"מ שלא לחשוף מידע רגיש לתוקפים. וחלקם – בכך שנוודא שהם מופעלים ומצמצמים את אפשרויות התקיפה כלפי האתר שלנו. במהלך השורות הבאות אסביר לכם באופן מפורט כיצד להוסיף, למחוק או לשנות את הheaders מהאתר שלכם, בין אם אתם משתמשים במערכת wordpress, באתר שכתבתם בעצמכם או בכל מערכת אחר, הפעולה היא אותה פעולה והיא חשובה מאד לאבטחת המערכת שלכם. שימו לב שיש אפשרות לטפל בheader בשרת עצמו, אך אנו נתמקד בשינוי ע"י שפת צד השרת.
כמו-כן, אציין שבימים אלו אני עובד על כתיבת מדריך מקיף מא' עד ת' להקשחת מערכות wordpress. מדובר במדריך האינטרנטי המקיף ביותר שתמצאו (ולא משנה באיזו שפה) להקשחת המערכת שלכם. קחו בחשבון שהחלק שלפניכם הוא חלק חשוב מאותה הקשחה ואם אתם רוצים להבטיח את אבטחת המידע באתר שלכם, הקפידו לבצע את כל הפעולות המומלצות בו.
נפתח עם הheaders שיש למחוק. אם הסתכלתם בheaders שנשלחים מהאתר שלכם (אם דילגתם על החלק המסביר כיצד לבצע זאת, חזרו לתחילת המדריך להסבר הפשוט) וראיתם את הכותרת שמיד נציין, מצאתם פרצת אבטחה בשם 'information disclosure' באתר שלכם ועליכם לתקנה.
X-Powered-By: PHP 7.1
כותרת המציינת את שפת צד השרת של המערכת והגרסה שלו. כאמור, מדובר במידע בעל ערך רב לתוקף, שיכול למקד את חיפושיו אחר פגיעויות כלפי מערכת זו. אם מדובר בגרסה לא מעודכנת העבודה קלה יותר ובעזרת חיפוש פשוט במאגרי פגיעויות, יוכל התוקף למצוא את הפגיעויות בגרסה המדוברת ולהשתמש בניצולים קיימים / לכתוב בעצמו לגרסה זו. ההמלצה הגורפת ביחס לheader זה היא למחוק אותו.
Server: Apache/2.4.1 (Unix)
כאמור, כותרת המציינת את פרטי השרת המארח וגרסתו. גם כאן יוכל התוקף להשתמש בפרטים אלו ע"מ למקד את תקיפתו ולחדור בקלות יתירה למערכת שלכם. ההמלצה הגורפת ביחס לheader זה היא או לשנות את שם השרת לשם לא נכון ובכך להערים על התוקף או למחוק את הפרטים.
כיצד נוכל למחוק או לשנות את ערך הheader בPHP?
אם נרצה לשנות את ערך הheader:
;header("X-Powered-By: Bar")
ע"מ למחוק את הheaer:
;header_remove("X-Powered-By")
כיצד נוכל למחוק את לשנות את ערך הheader בASP.NET?
בASP.NET התהליך מעט יותר מורכב ויש הבדל בין header לheader. ניתן למצוא מספר שיטות עבור ביצוע הפעולה, אנו נשתמש בזאת:
אם נרצה לשנות את ערך הheader:
;("context.Response.Headers.Remove("server ;("context.Response.Headers.Add("server", "secret
אם נרצה למחוק את הheader:
()protected void Application_PreSendRequestHeaders { ;("Response.Headers.Remove("Server }
כיצד נוכל למחוק את לשנות את ערך הheader בflask – pyhton?
אם נרצה לשנות את ערך הheader:
:()def index ()response = flask.Response "response.headers["server"] = "secret return response
אם נרצה למחוק את הheader:
del response.headers['server']
עד כה עסקנו בheaders שיש למחוק. כעת נדבר על הכותרות שיש להוסיף, כאלה שיסייעו לכם באבטחת המידע באתר שלכם והפיכתו לאתר מאובטח יותר. עם השנים פותחו עוד ועוד כותרות שמטרתם לוודא את שלמות המידע שלכם ומניעת ביצוע xss.
Content-Security-Policy
Content-Security-Policy זהו מנגנון שנועד לאיתור ומניעת ביצוע מתקפות xss והזרקות קוד. זהו למעשה המנגנון הטוב ביותר למניעת מתקפות אלו, אך מצד שני יישומו מורכב יותר מהאפשרויות האחרות. CSP מאפשר לאתרים לקבוע כי רק סקריפטים שנטענו ממקורות ספציפיים יוכלו להיטען בדף, אך סקריפטים שיטענו בדף עצמו או ממקורות לא מורשים לא יוכלו לבצע זאת. כלומר: ע"מ לממש את CSP, יש לבצע את הפונקציונליות של הדף בדפים נפרדים ולהטעינם בעזרת תגי <script> לדף הרלוונטי, אך אין אפשרות לבצעם בדף עצמו. במדיניות הCSP ניתן לקבוע גם מניעת טעינת תגי css מהדף עצמו, ע"מ למנוע css keylogger ומתקפות אחרות וכן קביעת שימוש בפרוטקולים ספציפיים בלבד ובכך לייתר את הצורך בשימוש בHSTS לדוגמא (ראה בהמשך). כאמור, CSP זוהי הדרך הטובה ביותר להבטיח מניעה של מתקפות xss והזרקות קוד, אך מהצד השני – יישומו מורכב, בשל הצורך לטעון תוכן אך ורק ממקורות חיצוניים ועל כן אתרים רבים לא משתמשים בו. לCSP אפשרויות רבות ואני אציג רק חלק מן האפשרויות ע"מ שתבינו את הרעיון, אך שימו לב: וודאו היטב קודם להגדרתו שההגדרה לא תפגע בפונקציונליות ובעיצוב של אתר האינטרנט שלכם.
כך נאפשר גישה לסקריפטים ואובייקטים רק מהאתר שלנו (כאילו שהוכנסו בתוך תג script src):
'script-src 'self'; object-src 'self
כך נוכל להגדיר גישה לסקריפטים רק מהאתר שלנו ומgoogle (שוב, כאלה שהוגדרו תחת script-src):
Content-Security-Policy: script-src 'self' https://apis.google.com
אם נרצה לאסור אובייקט מסויים, נשתמש ב'none'.
X-XSS-Protection
X-XSS-Protection זוהי כותרת שנועדה למנוע מתקפות xss, באתרים שלא משתמשים בCSP. זוהי תכונה של Internet Explorer, Chrome ו- Safari המונעת טעינה של דפים כאשר הם מזהים התקפות xss.
הערכים האפשריים לheader זה הם 0 ו1. אפס ימנע את סינון הxss וממילא לא נבחר את אפשרות זו, אלא את 1 שפירושו ניקוי הxss מהדף במקרה שהדפדפן מזהה אותו. גם כשאנו מגדירים 1, יש אפשרות לבחור שלא להציג את הדף הנגוע בכלל ולא רק לנקות את הxss ממנו, במקרה שנרצה לבחור באפשרות זו, נוסיף את הפרמטר mode עם הערך block. ניתן גם לקבל דיווח על הניסיון שנמנע בעזרת הפרמטר report עם url.
X-XSS-Protection: 1; mode=block
X-Frame-Options
כותרות זו מטרתה לקבוע את מדיניות לקיחת Frame מהאתר שלנו. כלומר: האם יתאפשר ביצוע בתגי iframe ע"מ להציג חלקים מהאתר שלנו בתוך אתר אחר. אי שימוש בכותרת זו עלול לגרום לליקוי אטבחה שיאפשר ביצוע מתקפת clickjacking. לדוגמא, אם אתם עורכים סקר באתר שלכם ומאפשרים לקיחת Frame. יוכל אחד המועמדים בסקר להציג frame של הסקר באתר שלו, להציג אותו בבהירות 0 (כך שהוא לא ייראה לעין) ולגרום למשתמשים להקליק על השם שלו, כאשר במקום השם שלו יופיע כיתוב: הקלק כאן לקבלת פרס כספי. הדבר יכול לגרום למניפולציות בתוכן ובפגיעה באמינות האתר.
הערכים האפשריים לheadder זה הם DENY וSAMEORIGIN. בחירה בDENY תמנע מכל אתר לקחת frame מאתר שלנו, גם לדומיין שלנו. בחירה בSAMEORIGIN תאפשר לדומיין שלנו לקחת frame ותמנע משאר האתרים (פעמים רבות מומלץ להשתמש בSAMEORIGIN, שכן בwordpress לדוגמא, תוספים כמו אלמנטור לא יוכלו לעבוד תחת הגדרת DENY).
X-Frame-Options: DENY
X-Content-Type-Options
X-Content-Type-Options זוהי כותרת שנועדה למנוע מאתרים לבצע זיהוי עצמאי של הcontent-type של חבילת המידע. מטרתה למנוע מתקפות MIME sniffing, המתבצעות כאשר הדפדפן מבצע זיהוי עצמאי של הcontent-type. הבעיה תתרחש כאשר באתר יהיה מנגנון של העלאת תמונות לצורך הדוגמא שיאפשר העלאת קבצי jpg בלבד, משתמש ינסה לבצע העלאה של קובץ html שיכיל xss עם הסיומת jpg. אלא שהרחרוח של הדפדפן יזהה את הקובץ כקובץ תמונה וינסה לבצע אותו, למרות שלמעשה מדובר בקובץ html שמכיל xss. כותרות זו אומרת לדפדפן להסתמך אך ורק על הcontent-type ולא לבצע סריקה עצמאית.
את header זה מגדירים כך:
X-Content-Type-Options: nosniff
Referrer-Policy
מטרתה של כותרת זו הוא להבטיח את פרטיות המשתמשים ואי דליפת מידע רגיש. שדה הReferrer מכיל את הדף ממנו הגיע הגולש למשאב הספציפי. הבעיה מתרחשת כאשר האתר הגיע מדף של איפוס סיסמא לדוגמא, שהכיל לינק לאתר אחר, כך שגם בעל האתר האחר יוכל כעת לאפס את הסיסמא שלו. או לחילופין – כאשר המידע מגיע מאתר שהכיל תמונות אישיות, אתר שהעביר נתונים בGET, כלומר – בurl וכן הלאה. במקרה כזה ידלוף מידע אישי של המשתמש שלנו. בעזרת הגדרת כותרת זו אנו יכולים לבטל את שדה הReferrer לחלוטין, או לקבוע באיזו צורה יופיע המידע הזה.
לheader זה שמונה ערכים אפשריים, אני אציין את השלושה המרכזיים: no-referrer – הheader יושמט לחלוטין. no-referrer-when-downgrade – ברירת המחדל, הheader יישלח רק עם אתר היעד גם משתמש בתקשורת מאובטחת של HTTPS. האפשרות השלישית היא origin – תישלח רק כתובת האתר המפנה, לא הדף הספציפי.
Referrer-Policy: origin
Strict-Transport-Security
כותרת שמטרתה לאכוף את HSTS, הפרוטוקול האוכף שימוש בHTTPS ומבצע הפנייה אליו, גם כאשר המשתמש מבקש בurl לבצע שימוש בHTTP ובכך מונע מתקפות man in the middle.
לheader זה ערך חובה אחד: max-age – כל כמה זמן (בשניות) על הדפדפן לזכור את חובת השימוש בHSTS. ישנם שני ערכים אופציונליים נוספים: includeSubDomains – אם נרצה לחייב HSTS גם בסאב דומיינים. preload – נועד למנוע את המגרעות בפרוטוקול הHSTS ולכלול את האתר ברשימת האתרים התומכים בHSTS של דפדפני האינטרנט הגדולים.
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Permissions Policy
תקן זה טרם זכה לפופולאריות רחבה שכן הוא עדיין רק בגדר טיוטה וטרם הפך לתקן רשמי, אך במהלך השנים הבאות הוא צפוי להפוך לכזה ולהוות לסטנדרט נפוץ. מטרתו לאפשר למנהל האתר לנהל בצורה טובה יותר את ממשקי הAPI שהוא עובד עמם: לאפשר, להשבית או לשנות את יישומם ובכך להבטיח את פרטיות ונוחות הגולשים שלו בצורה טובה יותר. לדוגמא, בעזרת השבתת של תוכן צד שלישי בתוך ממשקי הAPI.
לדוגמא, כך נוכל להעניק גישה למיקום המשתמש רק לAPI של exmple.com:
Permissions-Policy: geolocation=(self "https://map.example.com")
Subresource Integrity
הגדרה נוספת וחשובה מאד, שלא נכללת כheader נפרד, היא הגדרת שלמות הנתונים. כשאנו מייבאים סקריפטים למערכת שלנו תחת תגי <script></script> אנו, בסופו של דבר, מעמידים את המערכת שלנו תחת ליקויי אבטחה. תחשבו על כך, אם אנו מייבאים סקריפט ממקור כלשהו ובעל המקור, לפתע, משנה את קוד המקור לקוד זדוני, האתר שלנו יהיה תחת סיכון אבטחתי גבוהה. עבור מניעת הסיכון הזה, מומלץ לבצע גיבוב לכל סקריפט שאנו מייבאים ממקור חיצוני כלשהו ולהוסיף אותו לתג הscript, כך שאם יתבצע שינוי בscript הוא יפסיק את עבודתו. פעולה זו מבצעית בעזרת הוספת הhash לתג הסקריפט. ראשית-כל, ניצור את הhash ממכונת הלינוקס שלנו בעזרת openssl (הקובץ file.js יכיל את קובץ הjavascript כלפיו יתבצע הגיבוב):
cat file.js | openssl dgst -sha384 -binary | openssl base64 -A
ולאחר מכן, נוסיף אותו לתג הסקריפט שלנו, תחת הפרמטר integrity ושם הגיבוב. לדוגמא:
<script src="https://example.com/framework.js"
integrity="sha384-oqVuAfXRKap7fddcCY5uykM6+R9GqQ8K/uxy9rxsHNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>