-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathbrute-vhosts
More file actions
executable file
·147 lines (123 loc) · 4.17 KB
/
brute-vhosts
File metadata and controls
executable file
·147 lines (123 loc) · 4.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python2.7
###########
# IMPORTS #
###########
import sys
import argparse
from multiprocessing import Pool
#from multiprocessing.dummy import Pool # utilise threads rather than subprocesses
import signal
import modules.curl as curl
####################
# GLOBAL VARIABLES #
####################
global target
global canary
#############
# FUNCTIONS #
#############
def brute_vhost(vhost):
max_attempts = 3
attempt = 0
while attempt < max_attempts:
try:
url, _, _, _, _, _, resolve = curl.explode_target(target, vhost)
response = curl.request(method='GET', url=url, resolve=resolve)
except:
#import traceback
#traceback.print_exc()
attempt += 1
if attempt == max_attempts:
sys.stderr.write('%s => Request timed out.\n' % (target))
continue
else:
if not canary_exists(response):
sys.stdout.write('%s,%s\n' % (target, vhost))
sys.stdout.flush()
# break out of the loop
attempt = max_attempts
def canary_exists(response):
if 200 <= response.status_code <= 299:
if canary == response.text:
return True
elif response.status_code == 301 or response.status_code == 302 \
or response.status_code == 303 or response.status_code == 307:
if canary == response.headers['location']:
return True
else:
if canary == response.status_code:
return True
return False
def obtain_canary():
canary = None
# Attempt to request target, use response as a canary
max_attempts = 3
attempt = 0
while attempt < max_attempts:
try:
response = curl.request(method='GET', url=target)
if 200 <= response.status_code <= 299:
canary = response.text
elif response.status_code == 301 or response.status_code == 302 \
or response.status_code == 303 or response.status_code == 307:
canary = response.headers['location']
else:
canary = response.status_code
except:
#import traceback
#traceback.print_exc()
attempt += 1
if attempt == max_attempts:
sys.stderr.write('%s => Request timed out.\n' % (target))
continue
# break out of the loop
attempt = max_attempts
return canary
def initializer():
"""Ignore CTRL+C in the worker process."""
signal.signal(signal.SIGINT, signal.SIG_IGN)
########
# MAIN #
########
if __name__ == '__main__':
desc = 'Identify virtual hosts hosted by the target web server by setting different host ' \
'headers taken from the supplied list of hostnames.'
parser = argparse.ArgumentParser(description=desc)
parser.add_argument('file',
nargs='?',
type=argparse.FileType('r'),
action='store',
help='file containing a list of hostnames split by a newline, otherwise read from STDIN',
metavar='FILE',
default=sys.stdin)
required = parser.add_argument_group('required arguments')
required.add_argument('-t', '--target',
action='store',
help='target web server URL (http[s]://address:port)',
metavar='URL',
required=True)
args = parser.parse_args()
try:
vhosts = [line.strip() for line in args.file]
except KeyboardInterrupt:
exit()
global target
target = args.target
global canary
canary = obtain_canary()
if canary is None:
exit(1)
sys.stdout.write('%s,\n' % (target))
sys.stdout.flush()
# remove duplicates and sort
vhosts = list(set(vhosts))
vhosts = sorted(vhosts)
# https://www.binpress.com/tutorial/simple-python-parallelism/121
pool = Pool(processes=10, initializer=initializer)
try:
pool.map(brute_vhost, vhosts)
pool.close()
pool.join()
except KeyboardInterrupt:
pool.terminate()
pool.join()