התכונה 'הגדרת אבטחת הרשת' מאפשרת להתאים אישית את הגדרות האבטחה של האפליקציה ברשת בקובץ תצורה בטוח ודקלרטיבי, בלי לשנות את קוד האפליקציה. אפשר להגדיר את ההגדרות האלה לדומיינים ספציפיים ולאפליקציה ספציפית. היכולות העיקריות של התכונה הזו הן:
- עוגני אמון בהתאמה אישית: אפשר להתאים אישית את רשויות האישורים (CA) שנחשבות מהימנות לחיבורים המאובטחים של האפליקציה. לדוגמה, אמון באישורים מסוימים עם חתימה עצמית או הגבלת הקבוצה של רשויות האישורים הציבוריות שהאפליקציה סומכת עליהן.
- עקיפות לצורך ניפוי באגים בלבד: ניפוי באגים בטוח של חיבורים מאובטחים באפליקציה, בלי סיכון נוסף לבסיס המשתמשים שמותקנת אצלם האפליקציה.
- ביטול ההסכמה לשימוש בתעבורת נתונים בטקסט ללא הצפנה: הגנה על האפליקציות מפני שימוש בטעות בתעבורת נתונים בטקסט ללא הצפנה.
- הסכמה לשקיפות אישורים: הגבלת החיבורים המאובטחים של האפליקציה לשימוש באישורים שרשומים ביומן וניתנים להוכחה.
- הצמדת אישורים: הגבלת החיבור המאובטח של האפליקציה לאישורים מסוימים.
הוספת קובץ תצורה של אבטחת רשת
התכונה 'הגדרת אבטחת הרשת' משתמשת בקובץ XML שבו מציינים את ההגדרות של האפליקציה. צריך לכלול רשומה במניפסט של האפליקציה כדי להפנות לקובץ הזה. קטע הקוד הבא מתוך מניפסט מדגים איך יוצרים את הרשומה הזו:
<?xml version="1.0" encoding="utf-8"?> <manifest ... > <application android:networkSecurityConfig="@xml/network_security_config" ... > ... </application> </manifest>
התאמה אישית של רשויות אישורים מהימנות
יכול להיות שתרצו שהאפליקציה תאמין לקבוצה מותאמת אישית של רשויות אישור במקום לברירת המחדל של הפלטפורמה. הסיבות הנפוצות ביותר לכך הן:
- חיבור למארח עם רשות אישורים מותאמת אישית, כמו רשות אישורים בחתימה עצמית או רשות אישורים שהונפקה באופן פנימי בתוך חברה.
- הגבלת קבוצת ה-CAs רק ל-CAs שאתם סומכים עליהם, במקום לכל ה-CAs שמותקנים מראש.
- אמון ברשויות אישור נוספות שלא נכללות במערכת.
כברירת מחדל, חיבורים מאובטחים (באמצעות פרוטוקולים כמו TLS ו-HTTPS) מכל האפליקציות סומכים על רשויות אישור התעודות (CA) המותקנות מראש במערכת, ובאפליקציות שמטרגטות ל-Android 6.0 (רמת API 23) ואילך, כברירת מחדל יש אמון גם במאגר רשויות אישור התעודות שנוספו על ידי המשתמש. אפשר להתאים אישית את החיבורים של האפליקציה באמצעות base-config
(להתאמה אישית ברמת האפליקציה) או domain-config
(להתאמה אישית לכל דומיין).
הגדרת רשות אישורים בהתאמה אישית
יכול להיות שתרצו להתחבר למארח שמשתמש באישור SSL בחתימה עצמית, או למארח שאישור ה-SSL שלו הונפק על ידי רשות אישורים לא ציבורית שאתם סומכים עליה, כמו רשות האישורים הפנימית של החברה.
קטע הקוד הבא מראה איך להגדיר את האפליקציה ל-CA בהתאמה אישית ב-res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> </domain-config> </network-security-config>
מוסיפים את אישור ה-CA החתום בעצמו או הלא ציבורי, בפורמט PEM או DER, אל res/raw/my_ca
.
הגבלת הקבוצה של רשויות אישורים מהימנות
אם אתם לא רוצים שהאפליקציה תאמין לכל רשויות האישור שהמערכת סומכת עליהן, תוכלו לציין במקום זאת קבוצה מצומצמת יותר של רשויות אישור שאותן האפליקציה תאמין בהן. כך האפליקציה מוגנת מפני אישורים מזויפים שהונפקו על ידי כל אחת מרשות האישורים האחרות.
ההגדרה של הגבלת הקבוצה של רשויות ה-CA המהימנו דומה להענקת אמון ברשות CA מותאמת אישית לדומיין ספציפי, מלבד זאת שמספר רשויות CA מצוינות במשאב.
קטע הקוד הבא מראה איך להגביל את קבוצת רשויות האישורים המהימנה של האפליקציה ב-res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">secure.example.com</domain> <domain includeSubdomains="true">cdn.example.com</domain> <trust-anchors> <certificates src="@raw/trusted_roots"/> </trust-anchors> </domain-config> </network-security-config>
מוסיפים את רשויות האישורים המהימנו, בפורמט PEM או DER, אל res/raw/trusted_roots
.
שימו לב: אם משתמשים בפורמט PEM, הקובץ חייב להכיל רק נתוני PEM, ללא טקסט נוסף. אפשר גם לספק כמה רכיבים של <certificates>
במקום אחד.
איך נותנים אמון ברשות אישורים נוספות
יכול להיות שתרצו שהאפליקציה תאמין לרשויות אישור נוספות שלא נחשבות מהימנות במערכת, למשל אם המערכת עדיין לא כוללת את רשות האישור או שהיא לא עומדת בדרישות להכללה במערכת Android. אפשר לציין כמה מקורות לאישורים בהגדרה ב-res/xml/network_security_config.xml
באמצעות קוד כמו הקטע הבא.
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="@raw/extracas"/> <certificates src="system"/> </trust-anchors> </base-config> </network-security-config>
הגדרת רשויות אישור (CA) לניפוי באגים
כשמנסים לנפות באגים באפליקציה שמתחבר דרך HTTPS, מומלץ להתחבר לשרת פיתוח מקומי שאין בו את אישור ה-SSL של שרת הייצור. כדי לתמוך בכך בלי לבצע שינויים בקוד של האפליקציה, אפשר לציין רשויות אישור (CA) לצורכי ניפוי באגים בלבד, שיהיו מהימנות רק כשהערך של android:debuggable הוא true
, באמצעות debug-overrides
. בדרך כלל, סביבות פיתוח משולבות וכלי build מגדירים את הדגל הזה באופן אוטומטי לגרסאות build שלא מיועדות להפצה.
הקוד הזה בטוח יותר מהקוד המותנה הרגיל, כי כצעד זהירות מבחינת אבטחה, חנויות האפליקציות לא מקבלות אפליקציות שמסומנות ככאלה שאפשר לנפות בהן באגים.
בקטע הבא מוסבר איך לציין רשויות אישור לצורכי ניפוי באגים בלבד בקובץ res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <debug-overrides> <trust-anchors> <certificates src="@raw/debug_cas"/> </trust-anchors> </debug-overrides> </network-security-config>
הצטרפות לתוכנית שקיפות האישור
שקיפות אישורים (CT, RFC 9162) היא תקן אינטרנט שנועד לשפר את האבטחה של אישורים דיגיטליים. היא מחייבת את רשויות האישורים לשלוח את כל האישורים שהן מנפיקות ליומן ציבורי שבו הם מתועדים, וכך לשפר את השקיפות ואת האחריותיות בתהליך הנפקת האישורים.
בעזרת CT, שמאפשר לשמור תיעוד מאומת של כל האישורים, קשה יותר לגורמים זדוניים לזייף אישורים או לרשויות אישורים להנפיק אותם בטעות. כך אפשר להגן על המשתמשים מפני מתקפות אדם בתווך ומפני איומי אבטחה אחרים. מידע נוסף זמין באתר הרשמי של Certificate Transparency.
כברירת מחדל, אישורים מתקבלים גם אם הם לא רשומים ביומן של שקיפות אישורים. כדי לוודא שהאפליקציה מתחברת רק ליעדים עם אישורים שמתועדים ביומן CT, אפשר להביע הסכמה לשימוש בתכונה ב-<base-config>
או ב-<domain-config>
.
ביטול ההסכמה לתנועה בטקסט ללא הצפנה
הערה: ההנחיות שבקטע הזה רלוונטיות רק לאפליקציות שמטרגטות את Android מגרסה 8.1 (API ברמה 27) ומטה. החל מגרסה 9 של Android (רמת API 28), התמיכה בטקסט ללא הצפנה מושבתת כברירת מחדל.
אם אתם רוצים שהאפליקציה תתחבר ליעדים באמצעות חיבורים מאובטחים בלבד, תוכלו לבטל את התמיכה בטקסט ללא הצפנה (באמצעות פרוטוקול HTTP לא מוצפן במקום HTTPS) ליעדים האלה. האפשרות הזו עוזרת למנוע נסיגה לא מכוונת באפליקציות בגלל שינויים בכתובות URL שסופקו ממקורות חיצוניים, כמו שרתי קצה עורפי.
פרטים נוספים זמינים בכתובת NetworkSecurityPolicy.isCleartextTrafficPermitted()
.
לדוגמה, יכול להיות שתרצו לוודא שהאפליקציה תמיד תיצור חיבורים אל secure.example.com
באמצעות HTTPS כדי להגן על תעבורת נתונים רגישים מרשתות עוינות.
בקטע הבא מוסבר איך לבטל את ההסכמה להעברת טקסט ללא הצפנה ב-res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> </domain-config> </network-security-config>
הצמדת אישורים
בדרך כלל, אפליקציה סומכת על כל רשויות האישורים שמותקנות מראש. אם אחת מהרשויות האלה תיצור אישור מזויף, האפליקציה תהיה בסיכון לתוקף בנתיב. חלק מהאפליקציות בוחרות להגביל את קבוצת האישורים שהן מקבלות, על ידי הגבלת קבוצת רשויות האישורים שהן סומכות עליהן או על ידי הצמדת אישורים.
כדי להצמיד אישורים, מספקים קבוצת אישורים לפי גיבוב של המפתח הציבורי (SubjectPublicKeyInfo
של אישור X.509). שרשרת אישורים תקפה רק אם היא מכילה לפחות אחד מהמפתחות הציבוריים המוצמדים.
חשוב לזכור שכאשר משתמשים בהצמדת אישורים, תמיד צריך לכלול מפתח גיבוי. כך, אם תצטרכו לעבור למפתחות חדשים או לשנות רשויות אישורים (כשמחברים לאישור של רשות אישורים או לגורם ביניים של רשות האישור הזו), הקישוריות של האפליקציה לא תושפע. אחרת, תצטרכו לשלוח עדכון לאפליקציה כדי לשחזר את הקישוריות.
בנוסף, אפשר להגדיר תאריך תפוגה להצמדות, אחריו לא תתבצע הצמדה. כך אפשר למנוע בעיות קישוריות באפליקציות שלא עודכנו. עם זאת, הגדרת תאריך תפוגה להצמדות עשויה לאפשר לתוקפים לעקוף את האישורים המוצמדים.
בקטע הבא מוסבר איך להצמיד אישורים ב-res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <pin-set expiration="2018-01-01"> <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin> <!-- backup pin --> <pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin> </pin-set> </domain-config> </network-security-config>
התנהגות של ירושה של הגדרות
ערכים שלא מוגדרים בהגדרה ספציפית עוברים בירושה. כך אפשר להגדיר הגדרות מורכבות יותר ועדיין לשמור על הקריאוּת של קובץ התצורה.
לדוגמה, ערכים שלא מוגדרים ב-domain-config
נלקחים מההורה domain-config
, אם הם בתצוגת עץ, או מה-base-config
, אם לא. ערכים שלא מוגדרים ב-base-config
יקבלו את ערכי ברירת המחדל של הפלטפורמה.
לדוגמה, נניח שכל החיבורים לתת-דומיינים של example.com
חייבים להשתמש בקבוצה מותאמת אישית של רשויות אישור. בנוסף, תנועה ללא הצפנה לדומיינים האלה מותרת למעט כשמתחברים אל secure.example.com
.
כשמקפלים את ההגדרה של secure.example.com
בתוך ההגדרה של example.com
, אין צורך לשכפל את trust-anchors
.
הקטע הבא מראה איך ייראה ההטמעה הזו ב-res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> </domain-config> </domain-config> </network-security-config>
הפורמט של קובץ התצורה
התכונה 'הגדרת אבטחת הרשת' משתמשת בפורמט של קובץ XML. המבנה הכללי של הקובץ מוצג בקטע הקוד הבא:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="..."/> ... </trust-anchors> </base-config> <domain-config> <domain>android.com</domain> ... <trust-anchors> <certificates src="..."/> ... </trust-anchors> <pin-set> <pin digest="...">...</pin> ... </pin-set> </domain-config> ... <debug-overrides> <trust-anchors> <certificates src="..."/> ... </trust-anchors> </debug-overrides> </network-security-config>
בקטעים הבאים מתוארים התחביר ופרטים נוספים לגבי הפורמט של הקובץ.
<network-security-config>
- יכול להכיל:
-
0 או 1 מ-
<base-config>
כמות בלתי מוגבלת של<domain-config>
0 או 1 מ-<debug-overrides>
<base-config>
- תחביר:
<base-config cleartextTrafficPermitted=["true" | "false"]> ... </base-config>
- יכול להכיל:
-
<trust-anchors>
<certificateTransparency>
- description:
-
הגדרת ברירת המחדל שמשמשת את כל החיבורים שהיעד שלהם לא מכוסה ב-
domain-config
.ערכים שלא מוגדרים יקבלו את ערכי ברירת המחדל של הפלטפורמה.
הגדרת ברירת המחדל לאפליקציות שמטרגטות ל-Android 9 (רמת API 28) ואילך היא:
<base-config cleartextTrafficPermitted="false"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config>
הגדרת ברירת המחדל לאפליקציות שמטרגטות את Android מגרסה 7.0 (רמת API 24) עד Android מגרסה 8.1 (רמת API 27) היא:
<base-config cleartextTrafficPermitted="true"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config>
הגדרת ברירת המחדל לאפליקציות שמטרגטות ל-Android 6.0 (רמת API 23) ומטה היא:
<base-config cleartextTrafficPermitted="true"> <trust-anchors> <certificates src="system" /> <certificates src="user" /> </trust-anchors> </base-config>
<domain-config>
- תחביר:
-
<domain-config cleartextTrafficPermitted=["true" | "false"]> ... </domain-config>
- יכול להכיל:
-
<domain>
אחד או יותר<certificateTransparency>
אפס או אחד<trust-anchors>
אפס או אחד<pin-set>
אפס או אחד<domain-config>
מספר לא מוגבל של ערכי - description:
- הגדרה שמשמשת לחיבורים ליעדים ספציפיים, כפי שמוגדרים על ידי הרכיבים
domain
.חשוב לזכור שאם יש כמה רכיבי
domain-config
שמכסים יעד מסוים, המערכת משתמשת בהגדרה עם כלל הדומיין התואם הספציפי ביותר (הארוך ביותר).
<domain-config>
בתצוגת עץ
<domain>
- תחביר:
-
<domain includeSubdomains=["true" | "false"]>example.com</domain>
- מאפיינים:
-
-
includeSubdomains
-
אם
"true"
, כלל הדומיין הזה תואם לדומיין ולכל תת-הדומיינים, כולל תת-דומיינים של תת-דומיינים. אחרת, הכלל יחול רק על התאמות מדויקות.
-
<certificateTransparency>
- תחביר:
-
<certificateTransparency enabled=["true" | "false"]/>
- description:
-
אם הערך של
true
הוא true, האפליקציה תשתמש ביומני Certificate Transparency כדי לאמת אישורים. כשאפליקציה משתמשת באישור משלה (או באחסון המשתמש), סביר להניח שהאישור לא ציבורי ולכן אי אפשר לאמת אותו באמצעות שקיפות האישורים. כברירת מחדל, האימות מושבת במקרים האלה. עדיין אפשר לאלץ את האימות באמצעות<certificateTransparency enabled="true"/>
בהגדרות הדומיין. לכל<domain-config>
, ההערכה מתבצעת לפי הסדר הבא:- אם
certificateTransparency
מופעל, מפעילים את האימות. -
אם כל
<trust-anchors>
הוא"user"
או מוטמע (כלומר,"@raw/cert.pem"
), משביתים את האימות. - אחרת, אפשר להסתמך על ההגדרות שעברו בירושה.
- אם
<debug-overrides>
- תחביר:
-
<debug-overrides> ... </debug-overrides>
- יכול להכיל:
-
0 או 1
<trust-anchors>
- description:
-
החלפות שיוחלו כשהערך של android:debuggable הוא
"true"
. בדרך כלל זה המצב בגרסאות build לא ייעודיות להפצה שנוצרות על ידי סביבת פיתוח משולבת (IDE) וכלי build. עוגני האמינות שצוינו ב-debug-overrides
מוסיפים לכל ההגדרות האחרות, והצמדת האישורים לא מתבצעת כששרשרת האישורים של השרת משתמשת באחד מעוגני האמינות האלה לצורך ניפוי באגים בלבד. אם הערך של android:debuggable הוא"false"
, המערכת מתעלמת מהקטע הזה לגמרי.
<trust-anchors>
- תחביר:
-
<trust-anchors> ... </trust-anchors>
- יכול להכיל:
-
כמות בלתי מוגבלת של
<certificates>
- description:
- קבוצה של עוגני אמון לחיבורים מאובטחים.
<certificates>
- תחביר:
<certificates src=["system" | "user" | "raw resource"] overridePins=["true" | "false"] />
- description:
- קבוצה של אישורי X.509 לרכיבי
trust-anchors
. - מאפיינים:
-
src
-
המקור של אישורי ה-CA. כל אישור יכול להיות אחד מהסוגים הבאים:
- מזהה משאב גולמי שמצביע לקובץ שמכיל אישורי X.509. האישורים צריכים להיות מקודדים בפורמט DER או PEM. במקרה של אישורי PEM, אסור שהקובץ יכיל נתונים נוספים שאינם PEM, כמו תגובות.
"system"
לאישורי ה-CA של המערכת שמותקנים מראש"user"
לאישורי CA שנוספו על ידי משתמשים
overridePins
-
ההגדרה הזו קובעת אם רשויות האישורים מהמקור הזה עוקפות את הצמדת האישור. אם הערך של
"true"
הוא 0, המערכת לא תבצע הצמדה של רשתות אישורים שנחתמו על ידי אחת מרשויות האישורים מהמקור הזה. אפשר להשתמש באפשרות הזו כדי לנפות באגים ב-CA או כדי לבדוק התקפות אדם בתווך על התנועה המאובטחת של האפליקציה.ברירת המחדל היא
"false"
, אלא אם מצוין אחרת ברכיבdebug-overrides
, במקרה כזה ברירת המחדל היא"true"
.
<pin-set>
- תחביר:
-
<pin-set expiration="date"> ... </pin-set>
- יכול להכיל:
-
כמות בלתי מוגבלת של
<pin>
- description:
-
קבוצה של סיכות של מפתחות ציבוריים. כדי שחיבור מאובטח יהיה מהימן, אחד מהמפתחות הציבוריים בשרשרת האמון צריך להיות בקבוצת הסיכות. הפורמט של הסיכות מפורט במאמר
<pin>
. - מאפיינים:
-
-
expiration
-
התאריך, בפורמט
yyyy-MM-dd
, שבו יפוג התוקף של הסיכות, וכך יושבתו. אם לא מגדירים את המאפיין, התוקף של התגים לא יפוג.התוקף עוזר למנוע בעיות קישוריות באפליקציות שלא מקבלות עדכונים של קבוצת הסיכות שלהן, למשל כשהמשתמש משבית את עדכוני האפליקציות.
-
<pin>
- תחביר:
-
<pin digest=["SHA-256"]>base64 encoded digest of X.509 SubjectPublicKeyInfo (SPKI)</pin>
- מאפיינים:
-
-
digest
-
אלגוריתם התקציר ששימש ליצירת הסיכה. בשלב זה יש תמיכה רק ב-
"SHA-256"
.
-
מקורות מידע נוספים
למידע נוסף על הגדרת אבטחת הרשת, תוכלו לעיין במקורות המידע הבאים.