アップデート一覧に戻る
New releaseSep 13, 2026

sj v2.8.2

公開された(Swagger/OpenAPI)定義ファイルで定義されたエンドポイントを監査するためのツール。

共有

sj (Swagger Jacker)

sj は、公開されている Swagger/OpenAPI 定義ファイルの監査を支援するために設計されたコマンドラインツールであり、関連する API エンドポイントの認証の脆弱性をチェックします。また、手動での脆弱性テスト用のコマンドテンプレートも提供します。

これは、定義ファイルを解析してパス、パラメータ、および受け入れられるメソッドを抽出し、その結果を次の 5 つのサブコマンドのいずれかで使用することで実現します:

  • automate - 一連のリクエストを作成し、レスポンスのステータスコードを分析します。
  • prepare - 手動テストで使用するコマンドのリストを生成します。
  • endpoints - 生の API ルートのリストを生成します。パス値はテストデータで置き換えられません。
  • brute - 一般的に使用されるファイルパスに基づいて操作定義を見つけるために、ターゲットに一連のリクエストを送信します。
  • convert - 定義ファイルを v2 から v3 に変換します。

ビルド

ソースからコンパイルするには、Go バージョン >= 1.22.5 がインストールされていることを確認し、リポジトリ内で go build を実行します:

$ git clone https://github.com/BishopFox/sj.git
$ cd sj/
$ go build .

インストール

ツールの最新バージョンをインストールするには、次を実行します:

$ go install github.com/BishopFox/sj@latest

# Note: you may also need to place the path to your Go binaries within your PATH environment variable:
$ export PATH=$PATH:~/go/bin

使用方法

automate コマンドを使用して、定義された各エンドポイントに一連のリクエストを送信し、各レスポンスのステータスコードを分析します。

$ sj automate -u https://petstore.swagger.io/v2/swagger.json -qi -p http://127.0.0.1:8080               

Gathering API details.
⚠  POST     500  /v2/pet
⚠  PUT      500  /v2/pet
✓  GET      200  /v2/pet/findByStatus
✓  GET      200  /v2/pet/findByTags
✓  GET      200  /v2/pet/1
✓  POST     200  /v2/pet/1
⚠  POST     N/A  /v2/pet/1/uploadImage
✓  GET      200  /v2/store/inventory
⚠  POST     N/A  /v2/store/order
⚠  GET      N/A  /v2/store/order/1
✓  POST     200  /v2/user
⚠  POST     N/A  /v2/user/createWithArray
⚠  POST     N/A  /v2/user/createWithList
✓  GET      200  /v2/user/login
✓  GET      200  /v2/user/logout
✓  GET      200  /v2/user/bishopfox
✓  PUT      200  /v2/user/bishopfox

--replay-proxy フラグを使用すると、一致したリクエストを別のプロキシ (例: Burp Suite) 経由でリプレイできます。これにより、すべてのトラフィックを 1 つのプロキシ (または直接) 経由でルーティングしつつ、興味深い結果のみをインターセプトプロキシに送信できます:

$ sj automate -u https://petstore.swagger.io/v2/swagger.json -qi --replay-proxy http://127.0.0.1:8080

また、--proxy と組み合わせて、スキャントラフィックを別のプロキシ経由でルーティングしつつ、一致したものを Burp にリプレイすることもできます:

$ sj automate -u https://petstore.swagger.io/v2/swagger.json -qi -p http://proxy:9090 --replay-proxy http://127.0.0.1:8080

詳細出力を要求して、部分的な (または完全な) レスポンスを確認することもできます:

$ sj automate -u https://petstore.swagger.io/v2/swagger.json -qi -p http://127.0.0.1:8080 -v           

