概要
- Google の開発者ドキュメントサイトで 深刻な脆弱性 を発見
- FlaskセッションCookie にOAuthクライアント情報と署名鍵が含まれていた
- Cookie改ざんによる 任意コード実行(RCE) が可能
- 脆弱性の修正策と 報奨金$90,000 の授与
- 脆弱性の影響範囲と 技術的な詳細 の解説
Google開発者ドキュメントサイトのOAuthフローで発見した脆弱性
- Google Developers サイトのOAuthフロー調査中に /oauth2authorize へのアクセスを確認
- セッションCookieが発行され、Googleのサインインページへリダイレクト
- curlコマンド でCookieを取得し、内容を調査
- Cookieは Flask形式(session=<payload>.<timestamp>.<signature>)
- サイズが約1,200バイトと大きく、内容に疑問
- FlaskセッションCookieは 署名のみで暗号化されていない ため、内容の解析が可能
- 先頭のドットは zlib圧縮 を示す
- base64デコード・zlib解凍で中身を取得
- Cookie内容例
- _permanent: True
- google_oauth2_csrf_token: CSRFトークン
- google_oauth2_flow_<csrf>: バイト列(Flaskがbytes型をbase64化)
- バイト列をデコードすると pickle 形式
- oauth2client.client.OAuth2WebServerFlow オブジェクトが含まれ、 client_idとclient_secret が平文で格納
- Flask SECRET_KEY としてこのclient_secretが使われており、Cookie署名の検証にも利用
- 署名検証ロジックを再現し、完全一致を確認
セッション改ざんと任意コード実行への流れ
- FlaskサーバはセッションCookieを受け取ると
- 署名検証
- google_oauth2_flow_<csrf> をbase64デコード
- pickle.loads でオブジェクト復元
- 署名鍵が漏洩したことで、 攻撃者が任意のセッション内容を作成可能
- 自作pickleペイロードをセッションに埋め込むことで 任意コード実行 が成立
- 実証例として time.sleep(N) を実行するpickleを作成
- サーバ応答時間がN秒だけ遅延し、実行を裏付け
- 検証パターン
- Cookieなし:エラー
- 署名改ざん:エラー
- flowエントリなし:エラー
- 正常flow:トークン交換で失敗
- sleepペイロード:応答遅延で実行確認
影響範囲と修正策
- developers.google.com 以外にも同じ署名鍵が利用されていた
- firebase.google.com
- developer.android.com
- source.android.com
- docs.partner.android.com
- 修正案
- 漏洩したOAuthクライアントシークレットの ローテーション と既存セッションの無効化
- Flask SECRET_KEY をOAuth認証情報と分離し、サーバ側で安全に管理
- OAuthフローオブジェクトを サーバ側に保持 し、Cookieには参照IDのみ格納
- pickle の利用禁止、スキーマ検証付きのデータ専用フォーマットへ移行
報告と対応の経緯
- 2026年8月6日 脆弱性報告
- 8月7日 トリアージ・受理
- 8月27日 報奨金$90,000決定(通常$75,000+報告品質ボーナス)
- 10月7日 修正完了
- Google Bug HuntersチームとDevSiteエンジニアによる迅速な対応に謝意