tls, http/2演習
Post on 12-Apr-2017
4.262 Views
Preview:
TRANSCRIPT
自己紹介• 大津 繁樹
• 株式会社インターネットイニシアティブ(IIJ)
• Node.js Core Technical Committee メンバー
• IETF httpbis WGでHTTP/2相互接続試験など使用策定に参画
• ブログ: http://d.hatena.ne.jp/jovi0608/
本講義・演習の目的• 2日間の講義・演習を通じてTLS, HTTP/2の仕組みを学んで頂きます。
• 演習は、できるだけプログラミングを行う要素をなくし、Wireshark、Linux上のコマンドやファイル編集で収まるようにしています。
• TLS, HTTP/2ともに幅広く深い技術です。2日間で完全に理解するのは難しいでしょう。でも基本的な部分をおさえて将来の理解に役立ててください。
本講義・演習の内容(TLS)• 講義:TLS概要
• 講義:TLSを理解する準備(暗号技術など)
• 講義:事前学習解説(サーバ証明書取得までのPKIの仕組み)
• 講義:TLSの仕組みの理解 (Wiresharkの画面を見つつ)
• 演習:nginxでTLSサーバを構築
• 演習:SSLLabでA+を目指す
• 演習:RSA鍵を解読してTLSを破る(FREAK攻撃)
本講義・演習の内容(HTTP/2)
• 講義: HTTP/2が必要になった背景
• 講義: HTTP/2の仕組み解説
• 演習: nginxサーバをHTTP/2対応に
• 講義・演習: HTTP/2のTLS制限について
• 演習:HTTP/2によるHTTP Head of Blockingの解消
TLSの目的
• TLSプロトコルの最重要なゴールは、通信する2つのアプリケーションの間でプライバシーとデータの完全性を提供することです。
RFC5246: The Transport Layer Security (TLS) Protocol Version 1.2
1. Introduction The primary goal of the TLS protocol is to provide privacy and data integrity between two communicating applications.
アプリ アプリ
完全性
プライバシー
TLSの簡単な歴史
• SSL 1.0未発表
• 1994年 SSL 2.0
• 1995年 SSL 3.0
• 1996年 IETF TLS WGスタート
• 1999年 TLS 1.0
• 2006年 TLS 1.1
• 2008年 TLS 1.2
• 2013年 TLS 1.3検討スタート
SSLは、旧ネットスケープ社の私的プロトコル
TLSと名前を変えて標準化
SSL3.0と基本設計は大きく変えず、内部バージョンは TLS1.0 =SSL 3.1
現在の利用推奨
様々な拡張仕様の追加
TLSの要素技術
X509証明書
PKI
対称 暗号
暗号モード
公開鍵暗号
デジタル署名
メッセージ認証
乱数 生成
TLS鍵交換
一方向ハッシュ
TLSプロトコルは、これらの要素技術を組み合わせてアプリ間のセキュア通信を確立する手順を決める
TLS要素技術はどこで使われる?
ClientHello
ServerHelloDone
ChangeCipherSpec Finished
ChangeCipherSpec Finished
Application Data
Application Data
乱数生成
対称暗号・暗号モード・一方向ハッシュ・乱数生成
PKI・X509証明書・デジタル署名
乱数生成
ServerHello
Certificate
ClientKeyExchange
ServerKeyExchange(*)
乱数生成・鍵交換・ 公開鍵暗号・デジタル署名
メッセージ認証 対称暗号・暗号モード
メッセージ認証 対称暗号・暗号モード
乱数生成・鍵交換 デジタル署名
(* オプションで必須ではない)
TLS要素技術はどこで使われる?
乱数生成 Client/ServerHelloのNonce, 鍵ペアの生成 データ暗号化のIV
PKI CAによるサーバ証明書の署名と発行
X509証明書 Certificateによるサーバ・クライアントの認証・公開鍵の取得
電子署名 証明書の署名・鍵交換で交換する公開鍵の署名
鍵交換 Server/ClientKeyExchangeによる(EC)DH公開鍵の交換
公開鍵暗号 RSA鍵交換時にPreMasterSecretの暗号送信
一方向ハッシュ CBCなどの暗号モード利用時にアプリデータのMAC生成
メッセージ認証 MasterSecretの生成、Finishedによるハンドシェイクデータの完全性検証
対称暗号・暗号モード ChangeCipherSpec以降のハンドシェイクとアプリケーションデータの暗号化
(注:他にも細かいところで使われています。)
今回使うTLS要素技術
GCM AES
DHE ECDHE RSA
SHA256
HMAC
X509証明書
PKI
対称 暗号
暗号モード
公開鍵暗号
デジタル署名 メッセージ認証
乱数 生成
鍵交換 一方向ハッシュ
WoSign Free DV Cert
手入力??
セットメニュー化されたTLSの要素技術TLS CipherSuites
TLS_RSA_WITH_AES_128_GCM_SHA256 = {0x00,0x9C}
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256= {0xC0,0x2F};
対称 暗号
暗号モード
デジタル署名
メッセージ認証(ハッシュ)
鍵交換TLS _ _ _WITH_ _ 鍵長 _ _
鍵交換・デジタル署名にRSA
対称暗号に128bit鍵長のAES
暗号モードにGCM
ハッシュにSHA256
鍵交換にECDHE
デジタル署名にRSA
対称暗号に128bit鍵長のAES
暗号モードにGCM
ハッシュにSHA256
番号として 0xC0,0x2Fを割り当て
対称暗号暗号文平文
共通鍵 共通鍵
平文
ストリーム暗号:データを逐次暗号化(RC4, Chacha20)
ブロック暗号:データをブロック毎に暗号化(DES, AES)
幾つかの暗号では既に危殆化: DES: 2005年 NIST FPS46-3規格の廃止(2030年までは許容)
RC4: RFC7455: Prohibiting RC4 Cipher Suites
暗号化 復号化
対称暗号 AES• 1997年よりプロジェクト開始、2000年選定、2001年仕様発行
• ブロックサイズ 128bit
• 鍵長: 128bits, 192bits, 256bits の3種類
• Intel/AMDのCPUでハードウェア処理のサポート (AES-NI)
暗号モード• ブロック暗号は同じデータを同じ鍵で暗号化すると毎回同一の暗号文になる。
• ブロック長より長いデータを暗号化する場合に暗号モードを利用して繰り返しを避ける。
• CBC:「(平文 XOR ベクトル) を暗号化」を続ける
• CTR: 「カウンターを暗号化 XOR 平文」を続ける実際にTLSで利用するには改ざん検知のためのMAC(メッセージ認証)との組み合わせる(AEAD)。
これまでの主流
これからの主流に(GCM後述)
認証タグ
AEAD(認証付き暗号)暗号化しないけど改ざん• • • • • • • • • • •
防止が必要なデータ • • • • • • • • •
(ヘッダ等)• • • •
暗号化する平文
AEAD 暗号化
暗号文
共通鍵
初期ベクトル
GCM• GCM (Galois Counter Mode: ガロアカウンターモード)
• CTRとGHASHを組み合わせたAEAD
• ハードウェア処理で高速化が可能
• AESと組み合わせて AES-GCMとして利用
一方向ハッシュ
• md5 • SHA-1 • SHA-2(SHA-256など6種)
• SHA-3(SHA3-256など6種)
2018年ぐらいには現実的なコストで衝突データを探せる見込み(*2)
既に現実的な攻撃手法が存在
(*2) Cryptanalysis of SHA-1 https://www.schneier.com/blog/archives/2005/02/cryptanalysis_o.html
(*1) how to Break MD5 and Other Hash Functions http://merlot.usc.edu/csac-f06/papers/Wang05a.pdf
8/5にNISTより正式公開
公開鍵暗号
512bit RSAの危険性 FREAK https://freakattack.com/
• 解を求めるのが困難な数学的問題を利用して暗号を生成。
• 公開鍵と秘密鍵のペアを生成。公開鍵はさらして大丈夫。
• 公開鍵で暗号化し秘密鍵で復号化。
• RSA 素因数分解
• ECC(楕円曲線暗号)楕円曲線上の離散対数問題
公開鍵 秘密鍵暗号化 復号化
鍵交換
• 2者間で安全に鍵を共有する仕組み
• 互いに公開鍵を交換しあい、共有鍵を生成する。
• 通信経路上で共有鍵のやり取りがない。
• DH (Diffie-Hellman) • ECDH(楕円曲線DH)脆弱性:DH Logjam https://weakdh.org/
公開鍵公開鍵 秘密鍵秘密鍵
デジタル署名
• データの完全性のチェックが可能となる。
• データの送信元の認証が可能となる。
• 公開鍵の信頼性の範囲で否認防止が可能となる。
• RSA • DSA,ECDSA
公開鍵秘密鍵 データ+デジタル署名
データハッシュ値を暗号化しデジタル署名を生成
デジタル署名を復号化。データハッシュ値と比較し検証する
事前課題の解説・復習演習で利用するTLSサーバ証明書(DV)を取得するまでの一連の手続きを行う
1.乱数データの生成
2.秘密鍵(RSA)の生成・確認・保護
3.CSRの生成・確認・提出
4.CAに申請・サーバ証明書発行
5.サーバ証明書の取得・確認https://gist.github.com/shigeki/102cd71b34627c5bf330
openssl genrsa, openssl rsa
openssl req
openssl x509
乱数生成利用用途: • 暗号鍵(対称暗号:秘密鍵、公開鍵暗号:鍵ペア)の生成
• 暗号モードの初期ベクトルやNonce(*)の生成
• MAC(メッセージ認証)用鍵
求められる機能:
無作為性: 偏りがなく等しい数である。
予測不可能性: 次の乱数が予想できない。
制限負可能性: 同じ乱数列を再現できない。
(* Nonce(number used once)一度だけ使い捨て用に使われる数字)
乱数生成• 実際の利用は、疑似乱数生成。seedが必要。
• OppenSSLのdefault built-inでは、seedはLinuxの/dev/urandom+pid+uid+timeを利用。WindowsではOSのAPIのCryptGenRandomだけでなく画面スクリーンのビットマップハッシュやヒープメモリも利用。
脆弱性:
• CVE-2008-0166: DebianやUbuntuのOpenSSLに予測可能な乱数を生成してしまう脆弱性
• SSH公開鍵にブルートフォース攻撃
Linuxのエントロピー• /dev/urandom
• ブロックしない
• 外部デバイス(キーボードやディスクなど)の割り込みをエントロピーソースにして溜める。加工したデータのハッシュ値を取る。
• エントロピーが十分溜まっているかが重要(特にインストール直後)
• /proc/sys/kernel/random/entropy_avail で値を確認できる。(Max 4k) 1k以下だったらエントロピーの追加を検討。
• findなどでDisk I/Oを人為的に増やしたり、rng-tools, Virtio_RNG, Haveged 等ツールを使う
演習1.1: エントロピーの確認• サーバに入り、プールしているエントロピーを確認します。
• cat /proc/sys/kernel/random/entropy_avail
• Disk I/Oを発生させます。
• find / > /dev/null
• エントロピーが変わったかどうか確認します。
• /dev/urandom からデータを読み込みます。その後エントロピープールが減ったことを確認します。
• head -10 /dev/urandom > /dev/null
事前学習の復習• 事前学習で作成したファイルの中身を見てみる
秘密鍵
$ openssl rsa -text -in private.key -noout
CSR
$ openssl req -text -in server.csr -noout
サーバ証明書
$ openssl x509 -text -in server.crt -noout
ASN.1, DER, PEM
PEM: DER形式をBase64に変換してBEGINヘッダ~ENDフッタをつけたテキスト
ASN.1: データ構造を表す書式
DER: ASN.1のデータ構造をタグ+長さ+データでエンコードしたバイナリ
秘密鍵(RSA)• 公開鍵暗号やデジタル署名で利用する鍵データ。実際は公開鍵と秘密鍵の鍵ペアを生成している。
• TLS通信のセキュリティを確保する要の一つ。厳重に管理。
• 秘密鍵が漏洩するなど危殆化するとTLS通信のセキュリティは確保できなくなる。
• PKCS#1(RFC3447)で規定
• 秘密鍵は暗号化してPKCS#5形式で保管する、パスワードで復号化。
RSA秘密鍵の中身Private-Key: (2048 bit)
modulus:
publicExponent:
privateExponent:
prime1:
prime2:
exponent1:
exponent2:
coefficient:
鍵長N=PxQ (素数P,Qの積)公開値
E 暗号化する指数 通常2^16+1 公開値D=1/E mod((P-1)(Q-1)) 復号化する指数 秘密値
素数P 秘密値
素数Q 秘密値
中国剰余定理で計算するための値 秘密値 D, P, Qから計算できる
CSR• Certificate Signing Request(証明書署名要求)
• PKCS#10(RFC2986)で規定
• サーバ証明書の識別子(サーバ名など)と公開鍵を含んだもの。CA(認証局)にCSRを申請してサーバ証明書を発行してもらう。
CSRの中身• Version: バージョン 0x0
• Subject: 証明書を発行してもらうサーバの識別名
Subject: C=JP, ST=Hokkaido, O=Security Camp, CN=server21.hokkaido.koulayer.com
• 公開鍵:アルゴリズムや公開鍵のデータ
• 署名:上記データの署名
CN: Common Name サーバ名が入る
PKI概要CA
(Certificate Authority) VA (Validation Authority)RA
(Registration Authority)
CRL/OCSP
CSR
鍵ペア
実在確認サーバ証明書
https://~
失効確認
論理的に複数の役割に分かれているが物理的に1つでもよい
Root証明書
OS・ブラウザベンダー
サーバ証明書(X509)• TLS通信の信頼性を担保する要
• ビルトインのルート証明書からサーバ証明書まで証明書チェーンの署名検証
• オンライン以外で信頼性を担保(PKI)
ビルトインの ルート証明書
サーバ証明書
中間証明書
ビルトインの ルート証明書
サーバ証明書
中間証明書
トラストアンカー
証明書の種類EV証明書(Extended Validation)
CA共通の厳格な組織の実在証明 (物理的実在, 書面やデータ, 口座取引による実在審査・署名提出・電話確認など)
アドレスバーが緑色
OV証明書(Organization Validation)
各CAポリシー(CPS)に従った組織の実在証明 (書面やデータ審査・電話確認など)
DV証明書(Domain Validation)
各CAポリシー(CPS)に従ったドメイン保持証明 (メールの到達性確認など)
今回利用
ネットワーク以外の実在証明
サーバ証明書の確認サーバ証明書と秘密鍵の対応が間違っていたらTLSサーバは起動しない。なのでサーバ証明書と秘密鍵の公開鍵が一致するか必ずチェックする。
サーバ証明書
秘密鍵
openssl x509 -pubkey -inserver.crt -noout > server_pubkey.pem
openssl rsa -pubout -in private.key -out private_pubkey.pem
公開鍵
公開鍵
TLSのセキュリティ
TLSの セキュリティ
乱数生成
PKI秘密鍵の管理
暗号技術
エントロピー不足
不正発行
漏洩
アルゴリズム・強度の危殆化
TLSは、この4つの外部要素の上でインターネットで安全な通信を提供する仕組みである。
演習1.2https://html5.ohtsu.org/seccamp_hokkaido_2015/exam.pcapから pcap データをダウンロードして Wiresharkで開く
Wiresharkのデータを見比べながらTLSハンドシェイクを解説します。
TLSハンドシェイク(full handshake)
ClientHelloServerHello Certificate ServerHelloDone
ClientKeyExchange ChangeCipherSpec Finished
ChangeCipherSpec Finished
Application Data
Application Data
(赤文字はハンドシェイク)
ClientHelloとServerHelloのやり取りで双方が利用するTLSバージョンや暗号化方式などを合意する。
TLSハンドシェイク(resumption)
ClientHelloServerHello ChangeCipherSpec Finished
ChangeCipherSpec Finished
Application Data
Application Data
(赤文字はハンドシェイク)
SessionIDによるTLSセッションの再開。 鍵交換や証明書送付をスキップ。
今回は演習の対象外です
TLSハンドシェイクの意味ClientHello/ServerHello/ServerHelloDone
TLSのための情報交換 バージョン・乱数・暗号方式・拡張情報
Certificate 公開鍵情報の送付
エンドポイントの認証
ClientKeyExchange/ServerKeyExchange 共有鍵交換
ChangeCipherSpec 暗号開始の合図
Finished ハンドシェイクデータの改ざんチェック
TLS1.2の構造I P ヘ ッ ダ
T C P ヘッダ
TLS Record Layer (5バイト)
タイプ (4種類)
(1byte)
バージョン (2byte)
長さ (2byte)
Handshake (タイプ:0x16)
msgタイプ (10種類)
長さ
(3バイト長)ハンドシェイクデータ
Alert (タイプ:0x15)
レベル 理由
ChangeCipherSpec (タイプ:0x14)
タイプ
Application Data (タイプ:0x17)
暗号化されたデータ
msgタイプ ハンドシェイクデータの種類
0x00 HelloRequest0x01 ClientHello0x02 ServerHello0x0b Certificate0x0c ServerKeyExchange0x0d CertificateRequest0x0e ServerHelloDone0x0f CertificateVerify0x10 ClientKeyExchange0x14 Finished
TLS Record Layerデータに続いて、次の4種類のTLSデータのいずれかが続く。
TLS Handshakeは、この10種類に分かれる。
ClientHello項目 要素 サイズ 先頭の長さ情
報client_version uint8 major, uint8 minor 2 N/A
random uint32 gmt_unix_time, opaque random_bytes[28]
4 + 28 N/A
session_id opaque SessionID <0..32> 1バイト分cipher_suites uint8 CipherSuite[2] <2..2^16-2> 2バイト分
compression_methods
null(0) <1..2^8-1> 1バイト分
extensions extension_type(65535), extension_data<0..2^16-1>
<0..2^16-1> 2バイト分
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1type デー
タ長データ type デー
タ長データ type デー
タ長データ
Extension長 Extensionsデータ例
ClientHello
Record Layer Handshake (ClientHello)
type protocol version
length (2byte
)
msg type
length (3byte)
client version
random session id
cipher suite
compression
Extension
major
minor
major minor
0x16 0x03 0x01 ?? ?? 0x01 ?? ?? ?? 0x03 0x03 32 byte 可変 可変 可変 可変
Version 0x03,0x00 = SSLv3 0x03,0x01= TLSv1.0 0x03,0x02=TLSv1.1 0x03,0x03=TLSv1.2
クライアントが利用できる最高のTLSバージョンを指定、サーバがどのバージョンを使うか選択する
ServerHello項目 要素 サイズ 先頭の長さ情報
server_version uint8 major, uint8 minor 2 N/A
random uint32 gmt_unix_time, opaque random_bytes[28]
4 + 28 N/A
session_id opaque SessionID <0..32> 1
cipher_suite uint8 CipherSuite[2] 2 N/A
compression_method null(0) 1 N/A
extensions extension_type, extension_data<0..2^16-1>
<0..2^16-1> 2バイト分
Record Layer(5bytes) Handshake (ServerHello)
type protocol version
length (2bytes)
msg type
length (3byte)
server version
random 32bytes
session id cipher suite
2bytes
compression
major
minor major minor
0x16 0x03 0x03 ? + 4 0x01 ? 0x03 0x03 ? 長さ1byte 0x00,0x9c 長さ2bytes
Certificate
項目 要素 サイズcertificate_list ASN.1Cert<2^24-1> <0..2^24-1>
全証明書長 証明書#1長 証明書データ#1 証明書#2長 証明書データ#2
複数の証明書データを送付
最初は必ずサーバ証明書 2つ目以降は中間証明書など
ClientKeyExchange (RSA鍵交換の場合)
Record Layer(5bytes) Handshake(ClientKeyExchange)type protocol
versionlength
(2bytes)msg type
length (3byte)
Encrypted PreMasterSecret
major minor
0x16 0x03 0x03 ? + 4 0x10 ? 長さ2バイト ?
PreMasterSecretclient version random 46bytes
major minor
TLSの鍵生成の流れpre master secret
(任意のバイト数:鍵交換による) サーバ・クライアント間の鍵交換方式で生成し、秘密的に共有する
master secret (48 bytes)
PRF(pre_master_secret, "master secret", client_random+server_random)
keyblock (任意のバイト数:利用暗号方式による)
PRF(master_secret, "key expansion", server_random+client_random)
client_write_MAC server_write_MAC client_write_key server_write_key client_write_IV server_write_IV
PreMasterSecret/MasterSecret
• TLSで利用するIV(初期ベクトル)、共有鍵、MAC鍵のデータ元
• MasterSecretは48バイト長。PreMasterSecretの長さは鍵交換方式に依存する。
• MasterSecretは、PreMasterSecret、ClientRandom、ServerRandom、固定ラベルから生成する。
• Clinet/ServerRandomは全て丸見え。PreMasterSecretは、必ず死守して守らないといけない。これが漏えいするとTLSの安全性は全ておじゃん。
Freak/Logjam
ChangeCipherSpec
送信元が暗号開始を宣言。これを送信した後は暗号通信を行う。
Record Layer ChangeCipherSpec
ContentType
Version length (2byte)major minor
0x14 0x03 0x03 0x00 0x01 0x01
Finishedstruct { opaque verify_data[verify_data_length]; } Finished;
verify_data = PRF(master_secret, finished_label, Hash(handshake_messages))[0..11];
finished_label: クライアントは、"client finished"、サーバは"server finished"
12バイト固定
これまでのハンドシェイクデータ(ただし自分は除く)のハッシュを計算 TLS1.2では SHA256を使う
Finishedを受信すると、これまで送受信したハンドシェイクデータから計算した値と比較。
ハンドシェイクデータが改ざんされてないことを確認する。
Forward Secret
• 前方秘匿性 (PFS: Perfect Forward Secrecyとも書かれることも) • セッション毎に一時的な公開鍵を使う。• 証明書の秘密鍵は、一時的な公開鍵への署名に利用する。 • ハンドシェイクを含む全暗号データを取得されているような状況でも、将来的な証明書の秘密鍵漏洩などのリスクに対応する。
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Ephemeral:一時的な 鍵交換手法
接続ごとに公開鍵を変更する
DHE vs ECDHE• DH: Diffe-Hellman 離散対数問題を利用した鍵交換
((g^x) mod P)^y mod P = ((g^y) mod P)^x mod P = g^(xy) mod P
素数P, ジェネレータ g, 公開鍵(赤字、青字)などの情報を交換。ECDHEより計算量が多い。
• ECDHE: 楕円関数上での離散対数演算を利用した鍵交換
楕円関数のパラメータ・基点を名前で規定(secp256等)、公開鍵(楕円曲線上の点)を交換。DHより鍵長・計算量が少なくてすむ。
DHEのハンドシェイク
ClientHello ServerHello
Certificate ServerKeyExchange ServerHelloDone
ClientKeyExchange ChangeCipherSpec Finished ChangeCipherSpec
FinishedApplication Data
(赤文字が追加変更されるところ)
Clientの公開鍵を送付
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
P,G,サーバ公開鍵を署名して送付
公開鍵は毎回ランダムに生成されます
https://html5.ohtsu.org/seccamp_hokkaido_2015/dhe.pcap
ECDHEのハンドシェイク
ClientHello + elliptic_curves + ec_point_formats
ServerHello + ec_point_formats Certificate ServerKeyExchange ServerHelloDone
ClientKeyExchange ChangeCipherSpec Finished ChangeCipherSpec
FinishedApplication Data
(赤文字が追加変更されるところ)
ClientHello拡張を追加
ServerHello拡張を追加
楕円曲線名とServerの公開鍵を署名付きで送付
Clientの公開鍵を送付
楕円点の書式を合意使える楕円曲線名と楕円点書式を通知
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
公開鍵は毎回ランダムに生成されます
https://html5.ohtsu.org/seccamp_hokkaido_2015/ ecdhe.pcap
演習1.3:nginxの構築
https://gist.github.com/shigeki/b70bd5433e95722b5fa3
演習1.4:SSLLabのテストhttps://www.ssllabs.com/ssltest/index.html
Logjam攻撃• DHE鍵交換に対する攻撃(2015年5月に公開)
• あらかじめ素数Pがわかっていれば従来より離散対数問題を効率的に解けるようになった。
• DHでは標準素数が規定されており幾つかの実装ではそれを利用している。
• 512bit長の標準素数は数十秒で解ける。1024bit長も国家予算並みのお金をかければ解読できる。2048bit長以上の利用を推奨。
演習1.5:DHEの鍵長増加• nginxはデフォルトで1024bitの標準素数でDHEを利用している。
• 2048bit長以上にするにはユーザが独自にDHパラメータ(P,g)を生成し設定する。
$ openssl dhparam -out dhparam.pem 2048$ openssl dhparam -text -in dhparam.pem -noout
dhparamファイルを /usr/local/nginx/conf にコピーし、nginx.confにssl_dhparam dhparam.pem;を追加する。
演習1.6:目指せA+• いくつかスコアを増加させる方法はあるが、HSTSを設定してスコアを上げる。
• HSTS: HTTP Strict Transport Security
• Strict-Transport-Securityヘッダを利用すると指定した時間内はブラウザーが http:// が強制的に https:// へ接続にいく。nginx.conf に追加。
add_header Strict-Transport-Security "max-age=15768000; includeSubdomains";
HSTSの確認一度ブラウザでTLS接続してから chrome://net-internals/#hsts をあける。 Query domain にサーバ名を入力 mode が STRICT になっていれば設定OK
このRSA鍵を破るhttps://html5.ohtsu.org/seccamp_hokkaido_2015/nopfs.hokkaido.koulayer.com_sha256_en.zip
なんか変な素数の積だぞ
PreMasterSecretをゲット!$ cat > encrypted_premaster_secret.txt
0d9909953798f・・・・・721
$ xxd -p -r encrypted_premaster_secret.txt > encrypted_premaster_secret.der
$ openssl rsautl -decrypt -pkcs -inkey private.key -in encrypted_premaster_secret.der -hexdump
0000 - ・・・・・・ ..F.y.....)i,`.0
0010 - ・・・・・・ P......}.?C..c..
0020 - ・・・・・・ .x..Z.p..OK..ep.
テキスト形式でコピーした場合バイナリーに変換してください。
トータル何バイト長でしょうか 頭の2オクテットは何ですか?
3. 上級者向け課題https://html5.ohtsu.org/seccamp_hokkaido_2015/exam.pcap を解析して、PreMasterSecretを入手
MasterSecretを生成し、復号化用鍵を入手 暗号化されたアプリケーションデータを解読してください。 平文文字列が入手できればミッションクリア
http://www.slideshare.net/shigeki_ohtsu/security-camp2015-tlsのp76以降を参照
HTTP/2演習の内容• HTTP/1.1からHTTP/2へ
• HTTP/2の仕組み概要• 演習:HTTP/2サーバを作る
• 演習:HTTP/2プロトコル解析
Ethernet
IP(v4/v6)
TCP
TLS
HTTP/2 Frame Layer
HTTP/1.1 Semantics
HTTPプロトコルの年表1990 1995 2000 2005 2010 2015
Webの 始まり
HTTP/0.9 HTTP/1.0 RFC1945
HTTP/1.1 RFC2068
HTTP/1.1 RFC2616
HTTP/1.1 RFC7230-5
HTTP/2 RFC7540
SPDY/2
SPDY/3
SPDY/3.1
httpbis WG
暗黒の時代
HTTP-NG 中止
HPACK RFC7541
HTTP転送サイズとリクエスト数の遷移(2012/7/1~2015/7/1)
http://httparchive.org/trends.php?s=All&minlabel=Jul+1+2012&maxlabel=Jul+1+2015#bytesTotal&reqTotal
3年で
転送サイズ: 96%増
リクエスト数:20%増
(単一Webサイトの統計平均)
回線帯域を増速していくと
HTTP経由のダウンロード
時間
[ms]
0
800
1600
2400
3200
回線帯域[MBps]
0 3 5 8 10
More Bandwidth does’nt matter よりデータ引用http://docs.google.com/a/chromium.org/viewer?
a=v&pid=sites&srcid=Y2hyb21pdW0ub3JnfGRldnxneDoxMzcyOWI1N2I4YzI3NzE2
ページの表示時間は、これ以上短縮できない。
Make the Web Faster: Google の試験
RTT(Round Trip Time)を小さくしていくと
HTTP経由のダウンロード時間
[ms]
0
1000
2000
3000
4000
RTT[ms]
0 50 100 150 200 250 300
ちゃんと下がる
More Bandwidth does’nt matter よりデータ引用http://docs.google.com/a/chromium.org/viewer?
a=v&pid=sites&srcid=Y2hyb21pdW0ub3JnfGRldnxneDoxMzcyOWI1N2I4YzI3NzE2
Webページの表示速度を速くするには、回線速度増強よりRTT(の影響)を小さくするかが重要。でも物理的な制限で難しい。
Make the Web Faster: Google の試験
SPDY(スピーディ)の登場(2009年)• RTTの影響をできるだけ避けるべくGoogleはSPDYを開発した。
• SPDYは、Webページの表示速度を速くするためのプロトコルとして当初社内プロジェクトから生まれた。
• 既に3年以上に渡りGoogleの全サービスで利用され、TwitterやFacebook、LINEなど大規模なシステムに導入されている。 ブラウザの拡張プラグイ
ン(SPDY Indicator)を使うとSPDYを使っているサイトがわかる
演習: SPDY indicatorのインストール• https://chrome.google.com/webstore/category/extensions から検索・インストール
• HTTP/2サイトにアクセスして確認
• chrome://net-internals/#http2 でHTTP/2の接続状況を確認
HTTP/1.1は非効率なプロトコル
HTTP/1.1+SSLの輻輳ウィンドウサイズの変遷
輻輳ウィンドウサイズ
(mss
)
0
13
25
38
50
時間(sec)
10 18.75 27.5 36.25 45
SSL1 SSL2SSL3 SSL4SSL5 SSL6
6本のTCPがバラバラに輻輳制御。帯域を有効に使いきれてない
HTTP/2(SPDY)は効率的なプロトコル
SPDY利用時の輻輳ウィンドウサイズの変遷
輻輳ウィンドウサイズ
(mss
)
0
13
25
38
50
時間(sec)
60 68.75 77.5 86.25 95
SPDY
1本のTCPで最高速まで利用。帯域を最大限に効率的に使っている。
3. HTTP/1.1は処理が煩雑なテキストプロトコル
HTTP/1.1 200 OK Content-Type: image/jpeg Transfer-Encoding: chunked Trailer: Foo
123 {binary data} 0 Foo: bar
Status-Lineは一行目 空白は1つ
ヘッダ名は大文字・小文字区別せず
ヘッダ領域の区切りはCRLF一つ
:の後に空白を許可
CRLFで改行、複数行対応は廃止
レスポンスデータがchunkedであり、サイズはまだ不定
一番最後にFooヘッダが付与されることを宣言
続くデータが123バイトであることを宣言 データ終了の合図
Trailヘッダchunk終了合図のCRLF
HTTP/2はきっちりしたバイナリープロトコル
00 00 00 01
01 04
00 00 1a
88 5c 82 08・・・・・・
73 ff
00 00 00 01
00 00
00 00 7b
{binary data}
:status = 200 content-length = 123 content-type = image/jpeg trailer = Foo
HEADERS
DATA
フレーム長:28バイト
フレーム長:123バイト
フレームタイプ:HEADERS, END_HEADERSフラグ
ストリームID: 1
ストリームID: 1
フレームタイプ:DATA, フラグなし
(* 記載スペースの都合上Trailer HEADERSは省いています)
データの 位置・サイズ・型
が明確
HTTP/2の技術的な特徴• HTTP/1.1のセマンティックスを変えない。
•サーバへのTCP接続数を1つに限定
• TLSと連携してプロトコルを自動選択
•バイナリープロトコル(テキストデータの曖昧さを排除)
•全2重多重化通信
•フロー制御、優先度指定
•サーバプッシュ機能
HTTP/2の技術的な特徴• SPDYのプロトコルアーキテクチャはそのまま利用
• SPDYの無駄なヘッダフィールドやフレームタイプを統廃合し、簡略化
• SPDYの実運用で明らかとなったフロー制御・優先度制御といった課題へ対応する
• TLS利用を前提とするSPDYに対し、平文接続も利用可能にする 。
•ヘッダ圧縮脆弱性(CRIME)対策として新しくHTTPに特化したヘッダ送受信仕様(HPACK)を策定する
HTTP/2初期ニゴシエーション 3種類で2段階(その1)
あらかじめサーバがHTTP/2対応とわかっている場合、直接第2段階の接続方法を行う。 (DNSレコードや HTTPヘッダによるリダイレクト)
HTTP/1.1の接続後 Upgradeヘッダを使って、HTTP/2 に接続をアップグレードする。
TLS接続時にALPN拡張フィールドを利用してHTTP/2に接続を行う。
(1) TLS + ALPN
(2) HTTP Upgrade
(3) 事前知識に
よるDirect接続
詳細後述
WebSocketと一緒
詳細仕様 検討中
暗号化通信
平文通信
ALPN (Application Layer Protocol Negotiation)
クライアント サーバー
1. ClientHello + ALPN拡張
2. ServerHello + ALPN拡張
サーバ側でプロトコルを決定し、通知する h2
3. TLS 証明書・暗号化情報交換
プロトコルリストをサーバに送信 h2,spdy/3.1,http/1.1
HTTP/2で通信
TLSハンドシェイクhttps://html5.ohtsu.org/seccamp_hokkaido_2015/ http2.pcap
HTTP/2初期ニゴシエーション 3種類で2段階(その2)
505249202a20485454502f322e300d0a0d0a534d0d0a0d0a
PRI * HTTP/2.0\r\n \r\n SM\r\n \r\n
クライアントから謎の24byteのマジックコードをサーバに送り、初期情報(SETTINGSフレームを交換する)
SETTINGS (初期ウィンドウサイズ、ストリームの最大同時オープン数等の設定情報を含む)
間違えてHTTP/1.1 サーバに接続した場合は即切断される
HTTP/2のデータフレーム(binary)
ペイロード長(24bit)タイプ(8bit) フラグ(8bit)X ストリームID(31bit)
ペイロードデータ(ペイロード長bit)
タイプ フレーム種類 タイプ フレーム種類0x00 DATA 0x05 PUSH_PROMISE0x01 HEADERS 0x06 PING0x02 PRIORITY 0x07 GOAWAY0x03 RST_STREAM 0x08 WINDOW_UPDATE0x04 SETTINGS 0x09 CONTINUATION
デフォルトは14bit(16K),
24bit(16M)まで拡張可フレームヘッダ 9バイト
フロー制御
クライアント
サーバA
サーバB
Reverse Proxy
高速
低速
AとBからのデータを バランスよく返す
WINDOW_UPDATE
WINDOW_UPDATE
サーバは、Window Size が0になったらデータ送信を停止
Window Size を増加させる
サーバA,B へのウィンドウサイズ更新を調整
TCPコネクション、ストリーム毎にフロー制御が可能
プライオリティ
クライアントReverse Proxy
コンテンツ HTML
画像
CSS, js
HTML
CSS JS
画像1 画像2 画像3 画像4
依存性と重みを指定
weight:16 weight:16
プライオリティのユースケース
• ファイルタイプ(HTML/CSS/JS/画像)に応じた返答順序の指定
• タブ切り替えによる重みの上げ下げ • 分割されたビデオデータなど順番が明示的
に決められている場合
サーバプッシュ機能
コンテンツリクエスト
クライアント サーバ
画像のHTTPリクエストを予約
コンテンツのレスポンス
画像データキャッシュ
サーバはコンテンツの中身を判断し,あらかじめコンテンツに含まれている画像のリクエストを予約する.
予約された画像リクエストはクライアントからサーバに送らずに,クライアントはサーバ側からの画像データの送付を待つ
サーバから送信された画像データは,クライアントのキャッシュに保存
HTTP/2がTLSに求める制限
• TLSのバージョンは1.2以上
• プロトコル選択にALPN(RFC7301)を使う
• サーバ認証を共有できる接続は接続共有が可能
• クライアント認証の利用は初期接続時のみ可能
• SNI(Server Name Indicator)拡張必須
• TLS Compression禁止
• Renegotiation禁止
• 鍵長 (DHE 2048bit以上、ECDHE 224bit以上)サポート必須 • PFS必須 (DHE, ECDHE)
• AEAD(GCM/CCM)以外の暗号方式をブラックリストとして利用禁止
HTTP/2 仕様でTLSの利用条件を制限すべきかどうか大きな議論になったが、 新しいプロトコルはよりセキュアな状態で提供すべきとの意見で合意
比べて見よう Cipher Listnginxのデフォルト設定はサーバ側のリストを優先に選択
Chromeの Cipher List
nginxの Cipher List
サーバはECDHE_RSA_WITH_AES_256_CBC_SHAを選択 →AEAD(GCM)じゃないのでHTTP/2の条件外
RSA認証でサーバリストの上から合うのを探していくと
もう一度HTTP/2のTLS条件を思い出せ!
• 鍵長 (DHE 2048bit以上、ECDHE 224bit以上)サポート必須 • PFS必須 (DHE, ECDHE)
• AEAD(GCM/CCM)以外の暗号方式をブラックリストとして利用禁止
(注: openssl-1.0.2以上限定です)
これならいけるはず
演習4.2:nginxでHTTP/2サーバを作る
HTTP/2のTLS接続 条件クリア
HTTP/2
WiresharkでTLSハンドシェイクを取得 Client/ServerHello のALPN Extension を確認する
演習5: HTTP HoLを再現させる
$ git clone https://github.com/shigeki/seccamp-imageserver/ $ cd seccamp-imageserver/lib ~/seccamp-imageserver/lib$ node ./server.js Litening on port 8080
location / {
root /home/seccamp/seccamp-imageserver/html;
index index.html index.htm;
}
location /images {
proxy_pass http://localhost:8080;
}
nginx.confの変更
imageサーバを立ち上げ
すぐ返す
3秒後返す
top related