HTTP/2実装を攻撃
Stuart Larsen & John Villamil
Yahoo! ペンテスト チーム
本日の内容
▪  HTTP2とは
▪  なぜHTTP2は強い?
▪  http2fuzz
▪  ATS
▪  Firefox
▪  NodeJS
▪  まとめ
Stuart Larsen
▪  https://c0nrad.io
John Villamil
▪  @day6reak
自己紹介
HTTP/1.1 は1999年に登場
その後に・・・
▪  HTML と Java Script は進化した
▪  Webサイトは遥かに複雑になった
▪  ISPの回線速度は改善されてより広い帯域幅が提供されている
▪  Web上では遥かに多くのコンテンツが提供されている
▪  SSL は今ではより当たり前に使われている
▪  “HTTP/2よこんにちは、さようならSPDY”
http://blog.chromium.org/2015/02/hello-http2-goodbye-spdy-http-is_9.html
▪  HTTP/2 はSPDYおよびSPDY/2から進化したもの
▪  機能:
›  TCP使用の改善
›  バイナリプロトコル
•  フレームとストリーム
›  マルチプレキ゚シング (ストリーム)
•  かねてから認識されていた遅延を緩和
›  サーバからのプッシュ (PUSH_PROMISE)
›  データ圧縮 (HPACK)
›  フレーム
›  その他いろいろ
▪  大きな攻撃の可能性
HTTP/2 はパフォーマンスのため
HTTP/1.1からのアップグレード
▪  http:// および https:// というURIのスキームを維持
▪  TLS はオプションとしての位置づけ
›  Chrome と Firefox では必須としている
›  Internet Explorer と curlを含む他のクライアントはオプションのまま
▪  http:// のヘッダーをアップグレード
›  ラウンドトリップの原因になるが、HTTP/2 接続はより安定している
▪  マイナーバージョン番号は無し
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c
GET /index.html HTTP/1.1
Host: example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <SETTINGS payload>
HPACK
▪  HTTP はステートレス
›  リクエストのサイズ (cookies その他のヘッダー) は大きな影響を与える
›  圧縮は自然な解決策
▪  “Hpack was designed to make it difficult for a conforming implementation to leak information, to make encoding and decoding
very fast/cheap, to provide for receiver control over compression context size, to allow for proxy re-indexing (i.e. shared state
between frontend and backend within a proxy), and for quick comparisons of huffman-encoded strings.”
›  Roberto Peon, http://lists.w3.org/Archives/Public/ietf-http-wg//2014AprJun/1044.html
▪  レシーバが使用メモリサイズの最大値をコントロール
›  最少が0 で最大が 2^32
›  SETTINGS フレームで指定
▪  SPDY は圧縮アルゴリズムを使用
›  CRIME(Compression Ratio Info-leak Made Easy)攻撃に対して脆弱
HPACK
▪  name:value のペアをインデックスに
割り付け
›  双方のエンドポイントにおいてダイナミッ
クテーブルを作成
▪  差分符号化
›  スピードとサイズ圧縮に大きく寄与
›  リファレンス・テーブルはヘッダーのため
につくられる
›  現在のヘッダーと直前のものの差分のみが
符号化される
›  無駄を除去
▪  ハフマン符号化
›  固定ハフマンテーブル
›  文字列リテラル
HPACK 攻撃の可能性
▪  インデックス・テーブルのサイズとオフセット
▪  文字列リテラルの例
›  1つのビットがハフマン符号化されているかどうかを決定
›  整数はサイズを示す
›  文字列データが続く
›  オクテットの境界まで積み重ねていく
▪  コンテキスト更新
▪  ヘッダーテーブルのサイズ変更
›  デフォルトでは、動的テーブルのサイズは4k
▪  https://tools.ietf.org/html/rfc7541
ATSで手始め
▪  Yahoo ペンテストチームはATS (Apache Traffic Server)を見ることに
決定した
Http2ConnectionState.cc
ATS 2
▪  RFCより - http://tools.ietf.org/html/rfc7541#section-4.3
›  4.3. 動的テーブルサイズ変更時のエントリの削除
動的テーブルの最大サイズが減少するたびに、動的テーブルのサイズが最大サイズ以下になるまで動的テーブルの末尾
からエントリが削除されます。
▪  予期しないパケットの順序のために、 headers テーブルが空の時に
テーブルサイズを更新するバグが発生
▪  HTTP/1.1	はパイプライン化で複数のリクエストを送ることができる	
▪  ヘッドオブラインブロッキング	
›  レスポンスは送信された順に行われなくてはならない	
クライ
アント
サーバ
HTTP/1.1
クライ
アント
サーバ
HTTP/2
1
3
4
2
1
2
3
4
1
2
3
4
1
2
3
4
マルチプレキ゚シング
フレーム
▪  通信の基本ユニット
Length (24 bits)
Type (8 bits) Flags (8 bits)
R Stream Identifier (31 bits)
Payload (0+ bits)
▪  フレームタイプ
›  Headers
›  Data
›  Priority
›  Reset
›  Settings
›  Push
›  Ping
›  Goaway
›  Update
›  Continuation
サーバプッシュ
▪  リソースをクライアントにプッシュする新機能
▪  例えば、もし、クライアントが index.html をWebサーバへリクエス
トしたら、Webサーバは「クライアントは恐らく logo.png も欲しが
るだろう」と推測する
›  クライアントが logo.png を要求するのを待つ代わりに、サーバは先回りして
logo.png をプッシュするので、ユーザはリクエスト全てを待つ必要が無い
HTTP/2 の新しい攻撃の可能性
▪  HPACK	
▪  アップグレード・ダウングレード	
▪  つじつまの合わないマルチプレキ゚シング	
▪  不正なフォーマットのフレーム	
▪  クライアントに任意のデータをプッシュ	
▪  サーバに任意のデータをプッシュ	
▪  ストリーム依存	
▪  無効なフレームの記述
ファジング
▪  ランダムなデータ(バイナリ・アスキー)をアプリケーションに送信
して、予期せぬ動きをしないかをモニターする behavior
HTTPをファジング
メソッド
ホスト
パス
クエリー フラグメント
ヘッダー
ボディ
http2fuzz
▪  最初に公開された http2 ファ
ジングツール
▪  golangで開発されている
▪  クライアント・サーバ両方で
使用可能
•  テストケースの最小化のための
リプレイモード
•  高度なコンカレント機能
http2fuzz: クライアントモード
1. クライアントはWebサーバにhttp接続を確立
2. ALPN セクションでは h2 もしくは h2-14 を指定
3. 初期設定フレームはクライアント・サーバ間を往復する
4. ランダムに生成されたフレームがサーバに送信される
5. テスト対象のサーバがクラッシュしてもリスタートさせてテストを
継続
http2fuzz: サーバモード
1. サーバはローカルホストの証明書 をTLSようにロード
2. サーバはポートをバインドして接続を待つ
3. コネクションが確立されると、ランダムに生成されたフレームを、ブ
ラウザが接続を終了するまで送信し続ける
▪  ブラウザのファジングに使うスクリプトの例:
›  setInterval(function() { $.get(‘https://localhost:8000’) }, 2000)
▪  正常なフレームと、半分正常
なものと、完全に異常なもの
を混ぜる
▪  各々のストラテジは異なった
フレームを生成する
▪  ストラテジは組み合わせると
「ミニ・ファジングツール」
になる
ストラテジ
http2fuzz
ファジング
ツール
ファジング
ツール
ファジング
ツール
ストラテジ
1
ストラテジ
2
ストラテジ
3
ストラテジ
1
ストラテジ
3
ストラテジ
4
ストラテジ
2
ストラテジ
3
ストラテジ
4
ストラテジ
SettingsFuzzer:
▪  0から5の間のランダムな値を選ぶ
▪  ランダムな値で構成された多くのランダムな設定をSettingsFrameに
付け加える
HeaderFuzzer:
▪  0から5の間のランダムな値を選ぶ
▪  ランダムな値で構成された多くのランダムなHTTPヘッダーを
HeadersFrameに付け加える
ストラテジ
PriorityFuzzer:
▪  PriorityフレームにランダムなstreamDependencysteamId、weight、
および、 exclusive valueを設定して送信する
PingFuzzer:
▪  pingフレームにランダムな8 バイトペイロードを設定して送信する
ResetFuzzer:
▪  RSTフレームにランダムな streamIdとerrorCodeを設定して送信する
ストラテジ
WindowUpdateFuzzer:
▪  Window Update Frameにランダムな streamId とincr valueを設定して
送信する
RawFrameFuzzer:
▪  ランダムなframeType (0-12)、randomFlags (0-256)、
streamId(2**31)、および、 0から10000までの長さのランダムなバイ
配列を生成
▪  上記によって構成された異常なフレームを送信
ストラテジ
DataFuzzer:
▪  Data Frameにランダムな streamIdとendStream bool、そして、0か
ら10000バイトのランダムな長さのペイロードを設定して送信
PushPromiseFuzzer:
▪  PushPromise Frameに0から10000バイトのランダムな長さのペイロ
ード、streamId、promiseId、endHeaders bool、およびpadLengnth
(0-256)を設定して送信
ストラテジ
ContinuationFuzzer:
▪  Continuation Frameにランダムな streamIdとendStream bool、そして、
0から10000バイトのランダムな長さのペイロードを設定して送信
RawTCPFuzzer:
▪  TLS接続を確立して完全なガーベージを送信。ぺイロードは0から
10000バイトのランダムな長さの配列。
リプレイモード
▪  ファジングツールがクラッシュを検出したら原因を突き止めなくては
ならない
▪  ファジングに使われた各々のペイロードはreplay.jsonに保存される
▪  クラッシュするとファジングツールは停止してファイルも閉じられる
▪  ./http2fuzzを実行 –リプレイはフレームを同じ順序でサーバに送信
▪  そのため、いくつかのフレームを削除してそれでもなおサーバがクラ
ッシュするかどうかを確かめたり、必要なフレームを見つけ出すまで
フレームのセットを絞り込んだりすることができる。
FireFoxにおける不正なHTTP2ヘッダーフレームによるDoS
▪  不正なhttp2ヘッダーフレームがブラウザに送られる
▪  通常は、ヘッダーフレームはpad length、steam dependency
identifier、weight、header block fragmentそしてpaddingによって構
成される
▪  しかし、たったの1バイトのみが送信される
▪  これによって整数値のアンダーフローが発生し、結果として
nsCStringが約2^32バイトのメモリ割り当てを試みることになる
FireFoxにおける不正なHTTP2ヘッダーフレームによるDoS
Http2Session.cppの1226行目において、圧縮から復元されたフレームを
圧縮から復元されたフレームバッファに追加するコールが行われる:
FireFoxにおける不正なPushPromiseアンダーフローによる
DoS
Http2Session.cppの1634行目において、圧縮から復元されたフレームを
圧縮から復元されたフレームバッファに追加するコールが行われる:
= 4294967292
node-http2
▪  バグは見つかったが、状態を確定させるのが難しい
›  どのフレームをいつ送るのか
▪  全てのフィールドを検証する必要がある
›  値と大きさ
まとめ
▪  HTTP2とは
▪  なぜHTTP2は強い?
▪  http2fuzz
▪  ATS
▪  Firefox
▪  NodeJS
終わり
質問?

Stuart attacking http2 implementations truefinal-jp