מהנדס בכיר לקשרי מפתחים
במצגת הזו נסביר על השינוי האסטרטגי במעבר מהתייחסות ל-AI כעוזר גנרי לתכנות, לשימוש בו כבודק עמיתים אוטומטי לאבטחה שמותאם להקשר ומשולב ישירות במחזור החיים של הפיתוח ל-Android. אנחנו מסבירים איך סוכני AI מיוחדים, שמחוברים ל-toolchain של Android באמצעות מיומנויות, יכולים לעזור לשפר את אבטחת האפליקציה. הגישה הזו מגשרת על הפער בין היכולות הגולמיות של מודל ה-LLM לבין ההקשר המעמיק של הפרויקט, ומאפשרת לצוותי הפיתוח להמשיך לספק תכונות במהירות גבוהה בלי להתפשר על תקני אבטחה ומדיניות מחמירים.
תמליל
היי, אני קריסטן.
היי, אני סאבס.
ואנחנו כאן כדי לדבר איתכם היום על אבטחה בעידן סוכני ה-AI.
בשנה האחרונה הענקנו פרסים בסך של יותר מ-2 מיליון דולר במסגרת תוכנית Android Bug Hunters, ויותר מ-200, 000 דולר במסגרת התוכנית לנייד.
בעידן סוכני ה-AI, אבטחת האפליקציות מתפתחת כל הזמן.
עכשיו נדבר על הכלים שיעזרו לנו לפתור את הבעיות האלה במהירות וביעילות.
כדי לשפר את הביצועים של הסוכנים בנושא אבטחה ב-Android, הפתרון הוא לא הנחיה טובה יותר.
אלה כלים ותהליכי עבודה שעוזרים לסוכנים להבין את ה-API ואת ה-toolchains שלנו, כדי לשמור על בטיחות האפליקציה.
אז השעה היא 16:30.
ביום חמישי.
אתם משיקים גרסה, וה-CI הופך לאדום, רק שגיאה אחת: מקלט שידורים רשום ללא דגל ייצוא.
לכן, לא משנה אם אתם עובדים בצוות קטן שבו אתם עושים הכול, או בצוות גדול שבו בדיקות האבטחה מתבצעות כשאתם משיקים את הגרסה, המציאות היא אותה מציאות.
אנחנו מהנדסי מוצר, משיקים תכונות באיכות גבוהה במהירות, ולא בהכרח חוקרי אבטחה.
אז מה האינסטינקט הטבעי?
אז אנחנו מעבירים את האזהרה הזו לכלי מבוסס-סוכן, ומבקשים מהסוכן לתקן את הבעיה.
אבל לכלי מבוסס-סוכן שפועל בלי ההקשר של הפרויקט יש שלוש נקודות עיוורות.
יכול להיות שהמערכת לא תזהה שהאפליקציה שלכם בנויה ממודולים של תכונות דינמיות או מחבילות של כמה קובצי APK.
הוא רואה קובץ, לא פריט שנשלח.
יכול להיות שהוא לא ידע או לא יוכל לעקוב אחרי זרימת הנתונים מממשק המשתמש של Kotlin, דרך הלוגיקה המשותפת של KMP ועד לקריאות ה-JNI המקוריות של C++.
הוא רואה רק שכבה אחת.
ואחרון חביב, יכול להיות שהוא לא יכיר את גרסת ה-SDK המינימלית או את גרסאות ה-build של Gradle.
אז הפנינו נציג לאפליקציה וביקשנו ממנו לבצע בדיקת אבטחה.
התקבלו שישה ממצאים.
והנה העניין.
כל אחת מהן נכונה.
כולן הגיוניות, אבל רק אחת מהן היא הבאג שהתחלנו איתו.
השאר הוא שילוב של שיטות מומלצות, דברים שצריך לבדוק לעומק, השערות ודברים שאולי אפילו לא רלוונטיים.
אז עכשיו אתם מגדילים את זה ל-code base אמיתי, עם יותר אזהרות, ובכל בקשת משיכה, תתפתו להגיע ל-suppress lint.
תצטרכו לשנות את הקוד כדי למזג את השינוי, או שאולי אפילו תפספסו את נקודת החולשה לגמרי.
ככה נקודות חולשה אמיתיות חומקות מהבדיקה.
הכלי לא היה רשלני, הוא היה זהיר, אבל זהירות היא לא בהכרח מועילה.
בואו נראה דוגמה קונקרטית.
נניח שאתם מבקשים מהסוכן: "בדוק כל רכיב שיוצא באפליקציה הזו כדי לזהות הפניה אוטומטית של Intent באפליקציה".
זו משימת אבטחה אמיתית, ובאפליקציה עם כמה מודולים, זו משימה גדולה.
זה סוג הבקשה שבה העלות מופיעה בפועל.
בלי הנחיות ספציפיות ל-Android, לסוכן אין אסטרטגיה לשאלה הזו.
אז הוא משתמש בכוח גס.
הוא יכול לקרוא מודולים שלא מייצאים שום דבר.
יכול להיות שהיא תסיק מחדש מהעיקרון הראשון מה הופך הפניה ל-Intent לניתנת לניצול לרעה.
יכול להיות שהיא תעקוב אחרי נתיבים שמעולם לא היו נגישים.
אתם משלמים על ניתוח נתונים, לא על ניתוח.
מיומנות היא מה שמספק את האסטרטגיה החסרה.
לדוגמה, מיומנויות אבטחה ב-Android מספקות לסוכן הוראות שפועלות לפי ההנחיות הנוכחיות, אותו רצף של שלבים שחוקר אבטחה היה מבצע בפועל, והסוכן מפסיק לנחש.
הוא לא מגלה מחדש את הכללים כי הם סופקו על ידי המיומנות.
נכון לעכשיו, השקנו שתי מיומנויות אבטחה: אבטחת Intent והרשאות.
אבטחת Intent קשורה לפעולות שאפליקציות אחרות יכולות לגרום לאפליקציה שלכם לבצע.
לאפליקציה יש הרשאות וסשן כניסה לחשבון שאין לאתר.
לכן, כל רכיב שמיוצא וכל intent בהמתנה שאתם מוסרים הם דרך פוטנציאלית שבה מישהו יכול לפעול באמצעותכם.
הסקיל הזה עוזר להגן מפני המצב הזה.
היכולת הזו עוזרת לגשר על הפער בין הרשאה שמוצהרת לבין הרשאה שנאכפת בפועל.
הוא יכול לעזור לכם לכתוב את בדיקת ההרשאות המתאימה.
הוא עוזר לזהות אם ספק עם נתיב של תו כללי לחיפוש מעניק גישה לכל מסד הנתונים במקום לספרייה אחת.
היא גם מזהה בקשות להרשאות מוגזמות.
לדוגמה, לבקש גישה רחבה כשהכלי לבחירת תמונות מספיק.
משתמשים בו עם Android CLI, ואז שואלים "Audit for intent security".
אין הגדרות אישיות.
אין כוונון של כללים.
כך הפלט לא כולל רשימה ארוכה של אזהרות.
זו ביקורת.
יש כאן באג, הנה הסיבה שהוא משפיע על האפליקציה שלך, והנה התיקון.
והנה טיפ למתקדמים.
אפשר להשתמש ב-CLI של Android כדי למצוא ולהתקין בקלות.
android skills list
android skills add android-intent-security
android skills add android-permissions-securityהסקיל יודע בדיוק מה לחפש בפרויקט, ולכן הוא רואה את האפליקציה כמו שהיא נשלחת בפועל.
הוא מתחשב בגרסת ה-SDK המינימלית שלכם כדי שהתיקון יקומפל, בנתיבי קבצים אמיתיים ובמספרי שורות אמיתיים.
זו הביקורת שקיבלתם.
הוא מצביע על הקובץ והשורה המדויקים, מסביר את האיום האמיתי ואת הסיבה לשינוי, ולא רק אומר ש-Lint אומר את זה.
הוא מציין באיזה סקיל הוא השתמש.
הוא קרא את תצורת ה-build, זיהה את גרסת ה-SDK המינימלית 26, ובחר ב-ContextCompat כדי שהתיקון יעבוד. הוא גם נותן לכם את ההבדלים כדי שתוכלו להחיל אותם.
זו האזהרה שפתחנו איתה, אבל עכשיו עם הצעה לתיקון והסבר נוסף.
אז המיומנויות הקודמות מזהות באגים באבטחה.
עכשיו נדבר על תחום אחר, תאימות למדיניות בנושא אפליקציות.
לדוגמה, נניח שאתם מפתחי אפליקציות חדשים שרוצים להשיק אפליקציה בחנות Play.
מילוי טופס אבטחת הנתונים הוא שלב חשוב בהשקת האפליקציה, אז כדאי להשתמש בכל הכלים האפשריים כדי לוודא שהכול תקין לפני ששולחים את האפליקציה לבדיקה.
המיומנות "מדיניות Play" מבצעת ניתוח סטטי של ה-code base.
אם אתם מפרסמים אפליקציה קיימת בחנות Play, המערכת יכולה גם להצליב את ניתוח הקוד הסטטי עם ההצהרות בחנות Play.
הפעלת המיומנות הזו יכולה לעזור לכם לזהות בעיות פוטנציאליות שקשורות למדיניות של Play לפני שליחת האפליקציה, ולא אחרי, ולזרז את תהליך השליחה.
תהליך העבודה דומה למיומנויות האחרות שדיברנו עליהן: מייבאים את האפליקציה ואז מבקשים: "תבדוק אם האפליקציה הזו עומדת בדרישות המדיניות של Google Play לפני שאשלח אותה".
בצד ימין מוצג צילום מסך של דוח לדוגמה, ומתחתיו פקודות ה-Android CLI להתקנה שלו.
android skills list
android skills add play-policy-insightsאז כל מה שדיברנו עליו עד עכשיו קורה לפני שאתם שולחים את האפליקציה: בדיקת ה-Intent, בדיקת ההרשאות ואימות התאימות.
זו אבטחה בזמן הפיתוח, והיא חיונית.
אבל יש סוג שלם של איומים שקיימים רק אחרי שקובץ ה-APK שלכם מופץ ופועל במכשירים שאולי אין לכם שליטה עליהם.
בזמן הריצה, Play Integrity API עונה על שלוש שאלות שהקוד שלכם לא יכול לענות עליהן בעצמו: האם זהו build מקורי ולא שונה של האפליקציה?
האם האפליקציה פועלת במכשיר Android מקורי?
האם זה חשבון משתמש ב-Play?
לכן, אתם יכולים להשתמש ב-Play Integrity API כדי לקבל קביעות לגבי תקינות האפליקציה, תקינות המכשיר ועוד.
בנוסף לכך שקל ומהיר יותר לפרסם את האפליקציה בצורה בטוחה יותר, קל יותר גם להגן על ההכנסות ועל המוניטין של האפליקציה.
לכן, חשוב להגן על העסק מפני הונאה וניצול לרעה.
מרכז הבקרה החדש של "מוגן על ידי Play", שמוצג כאן, עוזר לכם לעקוב אחרי ההגנות על התקינות, ההפצה והמונטיזציה ולהגדיר אותן במקום אחד.
אנחנו גם מקצרים את זמן האחזור של Play Integrity API, כדי שתוכלו להשתמש בבדיקות האלה במהלך חוויית שימוש הכרחית (CUJ) שבה המהירות קריטית, וכך לחסום איומים ומכשירים מסוכנים מהר יותר.
אז דיברנו על התכונות והכלים של Android שעוזרים לשמור על בטיחות האפליקציות, אבל מה לגבי המשתמשים?
קודם נסביר על הגנת OTP ב-SMS.
נניח שאתם רוצים להטמיע באפליקציה אימות משתמשים באמצעות SMS ולשלוח קודי אימות.
הרשאת ה-SMS מאפשרת לאפליקציה לגשת לנתוני ההודעות, כולל נתונים רגישים כמו סיסמאות חד-פעמיות.
לכן, הוספנו כמה ממשקי API לאפליקציה שלך כדי שתוכל להטמיע את זה, כך שלא תצטרך לבקש הרשאות SMS רחבות, אבל עדיין תוכל לקבל קודי OTP ב-SMS לצורך אימות.
ה-SMS Retriever API מאפשר לאפליקציה לאמת באופן אוטומטי סיסמאות חד-פעמיות בלי הרשאות נרחבות ל-SMS.
אתם מוסיפים להודעה גיבוב (hash) באורך 11 תווים שמזהה את האפליקציה, והמערכת מעבירה לכם רק את ההודעה הזו.
אם אין לכם שליטה על פורמט ההודעה, השתמשו ב-SMS User Consent API.
המערכת מציגה הודעה חד-פעמית.
המשתמש מקיש על "אישור" או "דחייה". אם הוא מאשר, אתם מקבלים את ההודעה הזו.
עדיין אין צורך בהרשאה נרחבת ל-SMS.
יכול להיות שאפליקציות מסוימות יצטרכו את המיקום המדויק רק פעם אחת כדי להשלים משימות.
ההרשאה החד-פעמית הקיימת גורמת לחיכוך רב עם המשתמשים, ולכן לפעמים המפתחים מבקשים הרשאה רחבה יותר למיקום מדויק.
הכפתור להרשאת מיקום חד-פעמית הוא כלי שמאפשר לתת לאפליקציה גישה חד-פעמית למיקום המדויק בצורה חלקה.
זהו רכיב בממשק המשתמש של Android שמפתחי אפליקציות יכולים להתאים אישית ולהטמיע.
ביוני השקנו את הגרסה הראשונה של ספריית Jetpack לכפתור להרשאת מיקום חד פעמית בגרסת אלפא.
כאן אפשר לראות את ההרשאות שנדרשות כדי להפעיל את הכפתור להרשאת מיקום חד פעמית במניפסט של Android.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
android:usesPermissionFlags="onlyForLocationButton"/>
<uses-permission android:name="android.permission.USE_LOCATION_BUTTON" />
<application
android:icon="@mipmap/ic_launcher"
android:label="LocationButtonSample"
android:theme="@style/Theme.PinPoint">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>צריך להצהיר על הרשאת מיקום רגילה – הוספת דגל ההרשאה onlyForLocationButton, יחד עם ההרשאה הייעודית USE_LOCATION_BUTTON שנדרשת על ידי שירות העיבוד מרחוק של המערכת.
בצד שמאל, מופיע קוד Jetpack להטמעה.
...
import androidx.core.locationbutton.compose.LocationButton
@Composable
fun LocationPermissionScreen(onPermissionGranted: () -> Unit, onPermissionDenied: () -> Unit) {
// Renders the secure system-trusted Location Button composable
LocationButton(
// Callback triggered when the user taps the secure button and makes a decision on the permission dialog
onPermissionResult = { isGranted ->
if (isGranted) {
onPermissionGranted()
} else {
onPermissionDenied()
}
},
...כאן אפשר לראות שאנחנו יוצרים כפתור להרשאת מיקום חד פעמית ומפעילים קריאה חוזרת (callback).
הקריאה החוזרת הזו מופעלת כשהמשתמש לוחץ על הכפתור להרשאת מיקום חד פעמית כדי להחליט אם לאשר או לדחות את ההרשאה.
מצב הגנה מתקדמת הוא תכונה שמיועדת למשתמשים בסיכון או למשתמשים שחשוב להם לשמור על אבטחה, אבל כל אחד יכול להצטרף.
לדוגמה, אם יש לכם אפליקציה של בנק, אתם לא מאלצים את המשתמשים לבצע אימות רב-שלבי בכל העברה, כי משתמשים רגילים לא אוהבים את החיכוך הנוסף הזה.
אבל כשמצב ההגנה המתקדמת מופעל, האפליקציה יודעת שהמשתמש הזה רוצה את רמת ההגנה המקסימלית, ולכן אתם יכולים לדרוש באופן אוטומטי אימות ביומטרי בכל העברה.
מצב הגנה מתקדמת מיישם קבוצה של הגדרות אישיות שנקבעו מראש, שנועדו לשפר את ההגנה על המכשיר.
כאן אנחנו מסבירים איך לשלב את ה-SDK באפליקציה.
אתם צריכים לבקש את ההרשאה, לשלוח שאילתה למצב ההגנה המתקדמת ולבדוק אם המשתמש הפעיל את מצב ההגנה המתקדמת באמצעות קריאה לשירות המערכת של מנהל מצב ההגנה המתקדמת במכשיר.
class AdvancedProtectionManager() {
// Check the current status
fun isAdvancedProtectionEnabled(): Boolean
// Be alerted when status changes
fun registerAdvancedProtectionCallback(executor: Executor,
callback: Callback)
fun unregisterAdvancedProtectionCallback(callback: Callback)
}
interface Callback() {
// Called when advanced protection state changes
fun onAdvancedProtectionChanged(enabled: Boolean)
}ואז, אתם יכולים להאזין לשינויים בזמן הריצה על ידי רישום של הקריאה החוזרת (callback).
android skills list
android skills add android-intent-security
android skills add android-permissions-securityandroid skills list
android skills add play-policy-insights<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
android:usesPermissionFlags="onlyForLocationButton"/>
<uses-permission android:name="android.permission.USE_LOCATION_BUTTON" />
<application
android:icon="@mipmap/ic_launcher"
android:label="LocationButtonSample"
android:theme="@style/Theme.PinPoint">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>...
import androidx.core.locationbutton.compose.LocationButton
@Composable
fun LocationPermissionScreen(onPermissionGranted: () -> Unit, onPermissionDenied: () -> Unit) {
// Renders the secure system-trusted Location Button composable
LocationButton(
// Callback triggered when the user taps the secure button and makes a decision on the permission dialog
onPermissionResult = { isGranted ->
if (isGranted) {
onPermissionGranted()
} else {
onPermissionDenied()
}
},
...class AdvancedProtectionManager() {
// Check the current status
fun isAdvancedProtectionEnabled(): Boolean
// Be alerted when status changes
fun registerAdvancedProtectionCallback(executor: Executor,
callback: Callback)
fun unregisterAdvancedProtectionCallback(callback: Callback)
}
interface Callback() {
// Called when advanced protection state changes
fun onAdvancedProtectionChanged(enabled: Boolean)
}