Skip to content

Commit d833928

Browse files
authored
Merge pull request #65 from diogoosorio/apply-pep8-convention
Apply PEP8 convetion to the codebase
2 parents 515cb06 + a3ba052 commit d833928

12 files changed

+227
-112
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ python:
55
- 3.6
66
install:
77
- pip --version
8-
- pip install -r requirements.txt
8+
- pip install -r test-requirements.txt
99
- pip install pep8
1010
before_script:
11-
- pep8 --ignore=E501,W293,E202,E241,W291 *.py
11+
- pep8 -v *.py lib/
1212
script:
1313
- pytest

VHostScan.py

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,17 @@
77
from socket import gethostbyaddr
88
from lib.core.virtual_host_scanner import *
99
from lib.helpers.output_helper import *
10-
from lib.helpers.file_helper import get_combined_word_lists, load_random_user_agents
10+
from lib.helpers.file_helper import get_combined_word_lists
11+
from lib.helpers.file_helper import load_random_user_agents
1112
from lib.core.__version__ import __version__
1213
from lib.input import cli_argument_parser
1314

15+
DEFAULT_WORDLIST_FILE = os.path.join(
16+
os.path.dirname(os.path.abspath(__file__)),
17+
'wordlists',
18+
'virtual-host-scanning.txt'
19+
)
20+
1421

1522
def print_banner():
1623
print("+-+-+-+-+-+-+-+-+-+ v. %s" % __version__)
@@ -20,13 +27,14 @@ def print_banner():
2027

2128
def main():
2229
print_banner()
23-
30+
2431
parser = cli_argument_parser()
2532
arguments = parser.parse(sys.argv[1:])
2633

2734
wordlist = []
2835
word_list_types = []
29-
default_wordlist = "./wordlists/virtual-host-scanning.txt" if not arguments.stdin else None
36+
37+
default_wordlist = DEFAULT_WORDLIST_FILE if not arguments.stdin else None
3038

3139
if arguments.stdin:
3240
word_list_types.append('stdin')
@@ -42,11 +50,14 @@ def main():
4250
print("[!] No words found in provided wordlists, unable to scan.")
4351
sys.exit(1)
4452

45-
print("[+] Starting virtual host scan for {host} using port {port} and {inputs}".format(
46-
host=arguments.target_hosts,
47-
port=arguments.port,
48-
inputs=', '.join(word_list_types),
49-
))
53+
print(
54+
"[+] Starting virtual host scan for {host} using "
55+
"port {port} and {inputs}".format(
56+
host=arguments.target_hosts,
57+
port=arguments.port,
58+
inputs=', '.join(word_list_types),
59+
)
60+
)
5061

5162
user_agents = []
5263
if arguments.user_agent:
@@ -62,10 +73,14 @@ def main():
6273
if(arguments.add_waf_bypass_headers):
6374
print("[>] WAF flag set, sending simple WAF bypass headers.")
6475

65-
print("[>] Ignoring HTTP codes: %s" % (arguments.ignore_http_codes))
76+
print("[>] Ignoring HTTP codes: {}".format(arguments.ignore_http_codes))
6677

6778
if(arguments.ignore_content_length > 0):
68-
print("[>] Ignoring Content length: %s" % (arguments.ignore_content_length))
79+
print(
80+
"[>] Ignoring Content length: {}".format(
81+
arguments.ignore_content_length
82+
)
83+
)
6984

7085
if arguments.first_hit:
7186
print("[>] First hit is set.")
@@ -78,7 +93,12 @@ def main():
7893
wordlist.extend(aliases)
7994

8095
scanner_args = vars(arguments)
81-
scanner_args.update({'target': arguments.target_hosts, 'wordlist': wordlist, 'user_agents': user_agents})
96+
scanner_args.update({
97+
'target': arguments.target_hosts,
98+
'wordlist': wordlist,
99+
'user_agents': user_agents
100+
})
101+
82102
scanner = virtual_host_scanner(**scanner_args)
83103
scanner.scan()
84104
output = output_helper(scanner, arguments)

lib/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
See the file 'doc/COPYING' for copying permission
66
"""
77

8-
pass
8+
pass

lib/core/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
See the file 'doc/COPYING' for copying permission
66
"""
77

8-
pass
8+
pass

lib/core/__version__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# +-+-+-+-+-+-+-+-+-+
1+
# +-+-+-+-+-+-+-+-+-+
22
# |V|H|o|s|t|S|c|a|n| Developed by @codingo_ & @__timk
33
# +-+-+-+-+-+-+-+-+-+ https://github.com/codingo/VHostScan
44

5-
__version__ = '1.6.1'
5+
__version__ = '1.6.2'

lib/core/discovered_host.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ def __init__(self):
88
self.response_code = 0
99
self.hash = ''
1010
self.keys = []
11-
self.content = b''
11+
self.content = b''

