
Инструмент для аудита конечных точек, определенных в открытых файлах определений Swagger/OpenAPI.
# sj (Swagger Jacker)

sj — это инструмент командной строки, предназначенный для помощи в аудите открытых файлов определений Swagger/OpenAPI путём проверки связанных конечных точек API на слабую аутентификацию. Он также предоставляет шаблоны команд для ручного тестирования уязвимостей.
Он делает это путём разбора файла определения для извлечения путей, параметров и поддерживаемых методов, после чего использует результаты с одной из пяти подкоманд:
- `automate` — формирует серию запросов и анализирует код состояния ответа.
- `prepare` — генерирует список команд для ручного тестирования.
- `endpoints` — генерирует список необработанных маршрутов API. *Значения путей не будут заменены тестовыми данными*.
- `brute` — отправляет серию запросов к цели для поиска определений операций на основе часто используемых путей к файлам.
- `convert` — конвертирует файл определения из v2 в v3.
## Сборка
Чтобы скомпилировать из исходного кода, убедитесь, что у вас установлена версия Go `>= 1.22.5`, и выполните `go build` внутри репозитория:
```bash
$ git clone https://github.com/BishopFox/sj.git
$ cd sj/
$ go build .
```
## Установка
Чтобы установить последнюю версию инструмента, выполните:
```bash
$ 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`, чтобы отправить серию запросов к каждой определённой конечной точке и проанализировать код состояния каждого ответа.
```bash
$ 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). Это позволяет направлять весь трафик через один прокси (или напрямую), отправляя в ваш перехватывающий прокси только интересные результаты:
```bash
$ sj automate -u https://petstore.swagger.io/v2/swagger.json -qi --replay-proxy http://127.0.0.1:8080
```
Вы также можете комбинировать его с `--proxy`, чтобы направлять сканирующий трафик через другой прокси, при этом воспроизводя совпадения в Burp:
```bash
$ sj automate -u https://petstore.swagger.io/v2/swagger.json -qi -p http://proxy:9090 --replay-proxy http://127.0.0.1:8080
```
Вы также можете запросить подробный вывод, чтобы увидеть частичный (или полный) ответ:
```bash
$ 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`. Скорее всего, вам придётся их немного изменить.
```bash
$ 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`
отправляет каждый объявленный тип вместо только предпочтительного:
```bash
$ 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` отправляет соответствующее тело под ним:
```bash
$ sj prepare -l spec.yaml -T https://api.example.com -q -H "Content-Type: application/xml"
```
Когда операция *не* объявляет его, `sj` предупреждает и всё равно отправляет предпочтительное тело под
вашим заголовком, что полезно для дифференциального тестирования парсеров. Типы содержимого, для которых `sj`
не может закодировать тело (`application/octet-stream`, `text/plain`), пропускаются, а не отправляются как
пустое тело под вводящим в заблуждение заголовком.
> Используйте команду `endpoints`, чтобы сгенерировать список необработанных конечных точек из предоставленного файла определения.
```bash
$ 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`, чтобы отправить серию запросов в попытке найти файл определения на цели.
```bash
$ sj brute -u https://petstore.swagger.io -qi -p http://127.0.0.1:8080 -e
INFO[0000] Sending 2173 requests. This could take a while...
Request: 343
INFO[0033] Definition file found: https://petstore.swagger.io/v2/swagger
```
> Используйте команду `convert`, чтобы конвертировать файл определения из версии 2 в версию 3.
```bash
$ sj convert -u https://petstore.swagger.io/v2/swagger.json -qi -p http://127.0.0.1:8080 -o openapi.json
INFO[0000] Gathering API details.
INFO[0000] Wrote file to /current/directory/openapi.json
```
## Справка
Полный список команд можно найти, используя флаг `--help`:
```bash
$ sj --help
The process of reviewing and testing exposed API definition files is often tedious and requires a large investment of time for a thorough review.
sj (swaggerjacker) is a CLI tool that can be used to perform an initial check of API endpoints identified through exposed Swagger/OpenAPI definition files.
Once you determine what endpoints require authentication and which do not, you can use the "prepare" command to generate command templates for further (manual) testing.
Example usage:
Perform a quick check of endpoints which require authentication:
$ sj automate -u https://petstore.swagger.io/v2/swagger.json
Generate a list of commands to use for manual testing:
$ sj prepare -u https://petstore.swagger.io/v2/swagger.json
Generate a list of raw API routes for use with custom scripts:
$ sj endpoints -u https://petstore.swagger.io/v2/swagger.json
Perform a brute-force attack against the target to identify hidden definition files:
$ sj brute -u https://petstore.swagger.io
Convert a Swagger (v2) definition file to an OpenAPI (v3) definition file:
$ sj convert -u https://petstore.swagger.io/v2/swagger.json -o openapi.json
Usage:
sj [flags]
sj [command]
Available Commands:
automate Sends a series of automated requests to the discovered endpoints.
brute Sends a series of automated requests to discover hidden API operation definitions.
convert Converts a Swagger definition file to an OpenAPI v3 definition file.
endpoints Prints a list of endpoints from the target.
help Help about any command
prepare Prepares a set of commands for manual testing of each endpoint.
Flags:
-A, --agent string Set the User-Agent string. (default "Swagger Jacker (github.com/BishopFox/sj)")
--all-content-types Send a separate request for every request body content type an operation declares, instead of only the preferred one.
-b, --base-path string Set the API base path if not defined in the definition file (i.e. /V2/).
-f, --format string Declare the format of the definition file (json/yaml/yml/js). (default "json")
-H, --headers stringArray Add custom headers, separated by a colon ("Name: Value"). Multiple flags are accepted.
-h, --help help for sj
-i, --insecure Ignores server certificate validation.
-l, --local-file string Loads the documentation from a local file.
-o, --outfile string Output the results to a file. Only supported for the 'automate' and 'brute' commands at this time.
-p, --proxy string Proxy host and port. Example: http://127.0.0.1:8080 (default "NOPROXY")
-q, --quiet Do not prompt for user input - uses default values for all requests.
--replay-proxy string Replay matched requests using this proxy.
--randomize-user-agent Randomizes the user agent string. Default is 'false'.
-s, --safe-word stringArray Avoids 'dangerous word' check for the specified word(s). Multiple flags are accepted.
-T, --target string Manually set a target for the requests to be made if separate from the host the documentation resides on.
-t, --timeout int Set the request timeout period. (default 30)
-u, --url string Loads the documentation file from a URL
-v, --version version for sj
Use "sj [command] --help" for more information about a command.
```