
Uno strumento per auditare gli endpoint definiti in file di definizione esposti (Swagger/OpenAPI).
# sj (Swagger Jacker)

sj è uno strumento da riga di comando progettato per assistere nell'audit dei file di definizione Swagger/OpenAPI esposti, verificando gli endpoint API associati alla ricerca di autenticazione debole. Fornisce inoltre modelli di comandi per il test manuale delle vulnerabilità.
Lo fa analizzando il file di definizione per percorsi, parametri e metodi accettati, per poi utilizzare i risultati con uno dei cinque sottocomandi:
- `automate` - Genera una serie di richieste e analizza il codice di stato della risposta.
- `prepare` - Genera un elenco di comandi da utilizzare per il test manuale.
- `endpoints` - Genera un elenco di route API grezze. *I valori dei percorsi non verranno sostituiti con dati di test*.
- `brute` - Invia una serie di richieste a un target per trovare definizioni di operazioni basate su percorsi di file comunemente utilizzati.
- `convert` - Converte un file di definizione dalla v2 alla v3.
## Build
Per compilare dal sorgente, assicurati di avere installato Go versione `>= 1.22.5` ed esegui `go build` all'interno del repository:
```bash
$ git clone https://github.com/BishopFox/sj.git
$ cd sj/
$ go build .
```
## Install
Per installare l'ultima versione dello strumento, esegui:
```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
```
## Usage
> Usa il comando `automate` per inviare una serie di richieste a ciascun endpoint definito e analizzare il codice di stato di ogni risposta.
```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
```
Puoi usare il flag `--replay-proxy` per riprodurre le richieste corrispondenti attraverso un proxy separato (ad esempio, Burp Suite). Questo ti consente di instradare tutto il traffico attraverso un proxy (o direttamente) inviando solo i risultati interessanti al tuo proxy di intercettazione:
```bash
$ sj automate -u https://petstore.swagger.io/v2/swagger.json -qi --replay-proxy http://127.0.0.1:8080
```
Puoi anche combinarlo con `--proxy` per instradare il traffico di scansione attraverso un proxy diverso mentre riproduci le corrispondenze verso 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
```
Puoi anche richiedere un output dettagliato per vedere la risposta parziale (o completa):
```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"}
```
> Usa il comando `prepare` per preparare un elenco di comandi per il test manuale. Attualmente supporta sia `curl` che `sqlmap`. Probabilmente dovrai modificarli leggermente.
```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"}'
```
### Più content type per il corpo della richiesta
Spesso un'operazione dichiara lo stesso corpo sotto diversi content type. Per impostazione predefinita `sj`
invia quello con maggiori probabilità di essere accettato, preferendo `application/json`, poi
`application/x-www-form-urlencoded`, poi `multipart/form-data`, poi XML. La scelta è
deterministica, quindi esecuzioni ripetute producono comandi identici.
Poiché un parser JSON e un parser XML rappresentano superfici di attacco diverse, `--all-content-types`
invia ogni tipo dichiarato invece di solo quello preferito:
```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>'
```
Nota che questo moltiplica il numero di richieste inviate al target, e che
`--replay-proxy` ne riceve ognuna.
Per testare una singola codifica specifica, passala con `-H`. Quando l'operazione dichiara quel
tipo, `sj` invia il corpo corrispondente sotto di esso:
```bash
$ sj prepare -l spec.yaml -T https://api.example.com -q -H "Content-Type: application/xml"
```
Quando l'operazione *non* lo dichiara, `sj` avvisa e invia comunque il corpo preferito sotto
il tuo header, il che è utile per il test differenziale dei parser. I content type per cui `sj`
non riesce a codificare un corpo (`application/octet-stream`, `text/plain`) vengono saltati
invece di essere inviati come corpo vuoto sotto un header fuorviante.
> Usa il comando `endpoints` per generare un elenco di endpoint grezzi dal file di definizione fornito.
```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
```
> Usa il comando `brute` per inviare una serie di richieste nel tentativo di trovare un file di definizione sul target.
```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
```
> Usa il comando `convert` per convertire un file di definizione dalla versione 2 alla versione 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
Un elenco completo dei comandi è disponibile usando il flag `--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.
```