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.3k
Android Security 最前線
AndroidNougatで追加されたSecurity関係のAPIの使い方をまとめたものです。
YANOKURO
March 10, 2017
Tweet
Share
Other Decks in Technology
See All in Technology
強化されたAmazon Location Serviceによる新機能と開発者体験
dayjournal
3
230
自律的なスケーリング手法FASTにおけるVPoEとしてのアカウンタビリティ / dev-productivity-con-2025
yoshikiiida
0
200
生成AIで小説を書くためにプロンプトの制約や原則について学ぶ / prompt-engineering-for-ai-fiction
nwiizo
4
3k
製造業からパッケージ製品まで、あらゆる領域をカバー!生成AIを利用したテストシナリオ生成 / 20250627 Suguru Ishii
shift_evolve
PRO
1
160
TechLION vol.41~MySQLユーザ会のほうから来ました / techlion41_mysql
sakaik
0
200
KubeCon + CloudNativeCon Japan 2025 Recap by CA
ponkio_o
PRO
0
240
MySQL5.6から8.4へ 戦いの記録
kyoshidaxx
1
290
Node-RED × MCP 勉強会 vol.1
1ftseabass
PRO
0
170
高速なプロダクト開発を実現、創業期から掲げるエンタープライズアーキテクチャ
kawauso
1
110
AWS Organizations 新機能!マルチパーティ承認の紹介
yhana
1
210
AI導入の理想と現実~コストと浸透〜
oprstchn
0
130
CursorによるPMO業務の代替 / Automating PMO Tasks with Cursor
motoyoshi_kakaku
1
560
Featured
See All Featured
Gamification - CAS2011
davidbonilla
81
5.3k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.9k
What's in a price? How to price your products and services
michaelherold
246
12k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
44
2.4k
Agile that works and the tools we love
rasmusluckow
329
21k
Automating Front-end Workflow
addyosmani
1370
200k
Rebuilding a faster, lazier Slack
samanthasiow
82
9.1k
Making the Leap to Tech Lead
cromwellryan
134
9.4k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
17
950
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Raft: Consensus for Rubyists
vanstee
140
7k
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