Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Android Security 最前線
Search
YANOKURO
March 10, 2017
Technology
2.5k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Android Security 最前線
AndroidNougatで追加されたSecurity関係のAPIの使い方をまとめたものです。
YANOKURO
March 10, 2017
Other Decks in Technology
See All in Technology
Let's Change Our World—Again
snoozer05
PRO
4
280
CTO Night|NotionのAIエージェントとFDE
kzkhykw1991
0
300
LLM-as-a-Judgeは本当に信頼できるのか――評価器を評価する話
taka_aki
2
1k
How to Design Configuration for Rails Applications
willnet
1
1.1k
FinOps Agentが生んだ技術負債:コスト自動調査の落とし穴と解消までの道のり
oasis1994liveforever
3
250
macOS Golden Gate 時代のMac管理
tategami
0
110
生成AI時代、PMは事業責任者に進化するともっと面白い〜PMだからこそ事業構造を動かせる時代に〜
kakehashi
PRO
0
190
『SAR衛星データ解析入門』のご紹介とその応用
syuchimu
0
140
QA4AI 2026-Oct 生成AI時代の品質保証
tokuty
1
940
JAWS-UGグッズ職人仕事の流儀
kentapapa
0
130
CSS2026:OWS研究会・招待講演「世界観を、実装する」
atsush1_sada
2
130
初海外で注意すべきこと12選!!!安全快適なre:invent生活にするために
yuuuuuuu168
1
190
Featured
See All Featured
Designing Experiences People Love
moore
143
24k
SEO for Brand Visibility & Recognition
aleyda
0
4.8k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
2
330
Building the Perfect Custom Keyboard
takai
2
910
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
410
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
410
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
2
2k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
3k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
630
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.2k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
500
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
550
Transcript
Android Security ࠷લઢʂ Naoki Yano
ً Ϡϑʔגࣜձࣾ GYAOגࣜձࣾ Android Framework / Application / CTS
/ Driver Engineer Androidྺ 3 ؔ౦ྺ 2
Android Security ࠷લઢʁʁ Android Nougat ʹɺ SecurityपΓͷΞοϓσʔτ͕͍ͬͺ͍ʂʂ ɾUsing Scoped Directory
Access ɾDirect Boot ɾNetwork Security Config ɾKey Attestation ɾAPK Signature Scheme v2 ͍ͭͰ͑ΔΑ͏ʹ ४උ͓ͯ͘͜͠ͱ͕େࣄʂʂ
Android N Security Using Scoped Directory Access Direct Boot Network
Security Config Key Attestation APK Signature Scheme v2
Using Scoped Directory Access Android 6.0 Ҏલɿ ɹɹManifestʹPermissionΛఆٛ + PermissionRequest
ɹɹ֎෦ετϨʔδશͯͷΞΫηεΛڐՄɻ APP/FW Dir root Dir A Dir B Dir C Request Permit
Using Scoped Directory Access Android 7.0ɿ ɹɹΞΫηε͍ͨ͠σΟϨΫτϦͷStorageVolumeΛ࡞͠ɺRequestΛ͛Δɻ ɹɹಛఆͷσΟϨΫτϦͷΞΫηεͷΈڐՄ͢Δɻ APP/FW Dir
root Dir A Dir B Dir C Request Permit
Using Scoped Directory Access ৽نAPI ɾStorageVolume - ಛఆͷϢʔβʔͷڞ༗/֎෦ετϨʔδϘϦϡʔϜʹؔ͢Δใɻ - createAccessIntent()
- ϢʔβʔͷঝೝΛಘͨޙɺඪ४ͷετϨʔδσΟϨΫτϦ·ͨϘϦϡʔϜશମ ͷΞΫηεΛ༩͑ΔͨΊͷΠϯςϯτΛ࡞͢Δɻ - getState() - ετϨʔδϘϦϡʔϜͷঢ়ଶΛऔಘ͢Δɻ
Using Scoped Directory Access ৽نAPI ɾStorageManager ඞཁͳStorageVolumeΛऔಘ͢Δɻ - getPrimaryStorageVolume() -
getStorageVolume(File) - getStorageVolumes()
Using Scoped Directory Access // ΞΫηεݖ͕ඞཁͳstorageVolumeͷऔಘ StorageManager sm = getSystemService(StorageManager.class);
StorageVolume sv = sm.getPrimaryStorageVolume(); // ϢʔβʔঝೝΛಘΔͨΊͷIntentΛੜ Intent i = sv.createAccessIntent(Environment.DIRECTORY_MUSIC); // IntentΛStartActivityForResultͰ͛Δ startActivityForResult(i, REQUEST_CODE);
StorageVolume#createAccessIntent(String) package android.os.storage; public final class StorageVolume implements Parcelable {
… public @Nullable Intent createAccessIntent(String directoryName) { if ((isPrimary() && directoryName == null) || (directoryName != null && !Environment.isStandardDirectory(directoryName))) { return null; } final Intent intent = new Intent(ACTION_OPEN_EXTERNAL_DIRECTORY); intent.putExtra(EXTRA_STORAGE_VOLUME, this); intent.putExtra(EXTRA_DIRECTORY_NAME, directoryName); return intent; }
StorageVolume#createAccessIntent(String) package android.os; public class Environment { public static final
String[] STANDARD_DIRECTORIES = { DIRECTORY_MUSIC, DIRECTORY_PODCASTS, DIRECTORY_RINGTONES, DIRECTORY_ALARMS, DIRECTORY_NOTIFICATIONS, DIRECTORY_PICTURES, DIRECTORY_MOVIES, DIRECTORY_DOWNLOADS, DIRECTORY_DCIM, DIRECTORY_DOCUMENTS };
OpenExternalDirectoryActivity package com.android.documentsui; public class OpenExternalDirectoryActivity extends Activity { …
public void onCreate(Bundle savedInstanceState) { // σΟϨΫτϦ͕ࢦఆ͞Εͯͳ͍߹ɺrootͷݖݶΛऔಘ String directoryName = intent.getStringExtra(EXTRA_DIRECTORY_NAME ); if (directoryName == null) { directoryName = DIRECTORY_ROOT; } //ύʔϛογϣϯऔಘࡁΈͰͳ͍͔֬ೝ final StorageVolume volume = (StorageVolume) storageVolume; if (getScopedAccessPermissionStatus(getApplicationContext(), getCallingPackage(), volume.getUuid(), directoryName) == PERMISSION_NEVER_ASK) { //Ϣʔβ֬ೝDialogදࣔ final int userId = UserHandle.myUserId(); if (!showFragment(this, userId, volume, directoryName)) { }
Using Scoped Directory Access @Override public void onActivityResult(int requestCode, int
resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) { // ̎ճҎ߱μΠΞϩάΛग़͞ͳ͍Α͏ʹઃఆ getActivity().getContentResolver().takePersistableUriPermission(data.getData(), Intent.FLAG_GRANT_READ_URI_PERMISSION | ɹɹɹɹ Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // read, write // data.getData() ʹΞΫηεݖΛಘͨσΟϨΫτϦͷURI͕ೖ͍ͬͯΔ } }
Using Scoped Directory Access ɾײ ɹɹɾσΟϨΫτϦຖʹΞΫηεڐՄΛඞཁͱ͢Δͷɺ ɹɹɹ͏ଆͱͯ҆͠৺Ͱ͖Δɻ ɹɹɾϓϥΠϚϦετϨʔδͱͦΕҎ֎ͰAPIͷ͍ํ͕ ɹɹɹมΘͬͯ͘ΔͷͰҙʂ
Direct Boot Android 6.0 Ҏલɿ ɹɹ͕҉߸Խ͞Ε͍ͯΔ߹ɺطଘͷอଘઌɺ ɹɹϢʔβʔ͕ϩοΫΛղআͨ͠ޙʹ͚ͩ༻Ͱ͖Δɻ APP/FW data/user Boot
Unlock user key
Direct Boot APP/FW user Boot Unlock Android 7.0ɿ ɹɹϩοΫղআ͞Ε͍ͯͳ͍ঢ়ଶͰɺμΠϨΫτϒʔτϞʔυͰಈ࡞͢Δɻ ɹɹ҉߸ԽετϨʔδʹΞΫηεͰ͖Δɻ
user_de hard−backed key user key
Direct Boot ৽نAPI ɾandroid:directBootAware ίϯϙʔωϯτ͕҉߸ԽରԠ͢ΔΑ͏ʹࢦఆ͢Δɻ ɾandroid.intent.action.LOCKED_BOOT_COMPLETED ҉߸ԽετϨʔδ͕༻Մೳʹͳͬͨ͜ͱΛ௨͢Δɻ ɾContext#createDeviceProtectedStorageContext() ҉߸ԽετϨʔδʹΞΫηε͢ΔͨΊͷContextΛੜ͢Δɻ
Direct Boot // ίϯϙʔωϯτ͕҉߸ԽରԠ͢ΔΑ͏ʹFlagΛͨͯΔ <receiver android:name=".BootBroadcastReceiver" android:exported="false" android:directBootAware="true"> <intent-filter> <action
android:name="android.intent.action.LOCKED_BOOT_COMPLETED" /> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
Direct Boot // ProtectedStorageͷอଘ final Context deviceContext = getApplicationContext().createDeviceProtectedStorageContext(); deviceContext.moveSharedPreferencesFrom(context,
PREFERENCES_NAME)); SharedPreferences sp = deviceContext .getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
Direct Boot // LOCKED_BOOT_COMPLETEDΛड͚ͯσʔλΛऔಘ͢Δ public void onReceive(Context context, Intent intent)
{ boolean bootCompleted; String action = intent.getAction(); if (BuildCompat.isAtLeastN()) { bootCompleted = Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(action); } else { bootCompleted = Intent.ACTION_BOOT_COMPLETED.equals(action); } if (!bootCompleted) { return; } }
Android 6.0 Ҏલɿ Android 7.0ɿ Direct Boot Android Boot Unlocked
Android Boot Unlocked BOOT_COMPLETED LOCKED_BOOT_COMPLETED USER_UNLOCKED BOOT_COMPLETED
Direct Boot ApplicationInfo ai = getApplicationInfo(); Log.i(TAG, “deviceProtectedDataDir: ” +
ai.deviceProtectedDataDir); # deviceProtectedDataDir: /data/user_de/0/com.yanokuro.directboot
Direct Boot ɾײ ɹɹɾ҉߸ԽετϨʔδͰɺηΩϡϦςΟϨϕϧ͕ ɹɹɹԼ͕ΔͨΊɺԿΛอଘ͢Δ͔ਫ਼͕ࠪඞཁɻ ɹɹɾBOOT_COMPLETE͕ݺΕΔҐஔ͕มΘͬͨΑɻ
Network Security Config Android 7.0ɿ ΧελϜCAূ໌ॻΛ৴པ͢ΔͨΊͷ҆શͰ؆୯ͳAPIͷఏڙɻ σϑΥϧτͰɺϢʔβʔ͕Ճͨ͠CAΛ৴པ͠ͳ͍ɻ
Network Security Config ɾres/xml/network_security_config Λ࡞ ɾmanifestʹه
Network Security Config <?xml version="1.0" encoding="utf-8"?> <manifest ... > <application
... > <meta-data android:name="android.security.net.config" android:resource="@xml/network_security_config" /> </application> </manifest>
Network Security ConfigɹΧελϜͷূ໌ػؔ <?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>
Network Security Configɹূ໌ॻͷఆٛ <trust-anchors> // ΞϓϦ͕͍࣋ͬͯΔCAূ໌ॻΛ༻ <certificates src="@raw/my_ca"/> // γεςϜσϑΥϧτͷCAূ໌ॻΛ༻
<certificates src="system"/> // Ϣʔβ͕Ճͨ͠CAূ໌ॻΛ༻ <certificates src="user"/> </trust-anchors>
Network Security Configɹσόοά༻ debuggable=true <?xml version="1.0" encoding="utf-8"?> <network-security-config> <debug-overrides> <trust-anchors>
<certificates src="@raw/debug_ca"/> </trust-anchors> </debug-overrides> </network-security-config>
Network Security ConfigɹΫϦΞςΩετͷ௨৴Λېࢭ <?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config usesCleartextTraffic="false"> <domain
includeSubdomains="true">secure.example.com</ domain> </domain-config> </network-security-config>
Network Security ConfigɹߏϑΝΠϧ <?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> ... </base-config>
<domain-config> ... </domain-config> <debug-overrides> ... </debug-overrides> </network-security-config>
Network Security ConfigɹAndroid 7.0 default <base-config usesCleartextTraffic="true"> <trust-anchors> <certificates src="system"
/> </trust-anchors> </base-config>
Network Security ConfigɹAndroid 7.0 ະຬ <base-config usesCleartextTraffic="true"> <trust-anchors> <certificates src="system"
/> <certificates src="user" /> </trust-anchors> </base-config>
Network Security Config ɾײ ɹɹɾઃఆΞϓϦ͔ΒCAೖΕΔඞཁ͕ͳ͘ͳͬͯخ͍͠ɻ ɹɹɾ7.0ΑΓલͰ͑Δͱ͍͍ͳɻ
·ͱΊ ͦΕͧΕҙϙΠϯτ͋Δ͕ɺؾΛ͚ͭͯ͑ΑΓη ΩϡΞͳΞϓϦ͕࡞Εͦ͏ɻ ֤ػೳͷಈ͖Λ͔ͬ͠Γཧղͯ͠։ൃ͠·͠ΐ͏ɻ
EOF