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

תעודה אינה מאגר אמון

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

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

האפשרות ca של OpenVPN היא המקרה הברור ביותר של אמון מוגבל ליישום. הקובץ הזה מפרט את העוגנים שהלקוח יקבל, והוא עשוי להכיל CA פרטי אחד או, בפריסה קטנה, את התעודה החתומה בעצמה של השרת. גרסה 2.6 מקבלת גם --peer-fingerprint לנעיצת טביעת אצבע SHA-256 במקום הפצת קובץ CA. WireGuard נמצא עוד יותר בחוץ: אין בו תעודות כלל, רק מפתח ציבורי סטטי לכל עמית, ולכן שאלת החתימה העצמית אינה חלה עליו.

המקום שבו אתם מתקינים אמון קובע מי יורש אותו

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

ב־Debian או Ubuntu, הפלת קובץ אל /usr/local/share/ca-certificates/ והרצת update-ca-certificates משנות את החבילה ברמת המערכת. ב־Windows, certutil -addstore -f Root כותב למאגר המכונה וזקוק לשורת פקודה מוגברת, בעוד שהוספת -user מכוונת למאגר של המשתמש הנוכחי; השניים אינם ניתנים להחלפה. Firefox מחזיק מסד NSS משלו, ולכן ייבוא ברמת מערכת ההפעלה עשוי לעולם לא להופיע שם.

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

אתם עדיין מצפינים בלי CA ציבורי

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

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

אמון במנפיק אינו מדלג על בדיקת השם

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

OpenVPN הופך את ההפרדה לגלויה. verify-x509-name נועץ את הנושא הצפוי באמצעות התאמת name, name-prefix או subject. remote-cert-tls server דורש שתעודת העמית תהיה שמישה כתעודת שרת, מה שדוחה תעודה של לקוח בלבד גם כשהמנפיק מהימן. אף אחת מההגדרות אינה מוחלפת בשליחת קובץ CA.

בדקו את התעודה לפני שתחליטו משהו:

  • openssl x509 -in server.crt -noout -subject -issuer -dates -ext subjectAltName מציג מי הנפיק אותה, לאילו שמות ועד מתי.
  • openssl verify -CAfile ca.crt server.crt בודק אם השרשרת שאתם מתכננים לשלוח אכן מאמתת את העלה.
  • openssl s_client -connect vpn.example.net:443 -servername vpn.example.net -CAfile ca.crt -verify_return_error עובד לנקודות קצה של TLS כמו פורטל רשת; פרוטוקול OpenVPN בפורט 1194 אינו זרם TLS רגיל, ולכן הבדיקה הזאת אינה חלה שם.

תעודה עם תאריך שפג, בלי subjectAltName לשם שאליו אתם מתחברים, או בלי שימוש ב־serverAuth נכשלת לא משנה כמה בזהירות הותקן העוגן.

חמש בדיקות לפני שאתם מקבלים אחת

השוו את טביעת האצבע בערוץ שאינו החיבור שאתם מנסים לתקן: מסוף, מתקין שכבר יש לכם, קובץ תצורה חתום. openssl x509 -in server.crt -noout -fingerprint -sha256 בשרת ואותו ערך ביומן הלקוח מספיקים כדי לדעת שאתם מסתכלים על אובייקט אחד.

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

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

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

מאמרים קשורים