-
-
Notifications
You must be signed in to change notification settings - Fork 232
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #64 from diogoosorio/command-argument-class
Encapsulate the argument parsing logic in a class
- Loading branch information
Showing
5 changed files
with
235 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,6 @@ dist/ | |
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
from argparse import ArgumentParser | ||
|
||
class cli_argument_parser(object): | ||
def __init__(self): | ||
self._parser = self.setup_parser() | ||
|
||
def parse(self, argv): | ||
return self._parser.parse_args(argv) | ||
|
||
@staticmethod | ||
def setup_parser(): | ||
parser = ArgumentParser() | ||
|
||
parser.add_argument( | ||
'-t', dest='target_hosts', required=True, | ||
help='Set a target range of addresses to target. Ex 10.11.1.1-255' | ||
), | ||
|
||
parser.add_argument( | ||
'-w', dest='wordlists', | ||
help='Set the wordlists to use (default ./wordlists/virtual-host-scanning.txt)' | ||
) | ||
|
||
parser.add_argument( | ||
'-b', dest='base_host', default=False, | ||
help='Set host to be used during substitution in wordlist (default to TARGET).' | ||
) | ||
|
||
parser.add_argument( | ||
'-p', dest='port', default=80, type=int, | ||
help='Set the port to use (default 80).' | ||
) | ||
|
||
parser.add_argument( | ||
'-r', dest='real_port', type=int, default=False, | ||
help='The real port of the webserver to use in headers when not 80 (see RFC2616 14.23), useful when pivoting through ssh/nc etc (default to PORT).' | ||
) | ||
|
||
parser.add_argument( | ||
'--ignore-http-codes', dest='ignore_http_codes', default='404', | ||
help='Comma separated list of http codes to ignore with virtual host scans (default 404).' | ||
) | ||
|
||
parser.add_argument( | ||
'--ignore-content-length', dest='ignore_content_length', type=int, default=0, | ||
help='Ignore content lengths of specificed amount (default 0).' | ||
) | ||
|
||
parser.add_argument( | ||
'--first-hit', dest='first_hit', action='store_true', default=False, | ||
help='Return first successful result. Only use in scenarios where you are sure no catch-all is configured (such as a CTF).' | ||
) | ||
|
||
parser.add_argument( | ||
'--unique-depth', dest='unique_depth', type=int, default=1, | ||
help='Show likely matches of page content that is found x times (default 1).' | ||
) | ||
|
||
parser.add_argument( | ||
'--ssl', dest='ssl', action='store_true', default=False, | ||
help='If set then connections will be made over HTTPS instead of HTTP (default http).' | ||
) | ||
|
||
parser.add_argument( | ||
'--fuzzy-logic', dest='fuzzy_logic', action='store_true', default=False, | ||
help='If set then fuzzy match will be performed against unique hosts (default off).' | ||
) | ||
|
||
parser.add_argument( | ||
'--no-lookups', dest='no_lookup', action='store_true', default=False, | ||
help='Disable reverse lookups (identifies new targets and appends to wordlist, on by default).' | ||
) | ||
|
||
parser.add_argument( | ||
'--rate-limit', dest='rate_limit', type=int, default=0, | ||
help='Amount of time in seconds to delay between each scan (default 0).' | ||
) | ||
|
||
parser.add_argument( | ||
'--waf', dest='add_waf_bypass_headers', action='store_true', default=False, | ||
help='If set then simple WAF bypass headers will be sent.' | ||
) | ||
|
||
parser.add_argument( | ||
'-', dest='stdin', action='store_true', default=False, | ||
help="By passing a blank '-' you tell VHostScan to expect input from stdin (pipe)." | ||
) | ||
|
||
output = parser.add_mutually_exclusive_group() | ||
output.add_argument( | ||
'-oN', dest='output_normal', | ||
help='Normal output printed to a file when the -oN option is specified with a filename argument.' | ||
) | ||
|
||
output.add_argument( | ||
'-oJ', dest='output_json', | ||
help='JSON output printed to a file when the -oJ option is specified with a filename argument.' | ||
) | ||
|
||
user_agent = parser.add_mutually_exclusive_group() | ||
user_agent.add_argument( | ||
'--random-agent', dest='random_agent', action='store_true', default=False, | ||
help='If set, then each scan will use random user-agent from predefined list.' | ||
) | ||
|
||
user_agent.add_argument( | ||
'--user-agent', dest='user_agent', | ||
help='Specify a user-agent to use for scans' | ||
) | ||
|
||
return parser |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import argparse | ||
import pytest | ||
|
||
from lib.input import cli_argument_parser | ||
|
||
def test_parse_arguments_default_value(tmpdir): | ||
words = ['word1', 'word2', 'word3'] | ||
wordlist = tmpdir.mkdir('test_command').join('default') | ||
wordlist.write('\n'.join(words)) | ||
|
||
argv = ['-t', 'myhost'] | ||
|
||
arguments = cli_argument_parser().parse(argv) | ||
|
||
expected_arguments = { | ||
'target_hosts': 'myhost', | ||
'wordlists': None, | ||
'base_host': False, | ||
'port': 80, | ||
'real_port': False, | ||
'ignore_http_codes': '404', | ||
'ignore_content_length': 0, | ||
'first_hit': False , | ||
'unique_depth': 1, | ||
'fuzzy_logic': False, | ||
'no_lookup': False, | ||
'rate_limit': 0, | ||
'random_agent': False, | ||
'user_agent': None, | ||
'add_waf_bypass_headers': False, | ||
'output_normal': None, | ||
'output_json': None, | ||
'stdin': False, | ||
'ssl': False, | ||
} | ||
|
||
assert vars(arguments) == expected_arguments | ||
|
||
|
||
def test_parse_arguments_custom_arguments(tmpdir): | ||
words = ['some', 'other', 'words'] | ||
wordlist = tmpdir.mkdir('test_command').join('other_words') | ||
wordlist.write('\n'.join(words)) | ||
|
||
argv = [ | ||
'-t', '10.11.1.1', | ||
'-w', str(wordlist), | ||
'-b', 'myhost', | ||
'-p', '8000', | ||
'-r', '8001', | ||
'--ignore-http-codes', '400,500,302', | ||
'--ignore-content-length', '100', | ||
'--unique-depth', '5', | ||
'--first-hit', | ||
'--ssl', | ||
'--fuzzy-logic', | ||
'--no-lookups', | ||
'--rate-limit', '10', | ||
'--user-agent', 'some-user-agent', | ||
'--waf', | ||
'-oN', '/tmp/on', | ||
'-', | ||
] | ||
|
||
arguments = cli_argument_parser().parse(argv) | ||
|
||
expected_arguments = { | ||
'target_hosts': '10.11.1.1', | ||
'wordlists': str(wordlist), | ||
'base_host': 'myhost', | ||
'port': 8000, | ||
'real_port': 8001, | ||
'ignore_http_codes': '400,500,302', | ||
'ignore_content_length': 100, | ||
'first_hit': True, | ||
'unique_depth': 5, | ||
'ssl': True, | ||
'fuzzy_logic': True, | ||
'no_lookup': True, | ||
'rate_limit': 10, | ||
'user_agent': 'some-user-agent', | ||
'random_agent': False, | ||
'add_waf_bypass_headers': True, | ||
'output_normal': '/tmp/on', | ||
'output_json': None, | ||
'stdin': True, | ||
} | ||
|
||
assert vars(arguments) == expected_arguments | ||
|
||
def test_parse_arguments_mutually_exclusive_user_agent(): | ||
argv = [ | ||
'-t', '10.11.1.1', | ||
'--user-agent', 'my-user-agent', | ||
'--random-agent', | ||
] | ||
|
||
with pytest.raises(SystemExit): | ||
cli_argument_parser().parse(argv) | ||
|
||
def test_parse_arguments_mutually_exclusive_output(): | ||
argv = [ | ||
'-t', '10.11.1.1', | ||
'-oJ', | ||
'-oN', | ||
] | ||
|
||
with pytest.raises(SystemExit): | ||
cli_argument_parser().parse(argv) | ||
|
||
def test_parse_arguments_unknown_argument(): | ||
argv = [ | ||
'-t', '10.11.1.1', | ||
'-i-do-not-exist', | ||
] | ||
|
||
with pytest.raises(SystemExit): | ||
cli_argument_parser().parse(argv) |