Skip to content

Commit

Permalink
Potential fix for web_spider sslv3 handshake failure #5802
Browse files Browse the repository at this point in the history
Still needs more testing
  • Loading branch information
andresriancho committed Oct 28, 2014
1 parent 53320d0 commit 4d3da21
Showing 1 changed file with 77 additions and 18 deletions.
95 changes: 77 additions & 18 deletions w3af/core/data/url/handlers/keepalive.py
Original file line number Diff line number Diff line change
Expand Up @@ -822,26 +822,28 @@ def __init__(self, host, port=None, strict=None,

class ProxyHTTPConnection(_HTTPConnection):
"""
this class is used to provide HTTPS CONNECT support.
This class is used to provide HTTPS CONNECT support.
"""
_ports = {'http': 80, 'https': 443}

def __init__(self, host, port=None, strict=None):
_HTTPConnection.__init__(self, host, port, strict)

def proxy_setup(self, url):
#request is called before connect, so can interpret url and get
#real host/port to be used to make CONNECT request to proxy
# request is called before connect, so can interpret url and get
# real host/port to be used to make CONNECT request to proxy
proto, rest = urllib.splittype(url)
if proto is None:
raise ValueError("unknown URL type: %s" % url)
#get host

# get host
host, rest = urllib.splithost(rest)
self._real_host = host

#try to get port
# try to get port
host, port = urllib.splitport(host)
#if port is not defined try to get from proto

# if port is not defined try to get from proto
if port is None:
try:
self._real_port = self._ports[proto]
Expand Down Expand Up @@ -871,24 +873,85 @@ def connect(self):
#expect a HTTP/1.0 200 Connection established
response = self.response_class(self.sock, strict=self.strict,
method=self._method)
(version, code, message) = response._read_status()
version, code, message = response._read_status()

#probably here we can handle auth requests...
if code != 200:
#proxy returned and error, abort connection, and raise exception
self.close()
raise socket.error("Proxy connection failed: %d %s" %
(code, message.strip()))
#eat up header block from proxy....

# eat up header block from proxy....
while True:
#should not use directly fp probably
line = response.fp.readline()
if line == '\r\n':
break


class ProxyHTTPSConnection(ProxyHTTPConnection):
_protocols = [ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23]


class SSLNegotiatorConnection(httplib.HTTPSConnection):
"""
Connection class that enables usage of newer SSL protocols.
References:
http://bugs.python.org/msg128686
https://github.com/andresriancho/w3af/issues/5802
https://gist.github.com/flandr/74be22d1c3d7c1dfefdd
"""
def __init__(self, *args, **kwargs):
httplib.HTTPSConnection.__init__(self, *args, **kwargs)

def connect(self):
self.connect_multi_ssl()

def connect_socket(self):
"""
:return: fresh TCP/IP connection
"""
sock = socket.create_connection((self.host, self.port), self.timeout)

if getattr(self, "_tunnel_host", None):
self.sock = sock
self._tunnel()

return sock

def connect_multi_ssl(self):
"""
Test the different SSL protocols
"""
for protocol in _protocols:
try:
sock = self.connect_socket()

ssl_sock = ssl.wrap_socket(sock,
self.key_file,
self.cert_file,
ssl_version=protocol)

if ssl_sock:
self.sock = ssl_sock
_protocols.remove(protocol)
_protocols.insert(0, protocol)
break
else:
sock.close()
except ssl.SSLError, ssl_exc:
msg = "SSL connection error occurred with protocol %s: '%s'"
debug(msg % (protocol, ssl_exc))

else:
msg = 'Unable to create a SSL connection using protocol: %s'
raise HTTPRequestException(msg % protocol)


class ProxyHTTPSConnection(ProxyHTTPConnection, SSLNegotiatorConnection):
"""
this class is used to provide HTTPS CONNECT support.
This class is used to provide HTTPS CONNECT support.
"""
default_port = 443

Expand All @@ -897,16 +960,12 @@ class ProxyHTTPSConnection(ProxyHTTPConnection):

def __init__(self, host, port=None, key_file=None, cert_file=None,
strict=None):
ProxyHTTPConnection.__init__(self, host, port)
ProxyHTTPConnection.__init__(self, host, port, strict=strict)
self.key_file = key_file
self.cert_file = cert_file

def connect(self):
def connect_socket(self):
ProxyHTTPConnection.connect(self)
#make the sock ssl-aware
ssl_sock_inst = ssl.wrap_socket(self.sock, self.key_file,
self.cert_file)
self.sock = ssl_sock_inst


def to_utf8_raw(unicode_or_str):
Expand All @@ -924,11 +983,11 @@ def __init__(self, host, port=None, strict=None):
_HTTPConnection.__init__(self, host, port, strict)


class HTTPSConnection(httplib.HTTPSConnection):
class HTTPSConnection(SSLNegotiatorConnection):
response_class = HTTPResponse

def __init__(self, host, port=None, key_file=None, cert_file=None,
strict=None):
httplib.HTTPSConnection.__init__(self, host, port, key_file, cert_file,
SSLNegotiatorConnection.__init__(self, host, port, key_file, cert_file,
strict)
self.is_fresh = True

0 comments on commit 4d3da21

Please sign in to comment.