mirror of
https://github.com/BishopFox/sj.git
synced 2026-11-07 10:26:01 -10:00
117 lines
6.1 KiB
Go
117 lines
6.1 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var allContentTypes bool
|
|
var apiTarget string
|
|
var basePath string
|
|
var customDate string
|
|
var customEmail string
|
|
var customURL string
|
|
var force bool
|
|
var format string
|
|
var insecure bool
|
|
var localFile string
|
|
var Mode string
|
|
var outfile string
|
|
var proxy string
|
|
var replayProxy string
|
|
var quiet bool
|
|
var randomUserAgent bool
|
|
var rateLimit int
|
|
var rawValues bool
|
|
var safeWords []string
|
|
var swaggerURL string
|
|
var timeout int64
|
|
|
|
var rootCmd = &cobra.Command{
|
|
Use: "sj",
|
|
Short: "A tool for auditing documented (swagger/openapi) API endpoints.",
|
|
Long: `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`,
|
|
|
|
// PersistentPreRun captures the invoked subcommand name once, so the
|
|
// shared request-generation code can branch on the mode without reaching
|
|
// back into os.Args[1] (which panics or misbehaves when these functions
|
|
// are called programmatically rather than through the CLI).
|
|
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
|
Mode = cmd.Name()
|
|
},
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
if len(args) < 1 {
|
|
return fmt.Errorf("command not specified. See the --help flag for usage")
|
|
}
|
|
return nil
|
|
},
|
|
Version: "2.8.4",
|
|
// Errors and usage are surfaced once by Execute() with our own styling, so
|
|
// cobra should not also print them on a RunE failure.
|
|
SilenceErrors: true,
|
|
SilenceUsage: true,
|
|
}
|
|
|
|
// Execute runs the root command. It is the single place in the package that
|
|
// terminates the process: command and library code return errors up to here
|
|
// instead of calling os.Exit, which keeps that logic testable and reusable.
|
|
func Execute() {
|
|
if err := rootCmd.Execute(); err != nil {
|
|
printErr("%v", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func init() {
|
|
rootCmd.AddCommand(automateCmd)
|
|
rootCmd.AddCommand(endpointsCmd)
|
|
rootCmd.AddCommand(prepareCmd)
|
|
rootCmd.AddCommand(bruteCmd)
|
|
rootCmd.AddCommand(convertCmd)
|
|
rootCmd.PersistentFlags().BoolVar(&allContentTypes, "all-content-types", false, "Send a separate request for every request body content type an operation declares, instead of only the preferred one.")
|
|
rootCmd.PersistentFlags().StringVarP(&UserAgent, "agent", "A", "Swagger Jacker (github.com/BishopFox/sj)", "Set the User-Agent string.")
|
|
rootCmd.PersistentFlags().StringVarP(&basePath, "base-path", "b", "", "Set the API base path if not defined in the definition file (i.e. /V2/).")
|
|
rootCmd.PersistentFlags().StringVarP(&customURL, "custom-url", "c", "https://bishopfox.com", "Set a custom URL to test discovered URL parameters.")
|
|
rootCmd.PersistentFlags().StringVarP(&customDate, "custom-date", "d", "1990-01-01", "A custom date to test discovered date parameters.")
|
|
rootCmd.PersistentFlags().StringVar(&customEmail, "custom-email", "[email protected]", "A custom email address to test discovered email parameters.")
|
|
rootCmd.PersistentFlags().BoolVar(&force, "force", false, "Send requests without prompting, even if dangerous keywords are detected.")
|
|
rootCmd.PersistentFlags().StringVarP(&format, "format", "f", "json", "Declare the format of the definition file (json/yaml/yml/js).")
|
|
rootCmd.PersistentFlags().StringArrayVarP(&Headers, "headers", "H", nil, "Add custom headers, separated by a colon (\"Name: Value\"). Multiple flags are accepted.")
|
|
rootCmd.PersistentFlags().BoolVarP(&insecure, "insecure", "i", false, "Ignores server certificate validation.")
|
|
rootCmd.PersistentFlags().StringVarP(&localFile, "local-file", "l", "", "Loads the documentation from a local file.")
|
|
rootCmd.PersistentFlags().StringVarP(&outfile, "outfile", "o", "", "Output the results to a file. Only supported for the 'automate' and 'brute' commands at this time.")
|
|
rootCmd.PersistentFlags().StringVarP(&proxy, "proxy", "p", "NOPROXY", "Proxy host and port. Example: http://127.0.0.1:8080")
|
|
rootCmd.PersistentFlags().StringVar(&replayProxy, "replay-proxy", "", "Replay matched requests using this proxy.")
|
|
rootCmd.PersistentFlags().BoolVarP(&quiet, "quiet", "q", false, "Do not prompt for user input - uses default values for all requests.")
|
|
rootCmd.PersistentFlags().BoolVar(&randomUserAgent, "randomize-user-agent", false, "Randomizes the user agent string. Default is 'false'.")
|
|
rootCmd.PersistentFlags().BoolVar(&rawValues, "raw-values", false, "Do not URL-encode generated parameter names and values. Useful for parser-differential and WAF testing.")
|
|
// rootCmd.PersistentFlags().IntVarP(&rateLimit, "rate", "r", 15, "Limit the number of requests per second.") // NEED TO RE-IMPLEMENT RATE LIMIT
|
|
rootCmd.PersistentFlags().StringArrayVarP(&safeWords, "safe-word", "s", nil, "Avoids 'dangerous word' check for the specified word(s). Multiple flags are accepted.")
|
|
rootCmd.PersistentFlags().StringVarP(&apiTarget, "target", "T", "", "Manually set a target for the requests to be made if separate from the host the documentation resides on.")
|
|
rootCmd.PersistentFlags().Int64VarP(&timeout, "timeout", "t", 30, "Set the request timeout period.")
|
|
rootCmd.PersistentFlags().StringVarP(&swaggerURL, "url", "u", "", "Loads the documentation file from a URL")
|
|
rootCmd.CompletionOptions.DisableDefaultCmd = true
|
|
}
|