Gathering API details.
⚠  POST     500  /v2/pet
   {"code":500,"type":"unknown","message":"something 
⚠  PUT      500  /v2/pet
   {"code":500,"type":"unknown","message":"something 
✓  GET      200  /v2/pet/findByStatus
   []
✓  GET      200  /v2/pet/findByTags
   []
✓  GET      200  /v2/pet/1
   {"id":1,"category":{"id":1,"name":"cat"},"name":"d
✓  POST     200  /v2/pet/1
   {"code":200,"type":"unknown","message":"1"}
⚠  POST     N/A  /v2/pet/1/uploadImage
✓  GET      200  /v2/store/inventory
   {"sold":115,"bishopfox":1,"SOLD":1,"string":224,"d
⚠  POST     N/A  /v2/store/order
⚠  GET      N/A  /v2/store/order/1
✓  POST     200  /v2/user
   {"code":200,"type":"unknown","message":"1"}
⚠  POST     N/A  /v2/user/createWithArray
⚠  POST     N/A  /v2/user/createWithList
✓  GET      200  /v2/user/login
   {"code":200,"type":"unknown","message":"logged in 
✓  GET      200  /v2/user/logout
   {"code":200,"type":"unknown","message":"ok"}
✓  GET      200  /v2/user/bishopfox
   {"id":1,"username":"bishopfox","firstName":"bishop
✓  PUT      200  /v2/user/bishopfox
   {"code":200,"type":"unknown","message":"1"}

prepare コマンドを使用して、手動テスト用のコマンドのリストを準備します。現在、curl と sqlmap の両方をサポートしています。これらは多少修正する必要があるでしょう。

$ sj prepare -u https://petstore.swagger.io/v2/swagger.json -qi -p http://127.0.0.1:8080

$ curl -X POST "https://petstore.swagger.io/v2/pet" -H 'Content-Type: application/json' -d '{"category":{"id":1,"name":"bishopfox"},"id":1,"name":"doggie","photoUrls":"https://bishopfox.com","status":"available","tags":[{"id":1,"name":"bishopfox"}]}'
$ curl -X PUT "https://petstore.swagger.io/v2/pet" -H 'Content-Type: application/json' -d '{"category":{"id":1,"name":"bishopfox"},"id":1,"name":"doggie","photoUrls":"https://bishopfox.com","status":"available","tags":[{"id":1,"name":"bishopfox"}]}'
$ curl -X GET "https://petstore.swagger.io/v2/pet/findByStatus?status=1"
$ curl -X GET "https://petstore.swagger.io/v2/pet/findByTags?tags=1"
$ curl -X GET "https://petstore.swagger.io/v2/pet/1"
$ curl -X POST "https://petstore.swagger.io/v2/pet/1" -H 'Content-Type: application/x-www-form-urlencoded' -d 'name=bishopfox&status=bishopfox'
$ curl -X POST "https://petstore.swagger.io/v2/pet/1/uploadImage" -H 'Content-Type: application/x-www-form-urlencoded' -d 'additionalMetadata=bishopfox&file=1'
$ curl -X GET "https://petstore.swagger.io/v2/store/inventory"
$ curl -X POST "https://petstore.swagger.io/v2/store/order" -H 'Content-Type: application/json' -d '{"complete":true,"id":1,"petId":1,"quantity":1,"shipDate":"1990-01-01","status":"placed"}'
$ curl -X GET "https://petstore.swagger.io/v2/store/order/1"
$ curl -X POST "https://petstore.swagger.io/v2/user" -H 'Content-Type: application/json' -d '{"email":"[email protected]","firstName":"bishopfox","id":1,"lastName":"bishopfox","password":"bishopfox","phone":"bishopfox","userStatus":1,"username":"bishopfox"}'
$ curl -X POST "https://petstore.swagger.io/v2/user/createWithArray" -H 'Content-Type: application/json' -d '[{"email":"[email protected]","firstName":"bishopfox","id":1,"lastName":"bishopfox","password":"bishopfox","phone":"bishopfox","userStatus":1,"username":"bishopfox"}]'
$ curl -X POST "https://petstore.swagger.io/v2/user/createWithList" -H 'Content-Type: application/json' -d '[{"email":"[email protected]","firstName":"bishopfox","id":1,"lastName":"bishopfox","password":"bishopfox","phone":"bishopfox","userStatus":1,"username":"bishopfox"}]'
$ curl -X GET "https://petstore.swagger.io/v2/user/login?username=bishopfox&password=bishopfox"
$ curl -X GET "https://petstore.swagger.io/v2/user/logout"
$ curl -X GET "https://petstore.swagger.io/v2/user/bishopfox"
$ curl -X PUT "https://petstore.swagger.io/v2/user/bishopfox" -H 'Content-Type: application/json' -d '{"email":"[email protected]","firstName":"bishopfox","id":1,"lastName":"bishopfox","password":"bishopfox","phone":"bishopfox","userStatus":1,"username":"bishopfox"}'

複数のリクエストボディのコンテンツタイプ

操作はしばしば、同じボディを複数のコンテンツタイプで宣言します。デフォルトでは sj は受け入れられる可能性が最も高いものを送信し、application/json、次に application/x-www-form-urlencoded、次に multipart/form-data、次に XML を優先します。この選択は決定論的であるため、繰り返し実行しても同一のコマンドが生成されます。

JSON パーサーと XML パーサーは異なる攻撃対象領域であるため、--all-content-types は優先されるものだけでなく、宣言されたすべてのタイプを送信します:

$ sj prepare -l spec.yaml -T https://api.example.com -q --all-content-types

$ curl -X POST "https://api.example.com/multi" -H 'Content-Type: application/json' -d '{"name":"bishopfox","size":1}'
$ curl -X POST "https://api.example.com/multi" -H 'Content-Type: application/x-www-form-urlencoded' -d 'name=bishopfox&size=1'
$ curl -X POST "https://api.example.com/multi" -F 'name=bishopfox' -F 'size=1'
$ curl -X POST "https://api.example.com/multi" -H 'Content-Type: application/xml' -d '<name>bishopfox</name><size>1</size>'

これはターゲットに送信されるリクエスト数が増加し、--replay-proxy がそのすべてを受信することに注意してください。

特定の単一のエンコーディングをテストするには、-H でそれを渡します。操作がそのタイプを宣言している場合、sj はそれに対応するボディをその下で送信します:

$ sj prepare -l spec.yaml -T https://api.example.com -q -H "Content-Type: application/xml"

操作がそれを宣言していない場合、sj は警告し、あなたのヘッダーの下で優先されるボディをとにかく送信します。これはパーサー差分テストに役立ちます。sj がボディをエンコードできないコンテンツタイプ (application/octet-stream、text/plain) は、誤解を招くヘッダーの下で空のボディとして送信されるのではなく、スキップされます。

endpoints コマンドを使用して、提供された定義ファイルから生のエンドポイントのリストを生成します。

$ sj endpoints -u https://petstore.swagger.io/v2/swagger.json -qi -p http://127.0.0.1:8080

カテゴリ