From 0169271bf993aa16b4d5627eda8523552661d7ef Mon Sep 17 00:00:00 2001 From: ikoz Date: Wed, 2 Mar 2016 15:23:33 +0000 Subject: [PATCH] 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 b1b860f83..a04a36ba7 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 6913396d5..22ee8ff98 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 149d47105..9932ec8c0 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 6423888a1..68a712702 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)