הגדרה של הרשאה בהתאמה אישית לאפליקציה

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

רקע

‫Android היא מערכת הפעלה עם הפרדה בין הרשאות, שבה כל אפליקציה פועלת עם זהות מערכת נפרדת (מזהה משתמש ומזהה קבוצה ב-Linux). חלקים מהמערכת מופרדים גם הם לישויות נפרדות. כך Linux מבודד את האפליקציות זו מזו ומהמערכת.

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

חתימה על אפליקציות

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

מתן הרשאות חתימה אחרי זמן ייצור המכשיר

החל מ-Android 12 (רמת API 31), מאפיין knownCerts להרשאות ברמת החתימה מאפשר לכם להפנות לסיכומים של אישורי חתימה ידועים בזמן ההצהרה.

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

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

מזהי משתמשים וגישה לקבצים

בזמן ההתקנה, מערכת Android מקצה לכל חבילה מזהה משתמש ייחודי ב-Linux. הזהות נשארת קבועה למשך חיי החבילה במכשיר. במכשיר אחר, לאותה חבילה יכול להיות UID שונה. מה שחשוב הוא שלכל חבילה יש UID ייחודי במכשיר נתון.

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

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

מידע נוסף על מודל האבטחה של Android זמין במאמר סקירה כללית על אבטחת Android.

הגדרת הרשאות ואכיפה שלהן

כדי לאכוף את ההרשאות שלכם, קודם צריך להצהיר עליהן ב-AndroidManifest.xml באמצעות רכיב <permission> אחד או יותר.

מוסכמה למתן שמות

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

מומלץ להוסיף לכל הרשאה קידומת של שם החבילה של האפליקציה, באמצעות מתן שמות בסגנון של דומיין הפוך, ואחריו .permission., ואז תיאור של היכולת שההרשאה מייצגת, באותיות רישיות בפורמט SNAKE_CASE. לדוגמה, com.example.myapp.permission.ENGAGE_HYPERSPACE.

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

דוגמה

לדוגמה, אפליקציה שצריכה לשלוט באפליקציות אחרות שיכולות להפעיל אחת מהפעילויות שלה יכולה להצהיר על הרשאה לפעולה הזו באופן הבא:

<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.example.myapp" >
    
    <permission
      android:name="com.example.myapp.permission.DEADLY_ACTIVITY"
      android:label="@string/permlab_deadlyActivity"
      android:description="@string/permdesc_deadlyActivity"
      android:permissionGroup="android.permission-group.COST_MONEY"
      android:protectionLevel="dangerous" />
    ...
</manifest>

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

המאפיין android:permissionGroup הוא אופציונלי ומשמש רק כדי לעזור למערכת להציג הרשאות למשתמש. ברוב המקרים, מגדירים את זה לקבוצת מערכת רגילה (שמופיעה בandroid.Manifest.permission_group), אבל אפשר גם להגדיר קבוצה בעצמכם, כמו שמתואר בקטע הבא. מומלץ להשתמש בקבוצה קיימת, כי כך ממשק המשתמש של ההרשאות שמוצג למשתמש יהיה פשוט יותר.

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

דוגמה לתווית ולתיאור של ההרשאה CALL_PHONE:

<string name="permlab_callPhone">directly call phone numbers</string>
<string name="permdesc_callPhone">Allows the app to call non-emergency
phone numbers without your intervention. Malicious apps may cause unexpected
calls on your phone bill.</string>

יצירה של קבוצת הרשאות

כמו שמוצג בקטע הקודם, אפשר להשתמש במאפיין android:permissionGroup כדי לעזור למערכת לתאר את ההרשאות למשתמש. ברוב המקרים, מגדירים את זה לקבוצת מערכת רגילה (שמופיעה ב-android.Manifest.permission_group), אבל אפשר גם להגדיר קבוצה משלכם באמצעות <permission-group>.

רכיב <permission-group> מגדיר תווית לקבוצת הרשאות – גם אלה שמוצהרות במניפסט עם רכיבי <permission> וגם אלה שמוצהרות במקום אחר. ההגדרה הזו משפיעה רק על האופן שבו ההרשאות מוצגות למשתמשים. רכיב <permission-group> לא מציין את ההרשאות ששייכות לקבוצה, אבל הוא נותן לקבוצה שם.

כדי להוסיף הרשאה לקבוצה, צריך להקצות את שם הקבוצה למאפיין permissionGroup של רכיב <permission>.

רכיב <permission-tree> מגדיר מרחב שמות לקבוצת הרשאות שמוגדרות בקוד.

המלצות להרשאות מותאמות אישית

אתם יכולים להגדיר הרשאות מותאמות אישית לאפליקציות שלכם ולבקש הרשאות מותאמות אישית מאפליקציות אחרות על ידי הגדרת רכיבי <uses-permission>. עם זאת, חשוב לשקול היטב אם יש צורך בכך.

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

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

להמשך קריאה על:

<uses-permission>
הפניה ל-API של תג המניפסט שמצהיר על הרשאות המערכת הנדרשות לאפליקציה.

נושאים נוספים שיכולים לעניין אותך:

סקירה כללית בנושא אבטחה ב-Android
דיון מפורט על מודל האבטחה של פלטפורמת Android.