SSTエンジニアブログ

SSTのエンジニアによるWebセキュリティの技術を中心としたエンジニアブログです。

spindle-localproxy というローカルHTTPプロキシを開発しました【Part1】

こんにちは、SSTでWeb脆弱性診断用のツール(スキャンツール)開発をしている坂本(Twitter, GitHub)です。

普段は診断向けのスキャンツールを開発していますが、今年(2019年)の3月~8月にかけて、SST内部で使用する独自ローカルHTTPプロキシ「spindle-localproxy」を開発しました。

本記事(Part1)では開発の経緯や簡単な機能説明などを紹介します。 後日公開のPart2では、公開しても差し支えない範囲で技術的な内容を紹介します。 (以下、特に断りがない場合は「ローカルHTTPプロキシ」を「HTTPプロキシ」と表記します。)

3行でまとめ:

  1. 業務課題解決のためには独自のローカルHTTPプロキシツールを作るのが良さそう。
  2. 作ってみた。(作りきれなかった機能もあった)
  3. 好評っぽい。業務課題も全部ではないが大分解決できたっぽい。(作りきれなかった機能含めて)俺たちの戦いはこれからだ!

Part1. 開発の経緯と機能紹介

今回開発したHTTPプロキシは、診断サービスの 事前調査 における 画面遷移図 作成をサポートする社内ツールになります。 Part1 では概要紹介として、SSTにおける「事前調査」「画面遷移図」とは何か、どういう課題があってHTTPプロキシを作ることでどう解決したのかをざっくりとご紹介します。

診断サービスでの「事前調査」と「画面遷移図」

SSTの診断サービスでは、 診断を始める前の調整段階の作業を「事前調査」と呼んでいます。 主に以下のような作業を実施します。

  1. 診断対象となるリクエストをリストアップして見積もりを作成し、お客様と合意する。
  2. 診断時に必要となるアカウントなど洗い出して、お客様に準備してもらうか、自分たちで用意する。

診断対象となるリクエストをリストアップするために、SSTでは実際に診断対象のサイトにアクセスし、Excelでサイトマップ( これが「画面遷移図」 )を作成しています。 画面遷移図を作るにはHTTPプロキシを通したブラウザで診断対象のサイトにアクセスし、実際の利用者と同様にリンクを辿ったりフォームを送信します。 その時のHTTPプロキシの通信ログからURL / リクエストメソッド / パラメータ数を取り出して画面遷移図に記入します。 リクエストメソッドやパラメータ数に応じて診断対象に含めるか判断し、それも画面遷移図に記入します。

f:id:msakamoto-sf:20190819162839p:plain
画面遷移図の例

さらに診断対象のリクエストをそのまま再送(「リセンド」)し、同じレスポンスが返されるかチェックしてその結果も記入します。 仮に同じレスポンスが返されない場合、1度きりの遷移だったりCSRF対策がされている可能性があります。 そうなると診断作業の工数に影響してくるため、事前調査段階でそうした通信が無いかチェックしているわけです。 このチェックを「リセンドチェック」と呼んだりもしています。

なお事前調査ではお客様との調整作業が多くなるため、診断員とは別に事前調査を専門とするチームが担当しています。

画面遷移図作成における課題と独自HTTPプロキシによる解決

画面遷移図の作成では、これまで以下のような課題がありました。

  • HTTPプロキシ(主にBurpを使用)からExcelへのコピー & ペースト作業が多く、手間のかかる作業となっていた。
  • パラメータ数のカウント方法が診断で使うスキャンツールと一部異なっているため、事前調査段階でパラメータ数が低く見積もられるケースがあった。
  • 診断の工数に影響する以下のようなリクエストを目視でトリアージしていたため、抜け漏れが発生していた。
    • パラメータ数が異常に多い。
    • レスポンスが遅い。
    • リクエスト形式が特殊で、スキャンツールが対応していない。
    • (これらを事前調査段階で見逃すと、診断が時間内に完了しないリスクが高まる。)
  • リセンドチェックもBurpのRepeaterで手動送信し、結果の差分はComparerを使って目視でチェックするという手間のかかる作業となっていた。
    • Burp の Comparer はレスポンス中のマルチバイト文字が文字化けしてしまい、これも差分の目視チェックのやりづらさに拍車をかけていた。
  • 全体的に人手に頼った作業が多いため、教育コストと属人性が高くなっていた。
  • Excelにコピー & ペーストできる情報量には限りがあるため、診断開始後にWebサイトが画面遷移図と異なる挙動を示した時、「事前調査のときはどういうリクエストとレスポンスだったか?」を見直せなかった。

