קטגוריה של OWASP: MASVS-CODE: איכות הקוד
סקירה כללית
הסיכונים שקשורים להרשאות מותאמות אישית מתעוררים כשההגדרה של ההרשאות המותאמות אישית חסרה או שיש בה שגיאת כתיב, או כשהשימוש במאפיין android:protectionLevel התואם במניפסט לא תקין.
לדוגמה, אפשר לנצל את הסיכונים האלה על ידי יצירת הרשאה מותאמת אישית עם אותו שם, אבל שהוגדרה על ידי אפליקציה זדונית ועם רמות הגנה שונות.
הרשאות מותאמות אישית נועדו לאפשר שיתוף משאבים ויכולות עם אפליקציות אחרות. דוגמאות לשימוש לגיטימי בהרשאות מותאמות אישית:
- שליטה בתקשורת בין תהליכים (IPC) בין שתי אפליקציות או יותר
- גישה לשירותים של צד שלישי
- הגבלת הגישה לנתונים משותפים של אפליקציה
השפעה
ההשפעה של ניצול הפגיעות הזו היא שאפליקציה זדונית יכולה לקבל גישה למשאבים שהיו אמורים להיות מוגנים. ההשלכות של הפגיעות תלויות במשאב שמוגן ובהרשאות המשויכות לשירות האפליקציה המקורי.
סיכון: שגיאות הקלדה בהרשאות מותאמות אישית
יכול להיות שהרשאה מותאמת אישית מוצהרת בקובץ המניפסט, אבל נעשה שימוש בהרשאה מותאמת אישית אחרת כדי להגן על רכיבי Android שיוצאו, בגלל שגיאת הקלדה. אפליקציה זדונית יכולה לנצל אפליקציות שבהן יש שגיאת כתיב בהרשאה באחת מהדרכים הבאות:
- צריך לרשום את ההרשאה הזו קודם
- לצפות את האיות באפליקציות הבאות
ההרשאה הזו יכולה לאפשר לאפליקציה גישה לא מורשית למשאבים או שליטה באפליקציה שהיא הקורבן.
לדוגמה, אפליקציה פגיעה רוצה להגן על רכיב באמצעות ההרשאה READ_CONTACTS, אבל בטעות מאייתת את ההרשאה כ-READ_CONACTS. אפליקציה זדונית יכולה לתבוע בעלות על READ_CONACTS כי אף אפליקציה (או המערכת) לא בבעלותה, ולקבל גישה לרכיב המוגן. עוד וריאציה נפוצה של הפגיעות הזו היא android:permission=True. ערכים כמו
true ו-false, ללא קשר לאותיות רישיות, הם קלט לא תקין להצהרת ההרשאה, והמערכת מתייחסת אליהם באופן דומה לשגיאות כתיב אחרות בהצהרת הרשאה מותאמת אישית. כדי לפתור את הבעיה, צריך לשנות את הערך של מאפיין android:permission למחרוזת הרשאות תקינה. לדוגמה, אם האפליקציה צריכה לגשת לאנשי הקשר של המשתמש, הערך של מאפיין android:permission צריך להיות android.permission.READ_CONTACTS.
אמצעי צמצום סיכונים
בדיקות Android Lint
כשמצהירים על הרשאות בהתאמה אישית, כדאי להשתמש בבדיקות של Android lint כדי למצוא שגיאות הקלדה ושגיאות פוטנציאליות אחרות בקוד.
מוסכמות למתן שמות
כדאי להשתמש במוסכמה עקבית למתן שמות כדי שיהיה קל יותר לזהות שגיאות הקלדה. צריך לבדוק בקפידה את הצהרות ההרשאות המותאמות אישית במניפסט של האפליקציה כדי לוודא שאין בהן שגיאות הקלדה.
סיכון: הרשאות יתומות
ההרשאות משמשות להגנה על משאבים של אפליקציות. יש שני מקומות שונים שבהם אפליקציה יכולה להצהיר על ההרשאות שנדרשות לגישה למשאבים:
- AndroidManifest.xml: מוגדר מראש בקובץ AndroidManifest.xml (אם לא מצוין, נעשה שימוש בהרשאות
<application>), למשל, provider permission, receiver permission, activity permission, service permission; - קוד: רשום בקוד זמן הריצה, למשל,
registerReceiver().
עם זאת, לפעמים ההרשאות האלה לא מוגדרות על ידי תג <permission> תואם במניפסט של APK במכשיר. במקרה כזה, ההרשאות נקראות הרשאות יתומות. יכולות להיות לכך כמה סיבות, כמו:
- יכול להיות שיהיה חוסר סנכרון בין העדכונים במניפסט לבין הקוד עם בדיקת ההרשאות
- יכול להיות שקובץ ה-APK עם ההרשאות לא ייכלל ב-build, או שתיכלל גרסה שגויה
- יכול להיות שהשם של ההרשאה בבדיקה או במניפסט מאוית בצורה שגויה
אפליקציה זדונית יכולה להגדיר הרשאה יתומה ולקבל אותה. אם זה יקרה, יכול להיות שהאפליקציות עם הרשאות מיוחדות שסומכות על ההרשאה היתומה כדי להגן על רכיב מסוים ייפגעו.
במקרים שבהם האפליקציה עם ההרשאות המיוחדות משתמשת בהרשאה כדי להגן על רכיב כלשהו או להגביל את הגישה אליו, האפליקציה הזדונית עשויה לקבל גישה לרכיב הזה. דוגמאות: הפעלת פעילויות שמוגנות על ידי הרשאה, גישה לספק תוכן או שידור למקלט שידור שמוגן על ידי הרשאה יתומה.
יכול להיות גם מצב שבו האפליקציה עם ההרשאות המיוחדות תרומה לחשוב שהאפליקציה הזדונית היא אפליקציה לגיטימית, ולכן היא תטען קבצים או תוכן.
אמצעי צמצום סיכונים
מוודאים שכל ההרשאות המותאמות אישית שהאפליקציה משתמשת בהן כדי להגן על רכיבים מוגדרות גם בקובץ המניפסט.
האפליקציה משתמשת בהרשאות המותאמות אישית my.app.provider.READ ו-my.app.provider.WRITE כדי להגן על הגישה לספק תוכן:
Xml
<provider android:name="my.app.database.CommonContentProvider" android:readPermission="my.app.provider.READ" android:writePermission="my.app.provider.WRITE" android:exported="true" android:process=":myappservice" android:authorities="my.app.database.contentprovider"/>
האפליקציה גם מגדירה ומשתמשת בהרשאות המותאמות אישית האלה, וכך מונעת מאפליקציות זדוניות אחרות לעשות זאת:
Xml
<permission android:name="my.app.provider.READ"/>
<permission android:name="my.app.provider.WRITE"/>
<uses-permission android:name="my.app.provider.READ" />
<uses-permission android:name="my.app.provider.WRITE" />
סיכון: שימוש לא נכון ב-android:protectionLevel
במאפיין הזה מתואר רמת הסיכון הפוטנציאלית בהרשאה, ומצוין אילו פעולות המערכת צריכה לבצע כשהיא מחליטה אם להעניק את ההרשאה או לא.
אמצעי צמצום סיכונים
לא מומלץ לבחור ברמת הגנה רגילה או מסוכנת
שימוש בהרשאה רגילה או מסוכנת protectionLevel בהרשאות שלכם אומר שרוב האפליקציות יכולות לבקש ולקבל את ההרשאה:
- במקרה של 'רגיל' צריך רק להצהיר על כך
- הרבה משתמשים יאשרו את ההגדרה 'מסוכן'
לכן, protectionLevels האלה מספקות אבטחה מועטה.
שימוש בהרשאות חתימה (Android מגרסה 10 ואילך)
מומלץ להשתמש ברמות הגנה על חתימות בכל מקום שאפשר. השימוש ביכולת הזו מבטיח שרק אפליקציות אחרות שנחתמו באותו אישור כמו האפליקציה שיצרה את ההרשאה יוכלו לגשת לתכונות המוגנות האלה. חשוב לוודא שאתם משתמשים באישור חתימה ייעודי (לא נעשה בו שימוש חוזר) ושומרים אותו בצורה מאובטחת במאגר מפתחות.
כך מגדירים הרשאה בהתאמה אישית במניפסט:
Xml
<permission
android:name="my.custom.permission.MY_PERMISSION"
android:protectionLevel="signature"/>
הגבלת הגישה, למשל, לפעילות, רק לאפליקציות שקיבלו את ההרשאה המותאמת אישית הזו, באופן הבא:
Xml
<activity android:name=".MyActivity" android:permission="my.custom.permission.MY_PERMISSION"/>
כל אפליקציה אחרת שנחתמת באותו אישור כמו האפליקציה שהצהירה על ההרשאה המותאמת הזו תקבל גישה לפעילות .MyActivity ותצטרך להצהיר עליה במניפסט שלה באופן הבא:
Xml
<uses-permission android:name="my.custom.permission.MY_PERMISSION" />
זהירות מפני הרשאות מותאמות אישית של חתימה (Android בגרסה < 10)
אם האפליקציה מיועדת ל-Android בגרסה נמוכה מ-10, בכל פעם שההרשאות המותאמות אישית של האפליקציה מוסרות בגלל הסרות או עדכונים, יכול להיות שאפליקציות זדוניות יוכלו להמשיך להשתמש בהרשאות המותאמות אישית האלה ולעקוף את הבדיקות. הסיבה לכך היא פרצת אבטחה של הסלמת הרשאות (privilege escalation) (CVE-2019-2200) שתוקנה ב-Android 10.
זו אחת הסיבות (בנוסף לסיכון של תנאי מירוץ) שבגללן מומלץ להשתמש בבדיקות חתימה במקום בהרשאות בהתאמה אישית.
סיכון: מרוץ תהליכים
אם אפליקציה לגיטימית A מגדירה הרשאה מותאמת אישית של חתימה שמשמשת אפליקציות אחרות X, אבל היא מוסרת בהמשך, אפליקציה זדונית B יכולה להגדיר את אותה הרשאה מותאמת אישית עם protectionLevel שונה, למשל normal. בדרך הזו, B מקבל גישה לכל הרכיבים שמוגנים על ידי ההרשאה המותאמת אישית הזו באפליקציות של X, בלי צורך להיכנס עם אותו אישור כמו באפליקציה A.
אותו דבר קורה אם B מותקן לפני A.
אמצעי צמצום סיכונים
אם רוצים שרכיב יהיה זמין רק לאפליקציות שנחתמו באותו חתימה כמו האפליקציה שמספקת אותו, יכול להיות שאפשר להימנע מהגדרת הרשאות מותאמות אישית כדי להגביל את הגישה לרכיב הזה. במצב כזה, אפשר להשתמש בבדיקות חתימה. כש אחת מהאפליקציות שלכם שולחת בקשה לאפליקציה אחרת שלכם, האפליקציה השנייה יכולה לוודא ששתי האפליקציות חתומות באותו אישור לפני שהיא נענית לבקשה.
משאבים
- צמצום הבקשות להרשאות
- סקירה כללית של ההרשאות
- תיאור רמות ההגנה
- CustomPermissionTypo Android Lint
- איך משתמשים ב-Android Lint
- מאמר מחקר עם הסבר מפורט על הרשאות Android וממצאים מעניינים של בדיקות fuzz