שיטות עבודה מומלצות ל-SSL/TLS

יישום מאובטח של SSL/TLS הוא חיוני להגנה על נתונים בתעבורה מפני יירוט, שינוי והתקפות man-in-the-middle העלולות לפגוע בסודיות ובשלמות של תקשורת רגישה. אף ש-SSL/TLS מאומץ בהרחבה (כמעט כל אתר מודרני משתמש ב-HTTPS), יישומים רבים עדיין מכילים פגיעויות הנובעות מהגדרות לא נאותות - שימוש בגרסאות מיושנות של הפרוטוקול (SSL 2.0, SSL 3.0, TLS 1.0, TLS 1.1) שהוצאו רשמית משימוש (deprecated) על ידי גופים כגון IETF ו-PCI-DSS עקב פגיעויות ידועות כמו POODLE, BEAST ו-CRIME, cipher suites חלשות או שבורות כגון RC4, DES, 3DES ו-MD5 שניתן לתקוף באמצעות משאבי מחשוב מודרניים, אישורים עם אלגוריתמי חתימה SHA-1 הנחשבים כיום לא בטוחים, היעדר Perfect Forward Secrecy (PFS) המאפשר לפענח תעבורה שנלכדה באופן רטרואקטיבי אם המפתח הפרטי של השרת ייפרץ בעתיד, היעדר HSTS (HTTP Strict Transport Security) המאפשר downgrade attacks שבהם תוקף כופה חיבור HTTP לא מוצפן, ו-certificate pinning לא נאות או חסר ביישומים ניידים קריטיים המאפשר יירוט באמצעות אישורים זדוניים המותקנים במכשיר. תצורת SSL/TLS מיטבית לא רק משפרת את ה-security posture אלא גם משפיעה על הביצועים (handshakes של TLS 1.3 מהירים יותר מ-TLS 1.2), על התאימות (לקוחות ישנים מאוד עשויים שלא לתמוך בתצורות מודרניות) ועל ה-compliance (LGPD, GDPR, PCI-DSS מחייבים הצפנה חזקה לנתונים בתעבורה). מאמר זה מספק הנחיות טכניות מפורטות ליישום SSL/TLS על פי ה-best practices של התעשייה, ההמלצות של NIST, ה-Mozilla SSL Configuration Generator ו-OWASP.

גרסאות פרוטוקול: TLS 1.2 ו-TLS 1.3

השביתו לחלוטין את SSL 2.0, SSL 3.0, TLS 1.0 ו-TLS 1.1 בכל השרתים - לגרסאות אלו יש פגיעויות מתועדות ואין להשתמש בהן אפילו לצורך תאימות עם לקוחות legacy. הגדירו את שרת האינטרנט שלכם (nginx, Apache, IIS) או את ה-load balancer (AWS ALB, Azure Application Gateway) לקבל אך ורק TLS 1.2 ו-TLS 1.3. TLS 1.3, שאושר ב-2018 כ-RFC 8446, מציע שיפורים משמעותיים על פני גרסאות קודמות: handshake מהיר יותר (1-RTT במקום 2-RTT, עם תמיכה ב-0-RTT עבור resumed sessions), הסרה של cipher suites לא בטוחות (אין עוד תמיכה ב-RSA key exchange, בצפנים במצב CBC, ב-RC4, ב-3DES), forward secrecy חובה בכל ה-cipher suites, ו-handshake מוצפן המסתיר את ה-metadata של משא ומתן הפרוטוקול. ב-nginx, הגדירו עם "ssl_protocols TLSv1.2 TLSv1.3;". ב-Apache, "SSLProtocol -all +TLSv1.2 +TLSv1.3". AWS ALB מאפשר בחירת security policy המגדירה פרוטוקולים וצפנים - בחרו "ELBSecurityPolicy-TLS13-1-2-2021-06" לסביבות מודרניות או "ELBSecurityPolicy-2016-08" אם עליכם לתמוך בכמה לקוחות ישנים. נטרו את לוגי הגישה שלכם כדי לזהות כמה לקוחות עדיין משתמשים ב-TLS 1.0/1.1 - אם המספר זניח (פחות מ-0.1% מהתעבורה), תוכלו להשבית זאת ללא השפעה מהותית. עבור APIs מסוג B2B שבהם אתם שולטים בשני ה-endpoints, דרשו TLS 1.3 בלעדית. זכרו שגרסת הפרוטוקול נקבעת במהלך ה-handshake - השרת צריך להכריז על הגרסאות הנתמכות והלקוח בוחר את הגבוהה ביותר שגם הוא תומך בה.