lib/core/virtual_host_scanner.py

Lines changed: 75 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,26 @@
88
from lib.core.discovered_host import *
99
from urllib3.util import ssl_
1010

11-
DEFAULT_USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'
11+
DEFAULT_USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) '\
12+
'AppleWebKit/537.36 (KHTML, like Gecko) '\
13+
'Chrome/61.0.3163.100 Safari/537.36'
1214

1315
_target_host = None
1416
_ssl_wrap_socket = ssl_.ssl_wrap_socket
17+
18+
1519
def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None,
1620
ca_certs=None, server_hostname=None,
1721
ssl_version=None, ciphers=None, ssl_context=None,
1822
ca_cert_dir=None):
19-
ssl_wrap_socket_(sock, keyfile=keyfile, certfile=certfile, cert_reqs=cert_reqs,
20-
ca_certs=ca_certs, server_hostname=_target_host,
21-
ssl_version=ssl_version, ciphers=ciphers, ssl_context=ssl_context,
22-
ca_cert_dir=ca_cert_dir)
23-
ssl_.ssl_wrap_socket = _ssl_wrap_socket
23+
ssl_wrap_socket_(sock, keyfile=keyfile, certfile=certfile,
24+
cert_reqs=cert_reqs, ca_certs=ca_certs,
25+
server_hostname=_target_host, ssl_version=ssl_version,
26+
ciphers=ciphers, ssl_context=ssl_context,
27+
ca_cert_dir=ca_cert_dir)
28+
29+
ssl_.ssl_wrap_socket = _ssl_wrap_socket
30+
2431

2532
class virtual_host_scanner(object):
2633
"""Virtual host scanning class
@@ -35,43 +42,52 @@ class virtual_host_scanner(object):
3542
ignore_content_length: integer value of content length to ignore
3643
output: folder to write output file to
3744
"""
38-
39-
4045
def __init__(self, target, wordlist, **kwargs):
4146
self.target = target
4247
self.wordlist = wordlist
4348
self.base_host = kwargs.get('base_host')
4449
self.rate_limit = int(kwargs.get('rate_limit', 0))
4550
self.port = int(kwargs.get('port', 80))
4651
self.real_port = int(kwargs.get('real_port', 80))
47-
self.ignore_content_length = int(kwargs.get('ignore_content_length', 0))
4852
self.ssl = kwargs.get('ssl', False)
4953
self.fuzzy_logic = kwargs.get('fuzzy_logic', False)
50-
self.add_waf_bypass_headers = kwargs.get('add_waf_bypass_headers', False)
5154
self.unique_depth = int(kwargs.get('unique_depth', 1))
5255
self.ignore_http_codes = kwargs.get('ignore_http_codes', '404')
5356
self.first_hit = kwargs.get('first_hit')
5457

58+
self.ignore_content_length = int(
59+
kwargs.get('ignore_content_length', 0)
60+
)
61+
62+
self.add_waf_bypass_headers = kwargs.get(
63+
'add_waf_bypass_headers',
64+
False
65+
)
66+
5567
# this can be made redundant in future with better exceptions
56-
self.completed_scan=False
57-
58-
# this is maintained until likely-matches is refactored to use new class
68+
self.completed_scan = False
69+
70+
# this is maintained until likely-matches is refactored to use
71+
# new class
5972
self.results = []
60-
61-
# store associated data for discovered hosts in array for oN, oJ, etc'
73+
74+
# store associated data for discovered hosts
75+
# in array for oN, oJ, etc'
6276
self.hosts = []
6377

6478
# available user-agents
65-
self.user_agents = list(kwargs.get('user_agents')) or [DEFAULT_USER_AGENT]
79+
self.user_agents = list(kwargs.get('user_agents')) \
80+
or [DEFAULT_USER_AGENT]
6681

6782
@property
6883
def ignore_http_codes(self):
6984
return self._ignore_http_codes
7085

7186
@ignore_http_codes.setter
7287
def ignore_http_codes(self, codes):
73-
self._ignore_http_codes = [int(code) for code in codes.replace(' ', '').split(',')]
74-
88+
self._ignore_http_codes = [
89+
int(code) for code in codes.replace(' ', '').split(',')
90+
]
7591

7692
def scan(self):
7793
if not self.base_host:
@@ -83,9 +99,14 @@ def scan(self):
8399
for virtual_host in self.wordlist:
84100
hostname = virtual_host.replace('%s', self.base_host)
85101

102+
if self.real_port == 80:
103+
host_header = hostname
104+
else:
105+
host_header = '{}:{}'.format(hostname, self.real_port)
106+
86107
headers = {
87108
'User-Agent': random.choice(self.user_agents),
88-
'Host': hostname if self.real_port == 80 else '{}:{}'.format(hostname, self.real_port),
109+
'Host': host_header,
89110
'Accept': '*/*'
90111
}
91112

