מתווכים זדוניים ומבלבלים עם אבטחת תעבורה מסוג HTTPS ו-HTTP Strict

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

למה זה חשוב לך? כמה נקודות שכדאי לזכור:

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

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

מתווכים

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

אפשר לראות את הצעדים האלה בפעולה עם Trackroute. המסלול מהמחשב שלי אל HTML5Rocks נראה בערך כך:

$ traceroute html5rocks.com
traceroute to html5rocks.com (173.194.71.102), 30 hops max, 60 byte packets
 1  router1-lon.linode.com (212.111.33.229)  0.453 ms
 2  212.111.33.233 (212.111.33.233)  1.067 ms
 3  217.20.44.194 (217.20.44.194)  0.704 ms
 4  google1.lonap.net (193.203.5.136)  0.804 ms
 5  209.85.255.76 (209.85.255.76)  0.925 ms
 6  209.85.253.94 (209.85.253.94)  1.226 ms
 7  209.85.240.28 (209.85.240.28)  48.714 ms
 8  216.239.47.12 (216.239.47.12)  22.575 ms
 9  209.85.241.193 (209.85.241.193)  36.033 ms
10  72.14.233.180 (72.14.233.180)  43.222 ms
11  72.14.233.170 (72.14.233.170)  43.242 ms
12  *
13  lb-in-f102.1e100.net (173.194.71.102)  44.523 ms

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

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

האם זהו קו מאובטח?

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

סרגל הכתובות של Chrome מספק לא מעט פרטים על סטטוס החיבור.
בסרגל הכתובות של Chrome יש הרבה פרטים על סטטוס החיבור.

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

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

האבטחה היא ברירת מחדל

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

בשיטה הזאת,

כשמשתמש מבקר ב-http://example.com/, צריך להפנות אותו אל https://example.com/ על ידי שליחת התגובה 301 Moved Permanently עם כותרת Location מתאימה:

$ curl -I http://mkw.st/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.3.7
...
Keep-Alive: timeout=20
Location: https://mkw.st/

אפשר להגדיר הפניה אוטומטית כזו בקלות בשרתים כמו Apache או Nginx. לדוגמה, הגדרת Nginx שמפנה מחדש מ-http://example.com/ ל-https://example.com/ נראית כך:

server {
    listen [YOUR IP ADDRESS HERE]:80;
    server_name example.com www.example.com;
    location "/" {
        rewrite ^(.*) https://www.example.com$1 permanent;
    }
}

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

בדרך כלל, הגדרה של קובץ cookie כוללת כותרת HTTP שנראית בערך כך:

set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT

אפשר להורות לדפדפן להגביל את השימוש בקובץ ה-cookie לאבטחת סשנים על ידי התמקדות במילת מפתח אחת:

Set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT; secure

קובצי cookie שהוגדרו עם מילת המפתח מאובטחת אף פעם לא יישלחו ב-HTTP.

סגירת החלון הפתוח

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

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

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

דפדפנים שתומכים בכותרת הזו (נכון לעכשיו, Firefox, Chrome ו-Opera: Caniuse יש פרטים) ישימו לב שהאתר הספציפי הזה ביקש גישת HTTPS בלבד, כלומר, ללא קשר לאופן שבו המשתמש מגיע לאתר, הוא ייכנס דרך HTTPS. גם אם היא תקליד http://example.com/ בדפדפן, היא תגיע ל-HTTPS בלי ליצור חיבור HTTP. בנוסף, אם הדפדפן יזהה אישור לא תקף (עלולה לנסות לזייף את זהות השרת), המשתמשים לא יורשו להמשיך להשתמש ב-HTTP. זה הכול או כלום, וזה מצוין.

סטטוס ה-HSTS של השרת יפוג אחרי max-age שניות (בערך חודש בדוגמה הזו). יש להגדיר אותו לערך גבוה במידה סבירה.

כדי לוודא שכל תתי-הדומיינים של מקור מוגנים, אפשר להוסיף את ההוראה includeSubDomains לכותרת:

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

קדימה, בבטחה

הדרך היחידה להיות בטוחים אפילו מרחוק שהנתונים שאתם שולחים יגיעו לנמען המיועד ללא שינוי. כדאי לכם להגדיר חיבורים מאובטחים לאתרים ולאפליקציות שלכם עוד היום. זה תהליך פשוט למדי, והוא יעזור לשמור על אבטחת הנתונים של הלקוחות שלכם. אחרי שמכניסים ערוץ מוצפן, צריך להפנות את המשתמשים באופן שקוף לחיבור המאובטח הזה, ללא קשר לאופן שבו הם מגיעים לאתר, על ידי שליחת תגובת HTTP מסוג 301. לאחר מכן ודאו שכל המידע הרגיש של המשתמשים לגבי פעילות באתר משתמש רק בחיבור המאובטח הזה, על ידי הוספת מילת המפתח מאובטח בעת הגדרת קובצי cookie. לאחר מכן, חשוב לוודא שהמשתמשים אף פעם לא נופלים מהאוטובוס בטעות: שולחים את הכותרת Strict-Transport-Security כדי להגן עליהם ולוודא שהדפדפן עושה את מה שצריך.

הגדרת HTTPS לא מורכבת הרבה, ויש לה יתרונות עצומים לאתר ולמשתמשים. המאמץ כדאי.

משאבים

  • ב-StartSSL יש אישורים בחינם שמאומתים באמצעות דומיין. תמיד אפשר להביס את בחינם. כמובן שהעלאת רמה גבוהה יותר של אימות היא אפשרית וגם במחיר סביר.
  • בדיקת שרת SSL: אחרי שהגדרתם HTTPS לשרתים, ודאו שעשיתם זאת כמו שצריך על ידי הרצת הכלי לבדיקת שרת של SSL Labs. תקבלו דוח מפורט למדי שיראה לכם אם אתם מוכנים להתחיל לעבוד.
  • כדאי לקרוא את המאמר האחרון של Ars Technica, "אבטחת שרת האינטרנט באמצעות SSL/TLS", כדי לקבל קצת יותר פרטים לגבי הרקע הנדרש להגדרת שרת.
  • כדאי לעיין במפרט של HTTP Strict Transport Security (RFC6797) כדי לחפש את כל המידע הטכני על הכותרת Strict-Transport-Security שאולי תרצו.
  • אחרי שתבינו בדיוק מה אתם עושים, אפשר יהיה לפרסם את האתר כך שאפשר יהיה להגיע אליו רק באמצעות קבוצה ספציפית של אישורים. אנחנו עובדים בשלבי עבודה ב-IETF שמאפשרים לכם לעשות זאת בדיוק דרך הכותרת Public-Key-Pins; עדיין בימים הראשונים, אבל מעניינים וכדאי לעקוב אחריהם.