תיקון לפרצת אבטחה מסוג הפניה אוטומטית של Intent

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

מה הלאה?

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

הפעולה הנדרשת

  1. נכנסים לחשבון Play Console ועוברים לקטע ההתראות כדי לבדוק אילו אפליקציות מושפעות מהבעיות ומהם המועדים האחרונים לתיקון בעיות אלה.
  2. מעדכנים את האפליקציות המושפעות באמצעות השלבים שבהמשך.
  3. שולחים את הגרסאות המעודכנות של האפליקציות המושפעות.

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

פרטים נוספים

השימוש ב-Intent לא מהימן לפעילות של רכיב (למשל, על ידי הפעלת startActivity) או לאחזור נתונים (למשל, על ידי הפעלת setResult) מסוכן ועלול לאפשר לאפליקציות זדוניות לגרום לבעיות הבאות: 

  1. גניבת קבצים רגישים או נתוני מערכת (כמו הודעות SMS) מהאפליקציה
  2. הפעלת רכיבים פרטיים של האפליקציה עם ארגומנטים מורעלים.

חשוב שהאפליקציה לא תשמש לקריאה של startActivity‏, startService‏, sendBroadcast‏ או setResult‏ במנגנוני Intent לא מהימנים מבלי לאמת את מנגנוני ה-Intent או לאבטח אותם.

אנחנו ממליצים למנוע את פרצת האבטחה הזו באחת מהדרכים הבאות:

אפשרות 1: מגדירים את רכיב האפליקציה המושפע, שממנו יש הפניה אוטומטית ל-Intent שנשלף, כפרטי.

אם רכיב האפליקציה המושפע לא צריך לקבל מנגנוני Intent מאפליקציות אחרות, אפשר להגדיר את רכיב האפליקציה כפרטי באמצעות הגדרת android:exported=”false” במניפסט.

אפשרות 2: מוודאים שה-Intent שנשלף הגיע ממקור מהימן.

ניתן לוודא שפעילות המקור מהימנה באמצעות שיטות כמו getCallingActivity. למשל:

 ‎// check if the originating Activity is from trusted package
 if ‎(getCallingActivity().getPackageName().equals(“known”)) {‎
   Intent intent = getIntent();‎
   ‎// extract the nested Intent
   Intent forward = (Intent) intent.getParcelableExtra(“key”);‎
   ‎// redirect the nested Intent
   startActivity(forward);‎
‎  }‎

הערה:

  • כדי למנוע את פרצת האבטחה, לא מספיק לבדוק אם שיטת getCallingActivity()‎ מובילה לערך של נתון קיים. אפליקציות זדוניות עלולות לספק ערך null לפונקציה הזו.
  • במקרה של Google Play Services SMS Retriever Auth, הגנה על מקלט שידורים באמצעות SEND_PERMISSION תבטיח שה-Intent מגיע מ-Play Services.

אפשרות 3: מוודאים שה-Intent המיועד להפניה אוטומטית לא מזיק.

יש לוודא שה-Intent בהפניה האוטומטית

  1. לא יישלח לאף רכיב פרטי של האפליקציה שלכם, וגם
  2. לא יישלח לאף רכיב של אפליקציה חיצונית. אם ההפניה האוטומטית מיועדת לאפליקציה של צד שלישי, צריך לוודא שה-Intent לא יעניק הרשאת URI לאחד מספקי התוכן הפרטיים של האפליקציה או לנתוני המערכת.

אפליקציות יכולות לבדוק איזה רכיב ישמש לטיפול ב-Intent לפני הפניה אוטומטית שלו באמצעות שיטות כמו resolveActivity. למשל:

 Intent intent = getIntent();‎
 ‎// extract the nested Intent
 Intent forward = (Intent) intent.getParcelableExtra(“key”);‎
 ‎// get the component name
 ComponentName name = forward.resolveActivity(getPackageManager());‎
 ‎// check that the package name and class name are as intended
 if (name.getPackageName().equals(“safe_package”) &&
     name.getClassName().equals(“safe_class”)) {‎
   ‎// redirect the nested Intent
   startActivity(forward);‎
‎  }‎

אפליקציות יכולות לבדוק אם Intent מעניק הרשאת URI באמצעות שיטות כמו getFlags. למשל:

 ‎// extract the nested Intent
 Intent forward = (Intent) intent.getParcelableExtra(“key”);‎
 ‎// get the flags
 int flags = forward.getFlags();‎
 ‎// check that the nested intent does not grant URI permissions
 if ((flags & Intent.FLAG_GRANT_READ_URI_PERMISSION == 0) &&‎
     ‎(flags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION == 0)) {‎
   ‎// redirect the nested Intent
   startActivity(forward);‎
 ‎}‎

אפליקציות יכולות גם להסיר הרשאות URI שניתנו באמצעות removeFlags. למשל:

 // untrusted Intent
 Intent intent = getIntent();
 // remove the grant URI permissions in the untrusted Intent
 intent.removeFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 intent.removeFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
 // pass the untrusted Intent
 setResult(intent);

הסבר על ההתראות ובחירה באפשרות מניעה 

ההתראה של Play Console מדווחת היכן האפליקציה מפעילה startActivity‏, startActivityForResult,‏ startService,‏ sendBroadcast או setResult באמצעות Intent לא מהימן. כדי להבין מהי אפשרות המניעה המתאימה ביותר, צריך להתחקות אחר פונקציות קריאה חוזרת של שיטות כדי לאתר את המקור של ה-Intent הלא מהימן. לדוגמה, באפשרות 1, בודקים איזה רכיב צריך להגדיר כפרטי.

אנחנו כאן כדי לעזור

אם יש לכם שאלות טכניות לגבי פרצת האבטחה, תוכלו לפרסם אותן באתר Stack Overflow ולהשתמש בתג “android-security”. להבהרה לגבי השלבים שיש לבצע עד לפתרון הבעיה, תוכלו לפנות לצוות התמיכה במפתחים.

false
התפריט הראשי
1258333026798651607
true
חיפוש במרכז העזרה
true
true
true
true
true
5016068
false
false