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
HTTPSの基本から NetworkSecurityConfigまで
Search
Amane Nikaido
February 09, 2018
Technology
4.5k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
HTTPSの基本から NetworkSecurityConfigまで
Amane Nikaido
February 09, 2018
More Decks by Amane Nikaido
See All by Amane Nikaido
React with Kotlin
a2kaido
2
1.3k
Use Kotlin for build.gradle.
a2kaido
0
510
JavaからみたKotlin
a2kaido
0
140
Other Decks in Technology
See All in Technology
End-to-Endで考える信頼性 —LINEアプリにおけるクライアント開発×SRE連携の実践
maruloop
4
4.6k
タスクの複雑さでモデルを選ぶ ── Thompson Samplingで動かす“トークン/コスト最適化
satohy0323
0
560
関数型の考えを TypeScript に持ち込んで、テストしやすい純粋関数を増やす / Pure at the Core, Effects at the Edge: Bringing Functional Thinking into TypeScript
kaminashi
2
130
しくみを学んで使いこなそう GitHub Copilot app
torumakabe
2
290
壊して学ぶAWS CDK: そのcdk deployで消えるもの、残るもの
k_adachi_01
1
410
「守りたい体験」を渡すだけで E2E を生成させられるようになった話
hinac0
1
420
Type-safe IaC for Dart
coborinai
0
160
公式ドキュメントの歩き方etc
coco_se
1
120
AI時代の闇と光
tatsuya1970
0
110
Data + AI Summit 2026 イベントレポート: 「AIがビジネスで意思決定するデータ基盤」へ
nek0128
0
280
LLM/Agent評価:トップ営業の発言を「正解」にする 〜暗黙的正解による評価を営業資産に変える〜
takkuhiro
1
230
SRE依存からの脱却 運用を開 発チームへ移す、 フルサイ クル開 発体制の実践
joooee0000
0
3.2k
Featured
See All Featured
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
350
Designing for humans not robots
tammielis
254
26k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
420
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.4k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
67
56k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
What does AI have to do with Human Rights?
axbom
PRO
1
2.2k
How GitHub (no longer) Works
holman
316
150k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.2k
Into the Great Unknown - MozCon
thekraken
41
2.6k
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
150
Transcript
%SPJE,BJHJ )5514ͷجຊ͔Β /FUXPSL4FDVSJUZ$POpH·Ͱ ೋ֊ಊ ว (Amane Nikaido) @a2kaido
ࣗݾհ • ௨৴͕͖Ͱ͢ • conbu͞Μͷ͓ख͍Λ ͠·ͨ͠
ຊηογϣϯͷத • HTTPS௨৴ͷׂͱΈ • NetworkSecurityConfigʹ͍ͭͯ • NΑΓલͷPinning Certificates • Pinning
Certificatesͷӡ༻
എܠ • ެऺແઢLANʹଓ͢Δػձͷ૿Ճ • ௨৴༰ͷ౪ௌվ᜵ͷՄೳੑ͕͋Δ
2014 SSLূ໌ॻݕূͷҙשى
2016 HTTPSͷεεϝ • Protecting against unintentional regressions to cleartext traffic
in your Android apps https://android-developers.googleblog.com/2016/04/protecting-against-unintentional.html • Mythbusting HTTPS: Squashing security’s urban legends - Google I/O 2016 https://www.youtube.com/watch?v=YMfW1bfyGSY
2017 Android Developers Blog • 2018/11·ͰʹTarget API levelΛ26Ҏ্ʹ ͠·͠ΐ͏ •
Android N͔ΒϢʔβʔ͕Πϯετʔϧ ͨ͠ϧʔτূ໌ॻΛ৴པ͠ͳ͍Α͏ʹ https://android-developers.googleblog.com/2017/12/improving-app-security-and- performance.html
https://goo.gl/n4Aahh
Androidͷ Ξοϓσʔτ
Android M • usesCleartextTraffic • ฏจͰͷ௨৴Λېࢭ͢Δઃఆ <application … android:usesCleartextTraffic=“false”>
… </application>
Android N • Ϣʔβ͕Πϯετʔϧͨ͠ϧʔτূ໌ॻ Λ৴པ͠ͳ͍ • NetworkSecurityConfig • ฏจͰͷ௨৴ͷࢭ •
CAͷΞϯΧʔ • Pinning Certificates(ϐϯཹΊ)
ͦͦHTTPSͱ
҉߸Խ௨৴ͷࡾཁૉ • ػີੑ • ϝοηʔδશੑ • ΤϯυϙΠϯτਅਖ਼ੑ
҉߸Խ௨৴ͷࡾཁૉ • ػີੑ • ϝοηʔδશੑ • ΤϯυϙΠϯτਅਖ਼ੑ ҉߸Խ͞Ε͍ͯͯ ౪ௌ͞Εͳ͍͜ͱ
҉߸Խ௨৴ͷࡾཁૉ • ػີੑ • ϝοηʔδશੑ • ΤϯυϙΠϯτਅਖ਼ੑ վ͟Μ͕ͳ͘ શͰ͋Δ͜ͱ
҉߸Խ௨৴ͷࡾཁૉ • ػີੑ • ϝοηʔδશੑ • ΤϯυϙΠϯτਅਖ਼ੑ ਖ਼͍͠௨৴ઌͱ ௨৴͍ͯ͠Δ͜ͱ
҉߸Խ௨৴ͷࡾཁૉ • ػີੑ • ϝοηʔδશੑ • ΤϯυϙΠϯτਅਖ਼ੑ HTTPSͰ҆શੑ͕୲อ͞Ε͍ͯΔͣͰʁ
HTTPS௨৴Λ͢ΔͨΊͷ ূ໌ॻͷ
Client Server
Client Server ΄Μͱʹਖ਼͍͠௨৴૬खͳͷ͔ͳʁ
Client Server ΄Μͱʹਖ਼͍͠௨৴૬खͳͷ͔ͳʁ Certification Authority(ೝূہ)
Client Server Certification Authority(ೝূہ) ϧʔτূ໌ॻ
Client Server Certification Authority(ೝূہ) ϧʔτূ໌ॻ ॺ໊͖ SSLূ໌ॻൃߦ
Client Server Certification Authority(ೝূہ) ϧʔτূ໌ॻ ॺ໊͖ SSLূ໌ॻൃߦ SSLূ໌ॻ
Client Server Certification Authority(ೝূہ) ϧʔτূ໌ॻ ॺ໊͖ SSLূ໌ॻൃߦ SSLূ໌ॻ CAͷॺ໊͕͋Δ͔Β ؒҧ͍ͳ͍
HTTPS௨৴ͷ ϋϯυγΣΠΫ
HTTPS௨৴ͷྲྀΕ 1/4 ClientHello Client Server
HTTPS௨৴ͷྲྀΕ 2/4 ClientHello Client Server ServerHello Certificate
HTTPS௨৴ͷྲྀΕ 2/4 ClientHello Client Server ServerHello Certificate ূ໌ॻΛνΣοΫ ৴པ͢ΔCAͷॺ໊͕͋Δ͔
HTTPS௨৴ͷྲྀΕ 3/4 ClientHello Client Server ServerHello Certificate Finish Finish
HTTPS௨৴ͷྲྀΕ 4/4 ClientHello Client Server ServerHello Certificate Finish Finish HTTPS
தؒऀ߈ܸ Client Server
தؒऀ߈ܸ ClientHello Client Server ClientHello ਖ਼͍͠ূ໌ॻ
தؒऀ߈ܸ ClientHello Client Server ClientHello ਖ਼͍͠ূ໌ॻ ূ໌ॻΛࠩ͠ସ͑
தؒऀ߈ܸ ClientHello Client Server ClientHello ਖ਼͍͠ূ໌ॻ ِͷূ໌ॻ
தؒऀ߈ܸ ClientHello Client Server ClientHello ਖ਼͍͠ূ໌ॻ ِͷূ໌ॻ Finish Finish Finish
Finish HTTPS HTTPS
தؒऀ߈ܸ ClientHello Client Server ClientHello ਖ਼͍͠ূ໌ॻ ِͷূ໌ॻ Finish Finish Finish
Finish HTTPS HTTPS ͜͜Ͱূ໌ॻͷݕূΛ ͍ͯ͠ΔͷͰʁ
ِͷূ໌ॻΛ৴པʁ • ߈ܸऀΛCAͱͯ͠৴པ͍ͯ͠Δ (ϧʔτূ໌ॻΛΠϯετʔϧ͍ͯ͠Δ) Մೳੑ • ߈ܸऀ͕CA͔Βॺ໊͖ূ໌ॻΛ औಘͨ͠Մೳੑ
ِͷূ໌ॻΛ৴པʁ • ߈ܸऀΛCAͱͯ͠৴པ͍ͯ͠Δ (ϧʔτূ໌ॻΛΠϯετʔϧ͍ͯ͠Δ) Մೳੑ • ߈ܸऀ͕CA͔Βॺ໊͖ূ໌ॻΛ औಘͨ͠Մೳੑ ৴པ͢ΔCAΛ੍ݶ͢Ε͛Δ
ِͷূ໌ॻΛ৴པʁ • ߈ܸऀΛCAͱͯ͠৴པ͍ͯ͠Δ (ϧʔτূ໌ॻΛΠϯετʔϧ͍ͯ͠Δ) Մೳੑ • ߈ܸऀ͕CA͔Βॺ໊͖ূ໌ॻΛ औಘͨ͠Մೳੑ αʔό͕ฦ٫͢Δਖ਼͍͠ূ໌ॻΛ ͋Β͔͡Ί͍ͬͯΕ͛Δ
Android N • Ϣʔβ͕Πϯετʔϧͨ͠ϧʔτূ໌ॻ Λ৴པ͠ͳ͍ • NetworkSecurityConfig • ฏจͰͷ௨৴ͷࢭ •
CAͷΞϯΧʔ • Pinning Certificates(ϐϯཹΊ)
NetworkSecurityConfig (Android NҎ߱)
NetworkSecurityConfig • ฏจͰͷ௨৴ͷࢭ • CAͷΞϯΧʔ • Pinning Certificates(ϐϯཹΊ)
ઃఆํ๏ • res/xml/network_security_config.xml • ઃఆ༰Λهड़ • AndroidManifest.xml <application …
android:networkSecurityConfig="@xml/network_security_config"> … </application>
ฏจͰͷ௨৴ͷࢭ <network-security-config> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> </domain-config> </network-security-config>
CAͷΞϯΧʔ <network-security-config> <domain-config> <domain includeSubdomains="true">secure.example.com</domain> <domain includeSubdomains="true">cdn.example.com</domain> <trust-anchors> <certificates src="@raw/trusted_roots"/>
</trust-anchors> </domain-config> </network-security-config>
Pinning Certificates (ϐϯཹΊ) <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <pin-set expiration="2018-01-01"> <pin
digest=“SHA-256”>{ hash value }</pin> <!-- backup pin --> <pin digest=“SHA-256”>{ hash value }</pin> </pin-set> </domain-config> </network-security-config>
Pinning Certificates <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <pin-set expiration="2018-01-01"> <pin digest=“SHA-256”>{
hash value }</pin> <!-- backup pin --> <pin digest=“SHA-256”>{ hash value }</pin> </pin-set> </domain-config> </network-security-config> PinningͷظݶΛઃఆՄೳ ͷγεςϜ࣌ؒͱͷൺֱ
Pinning Certificates <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <pin-set expiration="2018-01-01"> <pin digest=“SHA-256”>{
hash value }</pin> <!-- backup pin --> <pin digest=“SHA-256”>{ hash value }</pin> </pin-set> </domain-config> </network-security-config> αʔόʔͷSSLূ໌ॻͷϋογϡΛઃఆ
Pinning Certificates <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <pin-set expiration="2018-01-01"> <pin digest=“SHA-256”>{
hash value }</pin> <!-- backup pin --> <pin digest=“SHA-256”>{ hash value }</pin> </pin-set> </domain-config> </network-security-config> base64 encoded digest of X.509 SubjectPublicKeyInfo (SPKI)
digestͷ࡞Γํ (खݩͷূ໌ॻͰ) ιʔε: https://github.com/datatheorem/TrustKit/blob/master/ get_pin_from_certificate.py $ python get_pin_from_certificate.py ca.pem
digestͷ࡞Γํ (αʔόʔ͔Β) $ openssl s_client \ -connect <hostname>:<port> \ |
openssl x509 -pubkey -noout \ | openssl rsa -pubin -outform der \ | openssl dgst -sha256 -binary \ | openssl enc -base64
NetworkSecurityConfig ͷιʔείʔυͷ༠͍
ؾ࣋ͪ • ͳʹ͔͋ͬͨ࣌ʹௐ͍ࠪ͢͠ • ؾʹͳΔڍಈΛ֬ೝͰ͖ΔΑ͏ʹͳΔ
ؔ࿈Ϋϥε • ManifestConfigSourceΫϥε • ઃఆͷಡΈࠐΈ • XmlConfigSourceΫϥε • network_security_config.xmlΛύʔε
ؔ࿈Ϋϥε • NetworkSecurityConfigΫϥε • XmlConfigSourceͰΠϯελϯεԽ͞ΕΔ • NetworkSecurityTrustManagerΫϥε • ূ໌ॻνΣοΫͱPinningνΣοΫΛ࣮ࢪ •
ূ໌ॻνΣοΫ࣮ॲཧdelegateͷ TrustManagerImplʹͤΔ
ؔ࿈Ϋϥε • TrustManagerImplΫϥε • ূ໌ॻνΣοΫͷ࣮ • https://github.com/google/conscrypt/blob/master/platform/ src/main/java/org/conscrypt/TrustManagerImpl.java • ߹ΘͤͯಡΉͱྑ͍
https://developer.android.com/training/ articles/security-ssl.html
Pinning Certificates <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <pin-set expiration="2018-01-01"> <pin digest=“SHA-256”>{
hash value }</pin> <!-- backup pin --> <pin digest=“SHA-256”>{ hash value }</pin> </pin-set> </domain-config> </network-security-config> PinningͷظݶΛઃఆՄೳ ͷγεςϜ࣌ؒͱͷൺֱ ࠶ ׃
NetworkSecurityTrustManager private void checkPins(List<X509Certificate> chain) throws CertificateException { PinSet pinSet
= mNetworkSecurityConfig.getPins(); if (pinSet.pins.isEmpty() || System.currentTimeMillis() > pinSet.expirationTime || !isPinningEnforced(chain)) { return; } … } PinningͷظݶΛઃఆՄೳ ͷγεςϜ࣌ؒͱͷൺֱ
ҙ • ʮશͯཧղͨ͠ʯͱ͍ͬͯࣗͰ ࣮͠ͳ͍͜ͱ
Android NΑΓલͰ Pinning Certificates͢Δ
Pinning Certificates (ϐϯཹΊ) ɹ TrustKit-AndroidΛར༻ ɹ OkHttpClientͷcertificatePinnerΛར༻
Pinning Certificates (ϐϯཹΊ) → TrustKit-AndroidΛར༻ ɹ OkHttpClientͷcertificatePinnerΛར༻
TrustKit-AndroidΛར༻ • API 15+ • MIT License • NetworkSecurityConfigͷઃఆΛ ಡΈࠐΜͰূ໌ॻͷݕূΛ͢Δ
TrustKit-AndroidΛར༻ TrustKit.initializeWithNetworkSecurityConfiguration(this); URL url = new URL("https://www.datatheorem.com"); String serverHostname =
url.getHost(); // HttpsUrlConnection HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setSSLSocketFactory( TrustKit.getInstance().getSSLSocketFactory(serverHostname) ); // OkHttp 3.3.x and higher OkHttpClient client = new OkHttpClient().newBuilder() .sslSocketFactory( TrustKit.getInstance().getSSLSocketFactory(serverHostname), TrustKit.getInstance().getTrustManager(serverHostname) ) .build(); }
TrustKit-AndroidΛར༻ TrustKit.initializeWithNetworkSecurityConfiguration(this); URL url = new URL("https://www.datatheorem.com"); String serverHostname =
url.getHost(); // HttpsUrlConnection HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setSSLSocketFactory( TrustKit.getInstance().getSSLSocketFactory(serverHostname) ); // OkHttp 3.3.x and higher OkHttpClient client = new OkHttpClient().newBuilder() .sslSocketFactory( TrustKit.getInstance().getSSLSocketFactory(serverHostname), TrustKit.getInstance().getTrustManager(serverHostname) ) .build(); }
TrustKit-AndroidΛར༻ TrustKit.initializeWithNetworkSecurityConfiguration(this); URL url = new URL("https://www.datatheorem.com"); String serverHostname =
url.getHost(); // HttpsUrlConnection HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setSSLSocketFactory( TrustKit.getInstance().getSSLSocketFactory(serverHostname) ); // OkHttp 3.3.x and higher OkHttpClient client = new OkHttpClient().newBuilder() .sslSocketFactory( TrustKit.getInstance().getSSLSocketFactory(serverHostname), TrustKit.getInstance().getTrustManager(serverHostname) ) .build(); }
Pinning Certificates ɹ TrustKit-AndroidΛར༻ → OkHttpClientͷcertificatePinnerΛར༻
OkHttpClientͷcertificatePinnerΛར༻ public void run() throws Exception { OkHttpClient client =
new OkHttpClient.Builder() .certificatePinner(new CertificatePinner.Builder() .add("publicobject.com", “sha256/{ hash value }”) .build()) .build(); Request request = new Request.Builder() .url("https://publicobject.com/robots.txt") .build(); Response response = client.newCall(request).execute(); }
OkHttpClientͷcertificatePinnerΛར༻ public void run() throws Exception { OkHttpClient client =
new OkHttpClient.Builder() .certificatePinner(new CertificatePinner.Builder() .add("publicobject.com", “sha256/{ hash value }”) .build()) .build(); Request request = new Request.Builder() .url("https://publicobject.com/robots.txt") .build(); Response response = client.newCall(request).execute(); } PinningͷظݶΛઃఆෆՄ
Pinning Certificatesͷ ӡ༻
ӡ༻࣌ͷϙΠϯτ • αʔόʔαΠυͱͷௐ • SSLূ໌ॻΛม͑ΒΕΔͱ௨৴Ͱ͖ͳ͘ͳΔ • SSLূ໌ॻߋ৽࣌ͷϧʔϧ੍ఆ • Pinning CerficatesͷexpireઃఆͳͲ
ཧతͳӡ༻ Server ূ໌ॻAظݶ ূ໌ॻAϐϯཹΊ + expireઃఆͳ͠ Client
ཧతͳӡ༻ Server ূ໌ॻAظݶ Client ূ໌ॻBൃߦ ূ໌ॻAϐϯཹΊ + expireઃఆͳ͠
ཧతͳӡ༻ Server ূ໌ॻAظݶ Client ূ໌ॻBൃߦ ূ໌ॻA + BϐϯཹΊͷΞϓϦϦϦʔε ڧ੍Ξοϓσʔτ ূ໌ॻAϐϯཹΊ
+ expireઃఆͳ͠
ཧతͳӡ༻ Server ূ໌ॻAظݶ Client ূ໌ॻBൃߦ ূ໌ॻBʹΓସ͑ ূ໌ॻA + BϐϯཹΊͷΞϓϦϦϦʔε ڧ੍Ξοϓσʔτ
ূ໌ॻAϐϯཹΊ + expireઃఆͳ͠
ཧతͳӡ༻ͷؾ࣋ͪ • ৗʹPinning Certificates͕༗ޮ • ূ໌ॻͷೖΕସ͑ͷλΠϛϯάͰ༗ޮ • expireͷઃఆΛ͍Ε͍ͯͳ͍ͷͰ γεςϜ͕࣌ؒͣΕ͍ͯͯ༗ޮ
ཧతͳӡ༻ͷؾ࣋ͪ • ৗʹPinning Certificates͕༗ޮ • ূ໌ॻͷೖΕସ͑ͷλΠϛϯάͰ༗ޮ • expireͷઃఆΛ͍Ε͍ͯͳ͍ͷͰ γεςϜ͕࣌ؒͣΕ͍ͯͯ༗ޮ ⚠
ΞϓϦͷߋ৽ΛΕΔͱ௨৴Ͱ͖ͳ͘ͳΔ ⚠ ڧ੍Ξοϓσʔτ͕ඞཁ
expireઃఆʹΑΔଥڠҊ Server ূ໌ॻAظݶ Client ূ໌ॻAϐϯཹΊظݶ
expireઃఆʹΑΔଥڠҊ Server ূ໌ॻAظݶ Client ূ໌ॻAϐϯཹΊظݶ ূ໌ॻBൃߦ
expireઃఆʹΑΔଥڠҊ Server ূ໌ॻAظݶ Client ূ໌ॻAϐϯཹΊظݶ ূ໌ॻBൃߦ ূ໌ॻBʹΓସ͑
expireઃఆʹΑΔଥڠҊ Server ূ໌ॻAظݶ Client ূ໌ॻAϐϯཹΊظݶ ূ໌ॻBൃߦ ূ໌ॻBʹΓସ͑ ূ໌ॻBϐϯཹΊ൛ϦϦʔε
ଥڠҊͷؾ࣋ͪ • ΞϓϦͷߋ৽ΛΕͯ௨৴Ͱ͖Δ • ڧ੍Ξοϓσʔτ͕ඞཁͳ͍ • ূ໌ॻΓସ͑࣌ʹPinning͕ޮ͔ͳ͍ ࣌ظ͕͋Δ
·ͱΊ
·ͱΊ • HTTPΊ·͠ΐ͏ • NetworkSecurityConfigʹΑͬͯɺѱҙ ͷ͋Δ߈ܸऀ͔ΒϢʔβʔΛकΔઃఆ͕ ؆୯ʹͰ͖ΔΑ͏ʹͳΓ·ͨ͠ • ӡ༻࣌ؾΛ͚ͭ·͠ΐ͏
͝੩ௌ͋Γ͕ͱ͏ ͍͟͝·ͨ͠
Appendix • GMailͷϝοηʔδݟΒΕͨ https://www.computerworld.com/article/2510951/cybercrime-hacking/ hackers-spied-on-300-000-iranians-using-fake-google-certificate.html • ෆਖ਼ͳূ໌ॻ͕ൃߦ͞Εͨ http://www.atmarkit.co.jp/news/201109/08/diginotar.html