I'm attempting to connect to a transparent Burp proxy using async-native-tls
. The way the transparent Burp proxy works is that it generates a new TLS cert based on the SNI parameter of incoming TLS connections on the fly. These TLS certs it generates are all signed by a Burp CA.
When I run my code, I get an error from OpenSSL complaining about a self-signed certificate in the chain. That's totally expected. In fact, all TLS certificate chains have a self-signed certificate in the path -- the CA! I believe I've correctly configured the Burp CA certificate as an alternative to the system CA.
Below are the relevant snippets.
use async_native_tls::{Certificate, TlsConnector};
use http_client::hyper::HyperClient;
use http_client::{hyper, Config, HttpClient, Request};
use std::error::Error;
use std::sync::Arc;
let mut tls_builder = native_tls::TlsConnector::builder();
tls_builder
// This is important, as it's how Burp knows which certificate to present
.use_sni(true)
// This is important, as it indicates that Burp's CA should be trusted
.add_root_certificate(Certificate::from_pem(
std::fs::read("/tmp/ca.pem")?.as_slice(),
)?)
// These should not be required, but I've turned them on in despairation
.danger_accept_invalid_hostnames(true)
.danger_accept_invalid_certs(true)
.disable_built_in_roots(true)
.max_protocol_version(None)
.min_protocol_version(None);
let burp_proxy_tls = TlsConnector::from(tls_builder);
let burp_proxy_config = Config::default().set_tls_config(Some(Arc::new(burp_proxy_tls)));
let mut http_client = HyperClient::new();
http_client.set_config(burp_proxy_config)?;
let mut request = Request::get("https://127.0.0.1:8000/...");
request.append_header("Cookie", "...");
// Not strictly needed since it's also in SNI
request.append_header("Host", "...");
let mut response = http_client.send(request).await?;
When I connect via s_client
, everything verifies OK:
$ openssl s_client -connect 127.0.0.1:8000 \
-servername www......com \
-CAfile /tmp/ca.pem \
</dev/null
CONNECTED(00000003)
depth=1 C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA
verify return:1
depth=0 C = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = www......com
verify return:1
---
Certificate chain
0 s:C = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = www........com
i:C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Jan 10 02:29:14 2023 GMT; NotAfter: Jan 10 02:29:14 2024 GMT
1 s:C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA
i:C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Jan 24 00:53:54 2014 GMT; NotAfter: Jan 24 00:53:54 2033 GMT
...
subject=C = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = www.......com
issuer=C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 2521 bytes and written 403 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
DONE
But then the program fails:
$ cargo run
Finished dev [unoptimized debuginfo] target(s) in 0.15s
Running `target/debug/xxxxxx`
Error: error trying to connect: error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:1889: (self-signed certificate in certificate chain)
Caused by:
0: error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:1889: (self-signed certificate in certificate chain)
1: error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:1889:
CodePudding user response:
Well, I never did figure out if this was possible with the async-native-tls
library. I wasn't tied to that library so I switched to isahc
since it was backed by CURL and I know I can get that to do what I want.
I did have to switch my burp proxy to port 443 because isahc
doesn't support --connect-to
yet, but I can work with that.
let http_client = HttpClient::builder()
.dns_resolve(ResolveMap::new().add("www.......com", 443, [127, 0, 0, 1]))
.ssl_ca_certificate(CaCertificate::file("/tmp/ca.pem"))
.ssl_options(SslOption::DANGER_ACCEPT_INVALID_CERTS)
.automatic_decompression(true)
.build()?;
let request = Request::get("https://www.......com/....")
.header("Cookie", cookies)
.body(())?;
let mut response = http_client.send(request)?;