Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Android Security 最前線
Search
YANOKURO
March 10, 2017
Technology
2
2.4k
Android Security 最前線
AndroidNougatで追加されたSecurity関係のAPIの使い方をまとめたものです。
YANOKURO
March 10, 2017
Tweet
Share
Other Decks in Technology
See All in Technology
Digitization部 紹介資料
sansan33
PRO
1
5.8k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
2
250
IBC 2025 動画技術関連レポート / IBC 2025 Report
cyberagentdevelopers
PRO
2
250
CloudComposerによる大規模ETL 「制御と実行の分離」の実践
leveragestech
0
160
激動の2025年、Modern Data Stackの最新技術動向
sagara
0
300
OPENLOGI Company Profile for engineer
hr01
1
46k
20251102 WordCamp Kansai 2025
chiilog
1
520
datadog-incident-management-intro
tetsuya28
0
120
OpenCensusと歩んだ7年間
bgpat
0
330
新米エンジニアをTech Leadに任命する ー 成長を支える挑戦的な人と組織のマネジメント
naopr
1
350
東京大学「Agile-X」のFPGA AIデザインハッカソンを制したソニーのAI最適化
sony
0
190
戦えるAIエージェントの作り方
iwiwi
21
10k
Featured
See All Featured
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.7k
How STYLIGHT went responsive
nonsquared
100
5.9k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Side Projects
sachag
455
43k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Become a Pro
speakerdeck
PRO
29
5.6k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.5k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.3k
Designing Experiences People Love
moore
142
24k
The Pragmatic Product Professional
lauravandoore
36
7k
How to train your dragon (web standard)
notwaldorf
97
6.3k
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