Cipher Suites: ECDHE ו-AES-GCM

Cipher suites מגדירות את האלגוריתמים המשמשים ל-key exchange, אימות, הצפנה סימטרית ו-HMAC במהלך חיבור TLS - בחירה לא נאותה עלולה לפגוע בכל אבטחת התקשורת אפילו בשימוש ב-TLS 1.2+. תנו עדיפות ל-cipher suites עם ECDHE (Elliptic Curve Diffie-Hellman Ephemeral) עבור key exchange שכן הוא מציע Perfect Forward Secrecy, ו-AES-GCM (Galois/Counter Mode) או ChaCha20-Poly1305 עבור הצפנה סימטרית שכן הם צפני AEAD (Authenticated Encryption with Associated Data) המבטיחים גם סודיות וגם שלמות. דוגמה ל-cipher suite מאובטחת: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 או TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256. הימנעו לחלוטין מ: cipher suites עם RC4 (פגיעות להטיות סטטיסטיות), export ciphers (מוגבלים ל-40 או 56 ביט על פי תקנות ייצוא ישנות), NULL ciphers (ללא הצפנה), DES ו-3DES (גודל בלוק קטן הפגיע ל-Sweet32), מצב CBC ב-TLS 1.0-1.1 (פגיע ל-BEAST ו-Lucky13), ו-RSA key exchange ללא DHE/ECDHE (ללא forward secrecy). ב-nginx, הגדירו "ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';" ו-"ssl_prefer_server_ciphers on;" כדי לכפות את סדר השרת. השתמשו בכלים כמו ssllabs.com/ssltest כדי לאמת את התצורה שלכם ולקבל דירוג A+. עבור TLS 1.3, ה-cipher suites פשוטות ובטוחות יותר כברירת מחדל (TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256).

HSTS: HTTP Strict Transport Security

HSTS הוא מנגנון המורה לדפדפנים להשתמש תמיד ב-HTTPS עבור דומיין מסוים, ובכך מונע התקפות SSL stripping שבהן man-in-the-middle כופה חיבור HTTP לא מוצפן על ידי יירוט הבקשה הראשונה לפני שהפניית ה-301 ל-HTTPS מתרחשת. יישמו את HSTS על ידי הוספת ה-header "Strict-Transport-Security" בכל תגובות ה-HTTPS של השרת שלכם: "Strict-Transport-Security: max-age=31536000; includeSubDomains; preload". הפרמטר max-age (בשניות) מגדיר כמה זמן על הדפדפן לזכור להשתמש רק ב-HTTPS - 31536000 שניות = שנה אחת הוא הערך המומלץ. "includeSubDomains" מחיל את המדיניות על כל תת-הדומיינים (השתמשו בזהירות שכן עליכם להבטיח שכל תת-הדומיינים תומכים ב-HTTPS). "preload" מציין שאתם רוצים שהדומיין שלכם ייכלל ב-HSTS preload list המתוחזקת על ידי הדפדפנים - רשימה מקודדת קשיח (hardcoded) של דומיינים שחייבים להשתמש תמיד ב-HTTPS אפילו בביקור הראשון לפני קבלת כל header של HSTS. כדי להיכלל ב-preload list, הגישו את הדומיין שלכם ב-hstspreload.org לאחר שאישרתם ש: כל האתר עובד בצורה מושלמת ב-HTTPS, יש לכם אישור תקף המכסה את הדומיין ותת-הדומיינים, אתם מפנים את כל תעבורת ה-HTTP ל-HTTPS, אתם מגישים את ה-header של HSTS בדומיין הבסיס עם ה-directives includeSubDomains ו-preload, ו-max-age גדול או שווה ל-31536000. חשוב: preload היא החלטה חד-כיוונית - הסרת דומיין מהרשימה עלולה להימשך חודשים ותשבור את הגישה למשתמשים במהלך תקופה זו אם לא תוכלו עוד לתמוך ב-HTTPS. ב-nginx: "add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload' always;". ב-Apache: "Header always set Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload'".

Certificate Pinning עבור יישומים קריטיים

