From 0169271bf993aa16b4d5627eda8523552661d7ef Mon Sep 17 00:00:00 2001 From: ikoz Date: Wed, 2 Mar 2016 15:23:33 +0000 Subject: New option: Add server certs to client chain If enabled, append all server certificates to the certificate chain served to the client, as extras. Can be used to bypass certain certificate pinning impementations. --- mitmproxy/cmdline.py | 6 ++++++ mitmproxy/protocol/tls.py | 6 ++++++ mitmproxy/proxy/config.py | 5 ++++- netlib/tcp.py | 10 ++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/mitmproxy/cmdline.py b/mitmproxy/cmdline.py index b1b860f8..a04a36ba 100644 --- a/mitmproxy/cmdline.py +++ b/mitmproxy/cmdline.py @@ -434,6 +434,12 @@ def proxy_ssl_options(parser): action="store_true", dest="no_upstream_cert", help="Don't connect to upstream server to look up certificate details." ) + group.add_argument( + "--add-server-certs-to-client-chain", default=False, + action="store_true", dest="add_server_certs_to_client_chain", + help="Add all the certificates of the server to the certificate chain " + "that will be served to the client, as extras." + ) group.add_argument( "--verify-upstream-cert", default=False, action="store_true", dest="ssl_verify_upstream_cert", diff --git a/mitmproxy/protocol/tls.py b/mitmproxy/protocol/tls.py index 6913396d..22ee8ff9 100644 --- a/mitmproxy/protocol/tls.py +++ b/mitmproxy/protocol/tls.py @@ -432,6 +432,11 @@ class TlsLayer(Layer): self.log("Establish TLS with client", "debug") cert, key, chain_file = self._find_cert() + if self.config.add_server_certs_to_client_chain: + extra_certs = self.server_conn.server_certs + else: + extra_certs = None + try: self.client_conn.convert_to_ssl( cert, key, @@ -441,6 +446,7 @@ class TlsLayer(Layer): dhparams=self.config.certstore.dhparams, chain_file=chain_file, alpn_select_callback=self.__alpn_select_callback, + extra_chain_certs = extra_certs, ) # Some TLS clients will not fail the handshake, # but will immediately throw an "unexpected eof" error on the first read. diff --git a/mitmproxy/proxy/config.py b/mitmproxy/proxy/config.py index 149d4710..9932ec8c 100644 --- a/mitmproxy/proxy/config.py +++ b/mitmproxy/proxy/config.py @@ -67,6 +67,7 @@ class ProxyConfig: ssl_verify_upstream_cert=False, ssl_verify_upstream_trusted_cadir=None, ssl_verify_upstream_trusted_ca=None, + add_server_certs_to_client_chain=False, ): self.host = host self.port = port @@ -107,6 +108,7 @@ class ProxyConfig: self.openssl_verification_mode_server = SSL.VERIFY_NONE self.openssl_trusted_cadir_server = ssl_verify_upstream_trusted_cadir self.openssl_trusted_ca_server = ssl_verify_upstream_trusted_ca + self.add_server_certs_to_client_chain = add_server_certs_to_client_chain def process_proxy_options(parser, options): @@ -206,5 +208,6 @@ def process_proxy_options(parser, options): ssl_version_server=options.ssl_version_server, ssl_verify_upstream_cert=options.ssl_verify_upstream_cert, ssl_verify_upstream_trusted_cadir=options.ssl_verify_upstream_trusted_cadir, - ssl_verify_upstream_trusted_ca=options.ssl_verify_upstream_trusted_ca + ssl_verify_upstream_trusted_ca=options.ssl_verify_upstream_trusted_ca, + add_server_certs_to_client_chain=options.add_server_certs_to_client_chain, ) diff --git a/netlib/tcp.py b/netlib/tcp.py index 6423888a..68a71270 100644 --- a/netlib/tcp.py +++ b/netlib/tcp.py @@ -584,6 +584,7 @@ class TCPClient(_Connection): self.address = address self.source_address = source_address self.cert = None + self.server_certs = [] self.ssl_verification_error = None self.sni = None @@ -668,6 +669,10 @@ class TCPClient(_Connection): self.cert = certutils.SSLCert(self.connection.get_peer_certificate()) + # Keep all server certificates in a list + for i in self.connection.get_peer_cert_chain(): + self.server_certs.append(certutils.SSLCert(i)) + # Validate TLS Hostname try: crt = dict( @@ -734,6 +739,7 @@ class BaseHandler(_Connection): request_client_cert=None, chain_file=None, dhparams=None, + extra_chain_certs=None, **sslctx_kwargs): """ cert: A certutils.SSLCert object or the path to a certificate @@ -769,6 +775,10 @@ class BaseHandler(_Connection): else: context.use_certificate_chain_file(cert) + if extra_chain_certs: + for i in extra_chain_certs: + context.add_extra_chain_cert(i.x509) + if handle_sni: # SNI callback happens during do_handshake() context.set_tlsext_servername_callback(handle_sni) -- cgit v1.2.3