Skip to content

Commit 9bfa57d

Browse files
committed
Add first hit flag to return first successful result.
1 parent fa71670 commit 9bfa57d

File tree

3 files changed

+40
-26
lines changed

3 files changed

+40
-26
lines changed

VHostScan.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def main():
2828

2929
parser.add_argument('--ignore-http-codes', dest='ignore_http_codes', type=str, help='Comma separated list of http codes to ignore with virtual host scans (default 404).', default='404')
3030
parser.add_argument('--ignore-content-length', dest='ignore_content_length', type=int, help='Ignore content lengths of specificed amount (default 0).', default=0)
31+
parser.add_argument('--first-hit', dest='first_hit', action='store_true', help='Return first successful result.', default=False)
3132
parser.add_argument('--unique-depth', dest='unique_depth', type=int, help='Show likely matches of page content that is found x times (default 1).', default=1)
3233
parser.add_argument("--ssl", dest="ssl", action="store_true", help="If set then connections will be made over HTTPS instead of HTTP (default http).", default=False)
3334
parser.add_argument("--fuzzy-logic", dest="fuzzy_logic", action="store_true", help="If set then fuzzy match will be performed against unique hosts (default off).", default=False)
@@ -40,7 +41,7 @@ def main():
4041
parser.add_argument("-oJ", dest="output_json", help="JSON output printed to a file when the -oJ option is specified with a filename argument." )
4142
parser.add_argument("-", dest="stdin", action="store_true", help="By passing a blank '-' you tell VHostScan to expect input from stdin (pipe).", default=False)
4243

43-
arguments = parser.parse_args()
44+
arguments = parser.parse_args()
4445
wordlist = []
4546

4647
word_list_types = []
@@ -69,23 +70,26 @@ def main():
6970

7071
user_agents = []
7172
if arguments.user_agent:
72-
print('[>] User-Agent specified, using it')
73+
print('[>] User-Agent specified, using it.')
7374
user_agents = [arguments.user_agent]
7475
elif arguments.random_agent:
75-
print('[>] Random User-Agent flag set')
76+
print('[>] Random User-Agent flag set.')
7677
user_agents = load_random_user_agents()
7778

7879
if(arguments.ssl):
79-
print("[>] SSL flag set, sending all results over HTTPS")
80+
print("[>] SSL flag set, sending all results over HTTPS.")
8081

8182
if(arguments.add_waf_bypass_headers):
82-
print("[>] WAF flag set, sending simple WAF bypass headers")
83+
print("[>] WAF flag set, sending simple WAF bypass headers.")
8384

8485
print("[>] Ignoring HTTP codes: %s" % (arguments.ignore_http_codes))
85-
86+
8687
if(arguments.ignore_content_length > 0):
8788
print("[>] Ignoring Content length: %s" % (arguments.ignore_content_length))
8889

90+
if arguments.first_hit:
91+
print("[>] First hit is set.")
92+
8993
if not arguments.no_lookup:
9094
for ip in Resolver().query(arguments.target_hosts, 'A'):
9195
host, aliases, ips = gethostbyaddr(str(ip))

lib/core/virtual_host_scanner.py

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313
class virtual_host_scanner(object):
1414
"""Virtual host scanning class
15-
15+
1616
Virtual host scanner has the following properties:
17-
17+
1818
Attributes:
1919
wordlist: location to a wordlist file to use with scans
2020
target: the target for scanning
@@ -38,6 +38,7 @@ def __init__(self, target, wordlist, **kwargs):
3838
self.add_waf_bypass_headers = kwargs.get('add_waf_bypass_headers', False)
3939
self.unique_depth = int(kwargs.get('unique_depth', 1))
4040
self.ignore_http_codes = kwargs.get('ignore_http_codes', '404')
41+
self.first_hit = kwargs.get('first_hit')
4142

4243
# this can be made redundant in future with better exceptions
4344
self.completed_scan=False
@@ -99,26 +100,15 @@ def scan(self):
99100

100101
# hash the page results to aid in identifing unique content
101102
page_hash = hashlib.sha256(res.text.encode('utf-8')).hexdigest()
102-
output = '[#] Found: {} (code: {}, length: {}, hash: {})\n'.format(hostname, res.status_code,
103-
res.headers.get('content-length'), page_hash)
104-
host = discovered_host()
105-
host.hostname = hostname
106-
host.response_code = res.status_code
107-
host.hash = page_hash
108-
host.content = res.content
109-
110-
for key, val in res.headers.items():
111-
output += ' {}: {}\n'.format(key, val)
112-
host.keys.append('{}: {}'.format(key, val))
113-
114-
self.hosts.append(host)
115-
116-
# print current results so feedback remains in "realtime"
117-
print(output)
103+
104+
self.hosts.append(self.create_host(res, hostname, page_hash))
118105

119106
# add url and hash into array for likely matches
120107
self.results.append(hostname + ',' + page_hash)
121-
108+
109+
if len(self.hosts) == 2 and self.first_hit:
110+
break
111+
122112
#rate limit the connection, if the int is 0 it is ignored
123113
time.sleep(self.rate_limit)
124114

@@ -141,3 +131,24 @@ def likely_matches(self):
141131
matches = ((segmented_data["key_col"].values).tolist())
142132

143133
return matches
134+
135+
def create_host(self, response, hostname, page_hash):
136+
"""
137+
Creates a host using the responce and the hash.
138+
Prints current result in real time.
139+
"""
140+
output = '[#] Found: {} (code: {}, length: {}, hash: {})\n'.format(hostname, response.status_code,
141+
response.headers.get('content-length'), page_hash)
142+
host = discovered_host()
143+
host.hostname = hostname
144+
host.response_code = response.status_code
145+
host.hash = page_hash
146+
host.content = response.content
147+
148+
for key, val in response.headers.items():
149+
output += ' {}: {}\n'.format(key, val)
150+
host.keys.append('{}: {}'.format(key, val))
151+
152+
print(output)
153+
154+
return host

tests/helpers/test_file_helper.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,3 @@ def test_get_combined_word_lists(wordlist):
3939

4040
assert wordlist.files == result['file_paths']
4141
assert wordlist.words == result['words']
42-

0 commit comments

Comments
 (0)