Certificate pinning הוא טכניקה שבה היישום שלכם (במיוחד אפליקציות ניידות ו-APIs קריטיים) מקודד קשיח או מטמיע את ה-hash/fingerprint של האישור הצפוי מהשרת, ומאמת במהלך ה-TLS handshake שהאישור המוצג תואם ל-pin השמור - הדבר מונע התקפות שבהן תוקף מתקין אישור זדוני במכשיר הקורבן (באמצעות malware או גישה פיזית) ומיירט תעבורת HTTPS שבדרך כלל הייתה זוכה לאמון על ידי שרשרת ה-CAs המוגדרת כברירת מחדל של מערכת ההפעלה. ישנם שני סוגי pinning: pin של אישור ה-leaf (ספציפי לאותו אישור, יש לעדכן כאשר האישור פג/מתחדש), או pin של המפתח הציבורי של ה-CA / המפתח הציבורי (גמיש יותר, מאפשר רוטציה של אישורים כל עוד הם חתומים על ידי אותה CA). יישמו pinning באפליקציות ניידות באמצעות frameworks מקוריים: ה-iOS Network framework מאפשר pinning באמצעות callbacks של URLSessionDelegate, Android משתמש ב-Network Security Configuration XML עם האלמנט pin-set, React Native יכול להשתמש בספריית react-native-ssl-pinning. עבור APIs, שקלו mutual TLS (mTLS) שבו גם הלקוח מציג אישור לשרת, המאומת באמצעות pinning. זהירות: pinning שגוי עלול לשבור את היישום שלכם אם תאבדו גישה לאישור ה-pinned ולא יהיה לכם מנגנון fallback - יישמו תמיד: pin גיבוי (אישור/CA תקף שני), עדכוני pin מסוג over-the-air, ותקופת grace לפני אכיפת ה-pins כדי לאפשר rollback במצבי חירום. השתמשו ב-Public Key Pinning במקום ב-Certificate Pinning כאשר ניתן (עמיד יותר בפני חידושים). דוגמה לתצורה ב-Android עם digest מסוג SHA-256 ו-hash בקידוד base64 של המפתח הציבורי. כלים כמו openssl יכולים לחלץ את ה-hash של המפתח הציבורי מאישורים לשימוש ב-pins.

Perfect Forward Secrecy (PFS)

Perfect Forward Secrecy היא תכונה קריפטוגרפית שבה פריצה של המפתח הפרטי ארוך-הטווח של השרת (ה-private key של אישור ה-SSL) אינה מאפשרת לפענח sessions שעברו שנלכדו - הדבר מושג באמצעות ephemeral keys הנוצרים באופן דינמי עבור כל session ונהרסים לאחר השימוש. ללא PFS, אם תוקף לוכד את כל התעבורה המוצפנת (דבר טריוויאלי עם network taps) ושנים מאוחר יותר מצליח לגנוב את ה-private key שלכם (באמצעות breach, איום פנימי, צו בית משפט), הוא יכול לחזור ל-pcaps השמורים ולפענח את כל ה-sessions ההיסטוריים - תרחיש המוכר בשם "retrospective decryption". PFS מונע זאת על ידי יצירת session keys ייחודיים באמצעות אלגוריתמי Diffie-Hellman שאינם תלויים ב-private key של האישור לצורך הגזירה - אפילו אם ה-private key נפרץ, session keys קודמים נותרים בטוחים שכן הם נוצרו עם רכיבים ephemeral שכבר אינם קיימים. כדי להבטיח PFS, השתמשו רק ב-cipher suites עם DHE (Diffie-Hellman Ephemeral) או ECDHE (Elliptic Curve DHE) ב-key exchange - הימנעו מ-RSA key exchange שאינו מציע PFS שכן ה-session key מוצפן עם ה-public key של השרת ומפוענח עם ה-private key. ב-TLS 1.3, PFS היא חובה (כל ה-cipher suites משתמשות ב-ECDHE). ב-TLS 1.2, הגדירו את השרת להעדיף צפני ECDHE על פני RSA. אמתו עם: openssl s_client -connect yoursite.com:443 -cipher 'ECDHE' - אם החיבור מצליח, PFS פועל. יתרון נוסף של PFS הוא ה-compliance - frameworks רבים (PCI-DSS, NIST) ממליצים או מחייבים PFS להגנה על נתונים רגישים. חיסרון: overhead קל בביצועים שכן פעולות DHE יקרות יותר מבחינה חישובית מ-RSA, אך עם חומרה מודרנית (AES-NI, האצת קריפטו של ה-CPU) ההשפעה זניחה.