# Methods for parsing command line arguments # # NOTE: you do **not** need to modify this file for this assignment! # # This file was originally from https://github.com/kernelmethod/xfuzz/ import argparse, os # Default list of HTTP response status codes that we should match if the -mc argument # is not passed in. DEFAULT_MATCH_CODES = [200, 301, 302, 401, 403] # Program description printed out when the -h / --help flag is given DESCRIPTION = "Simple web fuzzer using aiohttp" # Parser epilogue. This is displayed after the information about the flags when the # --help flag is passed in to xfuzz. EPILOGUE = """ ----- EXAMPLES: Find all pages under https://example.org/ ending with .php or .html that return an HTTP 200 OK response. python3 -m xfuzz -w /path/to/wordlist.txt -mc 200 -e php -e html \\ -u 'https://example.org/FUZZ' Find users with some integer UID by fuzzing the `id` URL parameter of a page: seq 1 10000 | python3 -m xfuzz -u 'https://example.org/user?id=FUZZ' Make POST requests with JSON data to fuzz a login API and brute-force the password of the 'admin' user. python3 -m xfuzz -w /path/to/password/wordlist.txt -mc 200 -u 'https://example.org/login' \\ -X POST -H 'Content-Type: application/json' -d '{"username":"admin","password":"FUZZ"}' You can find more information at https://github.com/kernelmethod/xfuzz """ def setup_argument_parser() -> argparse.ArgumentParser: """Create a new ``ArgumentParser`` instance to parse command-line arguments passed in to the script.""" # If the COLUMNS environment variable is not set, default to text wrapping at # 100 columns. os.environ.setdefault("COLUMNS", "100") parser = argparse.ArgumentParser( prog="fuzzer", description=DESCRIPTION, formatter_class=argparse.RawDescriptionHelpFormatter, epilog=EPILOGUE, ) # NOTE: you may *not* change any of the command line arguments that are here by # default! These are needed to make the tests work correctly. # Add required arguments parser.add_argument( "-u", "--url", required=True, help="The URL to fuzz", ) # Add optional arguments parser.add_argument( "-w", "--wordlist", required=True, help=( "The wordlist to use (provided as a path to a local file). If '-' is provided, xfuzz will " "read its wordlist from stdin instead." ), ) parser.add_argument( "-e", "--extension", dest="extensions", action="append", help=("One or more extensions to append (e.g. php, html, etc.). Multiple extensions " "may be provided."), ) parser.add_argument( "-X", "--method", default="GET", help="HTTP method to use (GET, POST, PUT, etc.) (default: %(default)s)", ) parser.add_argument( "-H", "--header", dest="headers", action="append", help=( 'One or more HTTP headers to add to requests, in the form "HeaderName: HeaderValue" ' '(e.g. "Content-Type: application/json" or `"Host: FUZZ.example.com"`). May be ' "specified one or more times." ), ) parser.add_argument("-d", "--data", default=None, help="Data to send in the body of the HTTP request.") parser.add_argument( "-mc", dest="match_codes", type=int, action="append", help=( "Match HTTP response codes. May be specified multiple times. If let unspecified, " f"defaults to the following response codes: {DEFAULT_MATCH_CODES}" ), ) # TODO: add any additional (optional) arguments that you want! However, note that these # arguments will not be explicitly supplied to the program during testing. return parser def parse_args(argv=None) -> argparse.Namespace: """Parse command-line arguments and return them in an ``argparse.Namespace`` instance.""" # NOTE: do *not* edit this function! The test harness expects arguments to be passed in to # the fuzz() function in a certain way. parser = setup_argument_parser() args = parser.parse_args(args=argv) # Set defaults for arguments with action="append" args.extensions = [] if args.extensions is None else [f".{ext}" for ext in args.extensions] args.headers = [] if args.headers is None else args.headers args.match_codes = DEFAULT_MATCH_CODES if args.match_codes is None else args.match_codes return args