
Human-friendly Thrift encoder/decoder
Readable Thriftは、バイナリ形式のThriftプロトコルメッセージを人間にわかりやすい形式に変換(およびその逆も)することで、扱いやすくします。これにより、バイナリ形式のThriftメッセージの手動分析や改ざんが、HTTPのようなプレーンテキストプロトコルを扱うのと同じくらい簡単になります。
このライブラリはJavaで実装されており、JVM上で動作するBurpやZAPなどの一般的なWebアプリケーションテストツール向け拡張機能との統合が可能です。分析ツールや改ざんツールを立ち上げて稼働させるには、適切なバイトを抽出してコーデックに渡すだけです。
readablethriftライブラリはGradleベースのMavenパッケージであり、他のプロジェクトに依存関係としてインストールして組み込むことができます。エンコードとデコードのための4つのシンプルなメソッドを提供しており、生のバイナリ形式またはBase64エンコード形式に対応しています。
注: 現在サポートされているのは標準のバイナリ形式プロトコルのみです。コンパクトバイナリとJSON(コーデックが生成する読みやすいJSONとは異なります)はまだサポートされていません。
ThriftCodec::decodeメソッドは、バイナリのThriftメッセージを含む生のバイトバッファから、説明的なorg.json.JSONObjectインスタンスを直接生成します。ThriftCodec::decodeB64String静的メソッドは、Base64文字列をデコードしてから、それに対してdecodeを呼び出します。ThriftCodec::encodeメソッドは、説明的なorg.json.JSONObjectインスタンスを、同等のThriftバイナリメッセージを含む生のバイトバッファに変換します。ThriftCodec::b64encodeJson静的メソッドは、JSONオブジェクトをThriftバイナリ形式に変換し、結果をBase64エンコードします。ThriftCodecクラスは拡張可能なように設計されており、追加のバイナリ形式ヘッダーやカプセル化など、Thriftバイナリプロトコル形式への変更や拡張を処理できます。
ライブラリに含まれる対話型コマンドラインインターフェースを使用するには、デフォルトのGradleタスクを使用してJARをビルドし、java -jarで実行します:
$ ./gradlew
BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed
$ java -jar build/libs/readablethrift-1.0.0-all.jar
Enter Base64 encoded message or JSON object (or q to quit):
人間が読みやすいJSONがどのように見えるかを示すために、アプリケーショントラフィックから抽出したBase64エンコードされたバイナリブロブの例を見てみましょう:
$ base64 -D | hexdump
gAEAAQAAAAVsb2dpbgAAAAAMAAALAAAAAAAIY29vbHVzZXILAAEAAAALcGFzc3dvcmQxMjMAAA==
00000000: 8001 0001 0000 0005 6c6f 6769 6e00 0000 ........login...
00000010: 000c 0000 0b00 0000 0000 0863 6f6f 6c75 ...........coolu
00000020: 7365 720b 0001 0000 000b 7061 7373 776f ser.......passwo
00000030: 7264 3132 3300 00 rd123..
「login」「username」「password」という文字列から、これが認証リクエストであることがうかがえます。このメッセージをその場で改ざんしたい場合、Thriftプロトコルのバイナリ形式パーサーの内部仕様を調べ、hexエディタでメッセージの構造を把握し、各フィールドを手動で更新する必要があります。usernameとpasswordの文字列の場合、文字列自体に加えて、先頭に付く長さの値も更新する必要があります。これは退屈で、エラーが発生しやすく、時間のかかる作業です。Readable Thriftを使えばこのプロセスはより簡単になります。以下は、同じメッセージをReadable Thriftに渡した結果です:
Enter Base64 encoded message or JSON object (or q to quit): gAEAAQAAAAVsb2dpbgAAAAAMAAALAAAAAAAIY29vbHVzZXILAAEAAAALcGFzc3dvcmQxMjMAAA==
{"message": {
"name": "login",
"type": "call",
"fields": [{
"id": 0,
"type": "struct",
"value": [
{
"id": 0,
"type": "string",
"value": "cooluser"
},
{
"id": 1,
"type": "string",
"value": "password123"
}
]
}],
"seqid": 0
}}
これで、このメッセージが「login」メソッドへの呼び出しを表しており、引数として2つの文字列値を含むstructを持つことを簡単に確認できます。文字列値の更新は、value JSONフィールドを編集して、新しいJSONテキストをコーデックに渡すだけで簡単にできます。長さのプレフィックスやバイナリ形式のその他の詳細はすべて自動的に処理されます。
可能性のあるオプションパラメータをテストするために、新しいフィールドを追加することも可能です。管理者用やデバッグ用のbooleanフラグがあるかもしれません。あるいは権限IDのリストはどうでしょうか? id、type、valueを指定して新しいフィールドを記述し、それをfields配列に追加します:
Enter Base64 encoded message or JSON object (or q to quit): {"message": {
"name": "login",
"type": "call",
"fields": [{
"id": 0,
"type": "struct",
"value": [
{
"id": 0,
"type": "string",
"value": "differentuser"
},
{
"id": 1,
"type": "string",
"value": "differentpassword!"
}
]
},
{"id": 1, "type": "bool", "value": true},
{"id": 2, "type": "list", "value":
{
"elemType": "i32",
"list": [1, 2, 3]
}
},
{"id": 3, "type": "map", "value":
{
"keyType": "string",
"valueType": "string",
"map": {
"dog": "bark",
"cat": "meow"
}
}
}],
"seqid": 0
}}
gAEAAQAAAAVsb2dpbgAAAAAMAAALAAAAAAANZGlmZmVyZW50dXNlcgsAAQAAABJkaWZmZXJlbnRwYXNzd29yZCEAAgABAQ8AAggAAAADAAAAAQAAAAIAAAADDQADCwsAAAACAAAAA2NhdAAAAARtZW93AAAAA2RvZwAAAARiYXJrAA==
以下は、更新されたメッセージをThriftバイナリプロトコルに変換し直したものです:
$ base64 -D | hexdump
gAEAAQAAAAVsb2dpbgAAAAAMAAALAAAAAAANZGlmZmVyZW50dXNlcgsAAQAAABJkaWZmZXJlbnRwYXNzd29yZCEAAgABAQ8AAggAAAADAAAAAQAAAAIAAAADDQADCwsAAAACAAAAA2NhdAAAAARtZW93AAAAA2RvZwAAAARiYXJrAA==
00000000: 8001 0001 0000 0005 6c6f 6769 6e00 0000 ........login...
00000010: 000c 0000 0b00 0000 0000 0d64 6966 6665 ...........diffe
00000020: 7265 6e74 7573 6572 0b00 0100 0000 1264 rentuser.......d
00000030: 6966 6665 7265 6e74 7061 7373 776f 7264 ifferentpassword
00000040: 2100 0200 0101 0f00 0208 0000 0003 0000 !...............
00000050: 0001 0000 0002 0000 0003 0d00 030b 0b00 ................
00000060: 0000 0200 0000 0363 6174 0000 0004 6d65 .......cat....me
00000070: 6f77 0000 0003 646f 6700 0000 0462 6172 ow....dog....bar
00000080: 6b00