Burp の Extender を開発して解決することも一時は考えましたが、Burpのプロキシ通信としてExtenderが取れる情報に不足がある(タイムスタンプやTLS情報が含まれない)などの理由で見送りました。 むしろBurpに代わる事前調査専用のHTTPプロキシを作ったほうが抜本的な解決につながると考え、以下のような二本立てで課題解決を目指しました。

  1. 画面遷移図作成をサポートする専用HTTPプロキシの開発
    • コピー & ペーストの手間を削減する。
    • パラメータ数のカウント方式をスキャンツールと揃える。
    • 診断の工数に影響するリクエストを検出し、アラートを上げる。
    • HTTPリクエスト/レスポンスを保存し、過去の通信ログを参照できるようにする。
    • リセンドチェックに必要な操作を一部自動化し、レスポンスの差分を見やすくする。
    • → これらの解決策を通じて人手に頼った作業を削減し、教育コストと属人性を低くする。
  2. 上記HTTPプロキシからの通信ログを集約する中央サーバの開発
    • 画面遷移図作成時に実行中のHTTPプロキシからの通信ログを集約する。
    • 集約したログをWeb画面上で確認できるようにして、事前調査の段階で診断員が通信ログをチェックできるようにする。
    • 集約したログを元にWeb画面上でサイトマップを作成し、画面遷移図としてExcelにエクスポートできるようにする。
    • → これらの解決策を通じて事前調査担当と診断員の距離を縮め、コミュニケーションを活性化させることで診断サービスの品質と効率の向上に貢献する。

一連の開発プロジェクトを「サイトマップという網の目のような繊維(遷移とかけてる)を巻き取る紡錘」というイメージを込めて、コードネーム「spindle」と命名しました。

社内承認と開発結果

事前調査を担当するチームでは前述のような課題が以前から認識されており、エンジニアリングによる解決に期待がかかっていました。 そこに、次のような坂本側の都合がマッチしました。

  • LittleProxy というOSSのJava製HTTPプロキシライブラリがあったため、ゼロからHTTPプロキシを作る必要は無さそう(= 現実的な期間でHTTPプロキシを開発できる)。
  • 坂本の方のスキャンツール開発が今年2月に一段落し、たまには別の開発もしてリフレッシュしたかった。
  • Java製のスキャンツール開発ではJava11など最新環境へのマイグレーションが予定されているが、いきなり大規模なマイグレーションに挑むのではなく、リスクの小さい開発案件で先行検証しておきたかった。

診断チーム側にも「しばらくスキャンツール開発はストップします。代わりに、うまく行けば画面遷移図の精度が向上する見込み。」とお願いし、時間を貰いました。 診断チームと診断マネージャーには圧倒的感謝です。

当初予定:

  • 2019-03 : 技術検証
  • 2019-04 ~ 05 : 画面遷移図作成専用のHTTPプロキシ開発
  • 2019-06 : 通信ログ集約中央サーバの開発
  • 2019-07 : 予備

が・・・蓋を開けてみたら、HTTPプロキシでWebSocketの対応に超苦戦し(Part2で解説予定)、その他の見積もりも甘く・・・

現実:

  • 2019-03 ~ 04 : 技術検証
  • 2019-05 ~ 07 : HTTPプロキシ開発
  • 2019-08 : HTTPプロキシの正式リリース, 資料整理

半年も使ってしまうと、スキャンツール開発でのタスクも積まれておりさすがにタイムアップとなってしまいました。 通信ログを集約する中央サーバの開発は全く着手できず、来年以降の宿題となりました。

こうして坂本の血と汗と涙と、
特にお風呂に入ってる時に頭に浮かぶ思いつきと、
坂本が技術検証で集中・苦戦しているときにブツブツ独り言をつぶやくのを全力でスルーしてくれた両隣・真向かいに座っている同僚の忍耐力と、
なかなか成果物が見えてこないにも関わらず辛抱強く待ってくれた事前調査担当チーム各位の太平洋より広い心と、
半年にわたる開発期間を与えてくれた診断チームとSSTの幹部各位のおかげで産み出されたHTTPプロキシが、
本記事タイトルにある「spindle-localproxy」となります。

spindle-localproxy の機能紹介

以下が画面遷移図作成専用のHTTPプロキシ「spindle-localproxy」の画面です。

f:id:msakamoto-sf:20190819162913p:plain
spindle-localproxyの実行画面

プロキシとしては以下のように一通りのカスタマイズが可能です。

  • 上流プロキシの設定
  • 接続/受信タイムアウトの設定
  • ホスト名/IPアドレスのマッピング(hosts設定)
  • クライアント証明書の設定
  • SNI(Server Name Indication)拡張のグローバル ON/OFF 設定, ホストごと ON/OFF 設定

MITM(man in the middle)によりHTTPS通信のリクエスト/レスポンスを復号して保存・表示します。

  • spindle-localproxy が内部でSSL/TLS通信をインターセプトし、ホストごとの証明書を自動生成することでMITMを実現しています。
  • spindle-localproxy 専用のCA証明書を「信頼できるルート証明書」としてホストOS(Chrome)/ブラウザ(Firefox)にインストールする必要があります。

HTTPプロキシについてはBurpのProxyタブと似たUIにしています。

  • 通信ログ一覧から画面遷移図へのコピペや、リセンドチェックができるようになっています。
  • 通信ログ一覧では柔軟なフィルタ設定に対応しています。
  • リクエスト/レスポンスのファイルダウンロードを備えており、またそれぞれ文字コードを指定して文字化けを補正することが可能です。
  • スキャンツールが解析するのと同じ方式でリクエストパラメータを解析します。JSONにも対応しています。
  • 過去の通信ログを遡って表示できます。
  • レスポンスが遅い / パラメータ数が大量にある / 特殊なリクエスト形式などを spindle-localproxy 側で自動検出し、通信ログ一覧中のアイコンで強調表示します。

