
sj v2.8.2
노출된 (Swagger/OpenAPI) 정의 파일에 정의된 엔드포인트를 감사하는 도구입니다.
sj (Swagger Jacker)

sj는 노출된 Swagger/OpenAPI 정의 파일을 감사할 때 도움을 주기 위해 설계된 명령줄 도구로, 연관된 API 엔드포인트의 인증 취약점을 점검합니다. 또한 수동 취약점 테스트를 위한 명령 템플릿도 제공합니다.
이 도구는 정의 파일에서 경로, 매개변수, 허용되는 메서드를 파싱한 후, 그 결과를 다섯 개의 하위 명령 중 하나와 함께 사용합니다:
automate- 일련의 요청을 생성하고 응답의 상태 코드를 분석합니다.prepare- 수동 테스트에 사용할 명령 목록을 생성합니다.endpoints- 원시 API 경로 목록을 생성합니다. 경로 값은 테스트 데이터로 대체되지 않습니다.brute- 일반적으로 사용되는 파일 경로를 기반으로 대상에 일련의 요청을 보내 작업 정의를 찾습니다.convert- 정의 파일을 v2에서 v3로 변환합니다.
Build
소스에서 컴파일하려면 Go 버전 >= 1.22.5가 설치되어 있는지 확인하고 저장소 내에서 go build를 실행하세요:
$ git clone https://github.com/BishopFox/sj.git
$ cd sj/
$ go build .
Install
최신 버전의 도구를 설치하려면 다음을 실행하세요:
$ 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
Usage
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"}'
Multiple request body content types
하나의 작업(operation)이 동일한 본문을 여러 콘텐츠 타입으로 선언하는 경우가 많습니다. 기본적으로 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는 경고를 표시하고 선호하는 본문을 지정한 헤더로 그대로 전송하는데, 이는 파서 차이 테스트(parser-differential testing)에 유용합니다. 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