@@ -96,8 +117,13 @@ def scan(self):
96117
'X-Remote-IP': '127.0.0.1',
97118
'X-Remote-Addr': '127.0.0.1'
98119
})
99-
100-
dest_url = '{}://{}:{}/'.format('https' if self.ssl else 'http', self.target, self.port)
120+
121+
dest_url = '{}://{}:{}/'.format(
122+
'https' if self.ssl else 'http',
123+
self.target,
124+
self.port
125+
)
126+
101127
_target_host = hostname
102128

103129
try:
@@ -108,7 +134,9 @@ def scan(self):
108134
if res.status_code in self.ignore_http_codes:
109135
continue
110136

111-
if self.ignore_content_length > 0 and self.ignore_content_length == int(res.headers.get('content-length')):
137+
response_length = int(res.headers.get('content-length', 0))
138+
if self.ignore_content_length and \
139+
self.ignore_content_length == response_length:
112140
continue
113141

114142
# hash the page results to aid in identifing unique content
@@ -119,49 +147,59 @@ def scan(self):
119147
# add url and hash into array for likely matches
120148
self.results.append(hostname + ',' + page_hash)
121149

122-
if len(self.hosts) == 2 and self.first_hit:
150+
if len(self.hosts) >= 1 and self.first_hit:
123151
break
124152

125-
#rate limit the connection, if the int is 0 it is ignored
153+
# rate limit the connection, if the int is 0 it is ignored
126154
time.sleep(self.rate_limit)
127155

128-
self.completed_scan=True
129-
156+
self.completed_scan = True
130157

131158
def likely_matches(self):
132159
if self.completed_scan is False:
133-
print("[!] Likely matches cannot be printed as a scan has not yet been run.")
134-
return
160+
print("[!] Likely matches cannot be printed "
161+
"as a scan has not yet been run.")
162+
return
135163

136164
# segment results from previous scan into usable results
137-
segmented_data={}
165+
segmented_data = {}
138166
for item in self.results:
139167
result = item.split(",")
140168
segmented_data[result[0]] = result[1]
141169

142-
dataframe = pd.DataFrame([[key, value] for key, value in segmented_data.items()], columns=["key_col", "val_col"])
143-
segmented_data = dataframe.groupby("val_col").filter(lambda x: len(x) <= self.unique_depth)
144-
matches = ((segmented_data["key_col"].values).tolist())
170+
dataframe = pd.DataFrame([
171+
[key, value] for key, value in segmented_data.items()],
172+
columns=["key_col", "val_col"]
173+
)
145174

146-
return matches
175+
segmented_data = dataframe.groupby("val_col").filter(
176+
lambda x: len(x) <= self.unique_depth
177+
)
178+
179+
return segmented_data["key_col"].values.tolist()
147180

148181
def create_host(self, response, hostname, page_hash):
149182
"""
150183
Creates a host using the responce and the hash.
151184
Prints current result in real time.
152185
"""
153-
output = '[#] Found: {} (code: {}, length: {}, hash: {})\n'.format(hostname, response.status_code,
154-
response.headers.get('content-length'), page_hash)
186+
output = '[#] Found: {} (code: {}, length: {}, hash: {})\n'.format(
187+
hostname,
188+
response.status_code,
189+
response.headers.get('content-length'),
190+
page_hash
191+
)
192+
155193
host = discovered_host()
156194
host.hostname = hostname
157195
host.response_code = response.status_code
158196
host.hash = page_hash
159-
host.content = response.content
197+
host.contnet = response.content
160198

161199
for key, val in response.headers.items():
162200
output += ' {}: {}\n'.format(key, val)
163201
host.keys.append('{}: {}'.format(key, val))
164202

165203
print(output)
166204

167-
return host
205+
return host

lib/helpers/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
See the file 'doc/COPYING' for copying permission
66
"""
77

8-
pass
8+
pass

lib/helpers/file_helper.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ def __init__(self, output_file):
88

99
def check_directory(self):
1010
directory = os.path.dirname(self.output_file)
11-
11+
1212
try:
1313
os.stat(directory)
1414
except:
@@ -18,7 +18,7 @@ def check_directory(self):
1818
# placeholder for error checking on -oJ implementation
1919
def is_json(json_file):
2020
try:
21-
with open(json_file, "r") as f:
21+
with open(json_file, "r") as f:
2222
json_object = json.load(f)
2323
except ValueError:
2424
return False
@@ -27,7 +27,7 @@ def is_json(json_file):
2727
def write_file(self, contents):
2828
# check if host directory exists, if not create it
2929
self.check_directory()
30-
30+
3131
with open(self.output_file, "w") as o:
3232
o.write(contents)
3333

0 commit comments

Comments
 (0)