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
グローバルチームと挑むプロダクト開発
sansantech
PRO
1
170
プライバシー保護の理論と実践
lycorptech_jp
PRO
1
250
ポストモーテム! DDoSからサイトは守れた。 でもビジネスは守れなかった。
bengo4com
0
2.1k
FinOps X 2026 Recap from Engineer Side #JapanFinOps
chacco38
0
270
次世代ランサムウェア対策の考察 / 20260704 Mitsutoshi Matsuo
shift_evolve
PRO
5
1.7k
Empower GenAI with Agile - あなたのアジャイルが生成AIのバフになる仕組み
hageyahhoo
1
150
Keeping applications secure by evolving OAuth 2.0 and OpenID Connect
ahus1
PRO
1
150
ローカルLLMとLINE Botの組み合わせ その3 / LINE DC Generative AI Meetup #8
you
PRO
0
130
Terraform共通モジュールをチーム横断で“変えられる”運用へ ― リリースと適用の分離
kekke_n
1
2.1k
SRE歴2ヶ月でも開発6年の知見を活かして、チームで止まっていた環境改善を前に進めた話
a_ono
1
220
AI駆動開発におけるQAエンジニアの役割事例 〜AI駆動開発の現場から〜
kobayashiyorimitsu
0
420
勉強会企画をアプリで構造化してみた 〜そこで見えた、AIとの付き合い方〜 / I've structured a study group plan using an app.
pauli
0
330
Featured
See All Featured
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
201
75k
Building the Perfect Custom Keyboard
takai
2
810
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
420
Navigating Weather and Climate Data
rabernat
0
280
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
650
Designing Experiences People Love
moore
143
24k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
Optimising Largest Contentful Paint
csswizardry
37
3.8k
Visualization
eitanlees
152
17k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
240
Joys of Absence: A Defence of Solitary Play
codingconduct
1
410
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