
sj v2.8.2
用于审计暴露的(Swagger/OpenAPI)定义文件中定义的端点的工具。
sj (Swagger Jacker)

sj 是一款命令行工具,旨在通过检查关联的 API 端点是否存在弱身份验证,来协助审计暴露的 Swagger/OpenAPI 定义文件。它还提供用于手动漏洞测试的命令模板。
它通过解析定义文件中的路径、参数和可接受的方法,然后将结果用于以下五个子命令之一:
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)重放匹配的请求。这样,你可以将所有流量路由到一个代理(或直连),同时只将感兴趣的结果发送到你的拦截代理:
$ 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
INFO[0000] Gathering endpoints.
/v2/store/inventory
/v2/store/order/{orderId}
/v2/pet
/v2/pet
/v2/store/order
/v2/user/createWithList
/v2/pet/{petId}/uploadImage
/v2/pet/findByTags
/v2/pet/{petId}
/v2/pet/{petId}
/v2/user/{username}
/v2/user/{username}
/v2/user/createWithArray
/v2/pet/findByStatus
/v2/user/login
/v2/user/logout
/v2/user
使用
brute命令发送一系列请求,尝试在目标上查找定义文件。