PacketProxyを触ってみました
こんにちは、SSTでWeb脆弱性診断用のツール(スキャンツール)開発をしている坂本(Twitter, GitHub)です。
先日DeNA様がGitHub上で公開された PacketProxy を触ってみました。
ここがすごい
- PacketProxyすごい!! 名前の通り、パケットレベルで中身を見たり、編集するのに向いてる。
- javaソースで約4万8千行とそれなりの規模。
- フレームワークやライブラリはあまり使わず、HTTP/WebSocketのパースなどを手作りしてる。
- ソケット周りも Java8 時代のJDKライブラリベースで、Nettyみたいなフレームワークは使ってない。でも手作りでここまで作れるのはすごい。
- DNS偽装 + invisible https proxy でスマホの通信を intercept できるようになってるのもすごい。
- スマホの通信で、OS側でプロキシ設定してもプロキシ通らない通信があるので、そうしたところにキッチリ対処してきてる感じがする。
- HTTPのJSON リクエスト/レスポンスボディをpretty printしてくれるの便利。
ちょっと不便だったところ
- HTTPに限って言うとパラメータの解析をしてくれないのでちょっとさみしい。
- UTF-8以外の日本語が文字化けする。(既に Issue が作成されてるので今後に期待)
- 弊社診断サービスみたいに、不特定多数のお客様からの診断だと未だに Shift_JIS, EUC-JP というのもあるので・・・。
- JSON の pretty print で日本語が文字化けする。
- さすがに msgpack のデコード/エンコードは未対応。これについては自分で拡張できそうなので、それで対応できるかも。
- リクエストとレスポンスがUI上は分離されてるので、ブラウザで沢山リソース読み込むところではどのレスポンスがどのリクエストに対応するのか、入り乱れてしまって分かりづらい。
- SpringBootを使ったWebアプリの画面をプロキシ通してみたところ、10回くらいリクエストが連続したのち、ブラウザ側で接続エラーとなってしまった。
- テストに使ったのは次の SpringBoot アプリ : https://github.com/SecureSkyTechnology/springboot2-async-chat-demo
- curl コマンドでアクセスしたら
curl: (52) Empty reply from server
となってしまった。History上はリクエスト/レスポンスが表示されてるのに、なぜcurlまで戻ってこないのか不明。
開発者視点から
- Spring Tools Suite 4 (4.4.0.RELEASE : Eclipse 4.13.0.v20190916-1323ベース) で Gradle プロジェクトのインポートに失敗する。
- 環境:
- Buildership, Eclipse Plugi-ins for Gradle 3.1.2.v20190903-1802
- Gradle Tooling API 5.6.1.v201903-1802
- Windows 10 Pro
- エラー内容 : import -> Gradle -> Existing Gradle Project で git clone したプロジェクトをimportしようとすると、
org.gradle.tooling.GradleConnectionException: Could not create an instance of Tooling API implementation using the specified Gradle distribution 'https://services.gradle.org/distributions/gradle-4.6-all.zip'.
が発生。
- 環境:
build.gradle
のserVersion
タスク中で git コマンドを実行した結果からバージョン番号を生成している。そのため、PATHにgitが入ってない環境だとビルドできない。- gitが入っていない環境であれば、適当なバージョン番号を返すようローカルで修正して対応。
- AdoptOpenJDK8 で
gradlew assemble
すると以下のコンパイルエラーが発生した。 → JFX がバンドルされている Oracle JDK 8 に切り替えたところコンパイルエラーについては解決した。
----------
446. ERROR in (..)\github\dena\PacketProxy\src\main\java\core\packetproxy\gui\GUIMain.java (at line 47)
import com.sun.javafx.util.Utils;
^^^^^^^^^^^^^^
The import com.sun.javafx cannot be resolved
----------
447. WARNING in (..)\github\dena\PacketProxy\src\main\java\core\packetproxy\gui\GUIMain.java (at line 133)
final Container cp = getContentPane();
^^
The value of the local variable cp is not used
----------
448. ERROR in (..)\github\dena\PacketProxy\src\main\java\core\packetproxy\gui\GUIMain.java (at line 181)
if (Utils.isWindows()) {
^^^^^
Utils cannot be resolved
----------
449. ERROR in (..)\github\dena\PacketProxy\src\main\java\core\packetproxy\gui\GUIMain.java (at line 183)
} else if (Utils.isMac()) {
^^^^^
Utils cannot be resolved
----------
- Oracle JDK 8でビルドしてみたところ、今度は以下のエラーが発生した。
Missing header in: src\jmh\java\packetproxy\common\StringSearchBenchmark.java
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':licenseJmh'.
> License violations were found: (...)\github\dena\PacketProxy\src\jmh\java\packetproxy\common\StringSearchBenchmark.java}
- →
src/jmh
フォルダ自体を削除しても、今度はmainのソースについて大量にLicense violations were found
が発生した。com.github.hierynomus.license
プラグインが関係してそうだが、ライセンスのダウンロードなども含めて影響しそうなため、ここでギブアップ。
まとめ
- パケットレベルのプロキシツールとしてすごい便利そうです。
- スマホの通信をキャプチャ/インターセプトするためのサポート機能が特に便利そうです。
- HTTPレベルのサポートについて今後に期待したいです。
最後に、これだけのツールがオープンソースで公開されるのはすごい有り難いです、DeNAに感謝です!
余談
spindle-localproxy の作者として、敗北感に打ちひしがれています。
DNSサーバを組み込みされてて・・・しかも、HTTPSで SNIを元にInvisible Proxy までキッチリ作ってきてるんですよ・・・?もう、ソースを見るたびにどんどん「負けた・・・」という感情が膨れ上がって、これはもうマインドフルネスで感情を切り離すしか、ブログを書く術が無いじゃないですか・・・。
あと SSL パススルーも作ってきてるの、さすが分かってらっしゃる。これも spindle-localproxy では作りきれなかった部分で、この辺が無いとスマホでのGoogle/Appleプラットフォーム側の決済APIがエラーになってしまうんですよね・・・。多分クライアント側でサーバ証明書を pinning してるために、MITMで別の証明書に差し替えてしまうと弾かれてしまうのだと思いますが。
この敗北感と焼け付くような嫉妬の感情を、spindle-localproxy にPacketProxyの機能をパクるの機能強化に捧げるよう今後も精進していきたいと思います。