実際の使い方は次のようになります。

  1. ブラウザにHTTPプロキシとして spindle-localproxy のポート番号を設定し、診断対象のサイトにアクセスする。
  2. 画面遷移図に記録したい通信について、通信ログ一覧のクリップアイコンをクリックする。→画面遷移図にそのままペーストできるフォーマットで、URL / 診断対象是非 / リクエストメソッドとパラメータ数がクリップボードにコピーされる。
    • パラメータ数のカウントや診断対象是非の判定は spindle-localproxy 側で処理しているため、面倒な複数回のコピペや人手による判断が不要となります。
  3. 画面遷移図にペーストする。
  4. 通信ログ一覧のリプレイアイコンをクリックし、リセンドする。→ リセンド結果を確認し、リセンドOK/NGを画面遷移図にコピペする。
    • リセンド結果の画面ではブラウザ上で操作したときのレスポンスと、リセンドのときのレスポンスが並べて表示されます。差分が発生した行は色分けして見やすく表示されるとともに、レスポンス中の日本語も文字コードを自動判定して文字化けを最小限に抑えます。

課題解決の結果

これにより、画面遷移図作成における課題を以下のように解決してみました。

  • HTTPプロキシ(主にBurpを使用)からExcelへのコピー & ペースト作業が多く、手間のかかる作業となっていた。
    • → コピペが最低2回で済むようになります。
  • パラメータ数のカウント方法が診断で使うスキャンツールと一部異なっているため、事前調査段階でパラメータ数が低く見積もられるケースがあった。
    • → スキャンツールと同じロジックでパラメータ数を自動でカウントするため、見積もり精度が向上します。
  • 診断の工数に影響する以下のようなリクエストを目視でトリアージしていたため、抜け漏れが発生していた。
    • パラメータ数が異常に多い。
    • レスポンスが遅い。
    • リクエスト形式が特殊で、スキャンツールが対応していない。
    • → spindle-localproxy 側で自動検出します。(それを画面遷移図に転記するのは人手だよりになるので、そこは未解決。)
  • リセンドチェックもBurpのRepeaterで手動送信し、結果の差分はComparerを使って目視でチェックするという手間のかかる作業となっていた。
    • → リセンド専用の機能を実装し、2クリックでリセンドチェックが可能となりました。レスポンスの差分が見やすくなり、文字化けも解消しました。
  • 全体的に人手に頼った作業が多いため、教育コストと属人性が高くなっていた。
    • → 専用ツールで日本語UIのため、教育コストを削減できるようになりました。目視で処理していた作業の多くが spindle-localproxy 側で自動処理できるようになり、属人性を低減できました。
  • Excelにコピー & ペーストできる情報量には限りがあるため、診断開始後にWebサイトが画面遷移図と異なる挙動を示した時、「事前調査のときはどういうリクエストとレスポンスだったか?」を見直せなかった。
    • → その画面遷移図を作成した担当者のローカルPC上に通信ログが保存されるため、過去の通信ログを見直すことが可能になりました。

これらが本当の解決となっているのか、これからの実運用でその答えが出るでしょう。(正式リリース前のテスト利用では概ね好評でした)

spindle の今後

当面は社内で spindle-localproxy を実運用してみて、現場からのフィードバックを反映させブラッシュアップを図ります。

宿題とspindle自身の課題として以下があります。

  • 通信ログを集約する中央サーバの開発が着手できていません。これについては来年以降、あらためて時間が取れた時に着手を考えています。
  • 開発リソースも不足しています。現状は坂本の一人開発なのがボトルネックでありリスクですが、JavaではマルチスレッドやHTTP通信、UIではExtJSなどそれなりの学習コストを有する技術の組み合わせとなっているのも開発リソースの調達を難しくしています。(これらの技術要素については Part2 で紹介予定です)
  • 課題解決という視点では、現状の診断サービス運用の枠内におさまる局所最適とも呼べるアプローチとなっており、ドラスティックな全体最適に挑戦する余地が残されています。

これらを踏まえつつ、あえて大きな夢を描くとどうなるか?以下は坂本個人の妄想段階ですが、こんなことできたらいいな・・・というイメージです。

  1. 通信ログを集約する中央サーバ上で、WebUIから画面遷移図を作成してExcelにエキスポートできるようになる。
  2. WebUI上で作った画面遷移図をお客様も見れるようにして、診断対象選定や診断中のトラブルをWeb上の画面遷移図を通してやりとりできるようになる。
  3. お客様自身がspindle-localproxyを手元で動かして、お客様自身で画面遷移図を作れるようになる。
  4. スキャン機能も追加して、お客様自身でスキャンできるようになる。

ビジネス観点からは突っ込みどころ満載ではありますが、面白さやワクワク感を感じられる青写真を夢見つつ、来年以降の開発を積み重ねていこうと思います。