Posted onEdited onInctfViews: Disqus: Word count in article: 872Reading time ≈3 mins.
Given many private keys, identify which one corresponds to a TLS
connection captured in a PCAP file.
Vulnerability
The TLS certificate in the handshake reveals the public key
(modulus). By comparing the public key's modulus with all available
private keys, the correct one can be identified.
❯ sudo python scrapy2.py Ether / IP / TCP 172.17.0.3:39618 > 172.17.0.2:pcsync_https S Ether / IP / TCP 172.17.0.2:pcsync_https > 172.17.0.3:39618 SA Ether / IP / TCP 172.17.0.3:39618 > 172.17.0.2:pcsync_https A Ether / IP / TCP 172.17.0.3:39618 > 172.17.0.2:pcsync_https PA / Raw Ether / IP / TCP 172.17.0.2:pcsync_https > 172.17.0.3:39618 A Ether / IP / TCP 172.17.0.2:pcsync_https > 172.17.0.3:39618 PA / Raw Ether / IP / TCP 172.17.0.3:39618 > 172.17.0.2:pcsync_https A Ether / IP / TCP 172.17.0.3:39618 > 172.17.0.2:pcsync_https PA / Raw Ether / IP / TCP 172.17.0.2:pcsync_https > 172.17.0.3:39618 PA / Raw Ether / IP / TCP 172.17.0.3:39618 > 172.17.0.2:pcsync_https PA / Raw Ether / IP / TCP 172.17.0.2:pcsync_https > 172.17.0.3:39618 PA / Raw Ether / IP / TCP 172.17.0.3:39618 > 172.17.0.2:pcsync_https PA / Raw Ether / IP / TCP 172.17.0.2:pcsync_https > 172.17.0.3:39618 FA Ether / IP / TCP 172.17.0.3:39618 > 172.17.0.2:pcsync_https FA Ether / IP / TCP 172.17.0.2:pcsync_https > 172.17.0.3:39618 A None
In the TLSv1.2 handshake, the server sends its X.509 certificate
containing the RSA public key. In RSA, the public and private keys share
the same modulus (N).
from cryptography import x509 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey from scapy import dadict from scapy.allimport * from scapy.allimport Raw, load_layer, rdpcap from scapy.layers.inet import IP, TCP from scapy.layers.tls.allimport TLS from scapy.layers.tls.cert import Cert from scapy.layers.tls.handshake import TLSCertificate
for pkt in packets: if pkt.haslayer(Raw): raw = pkt[Raw].load try: tls_parsed = TLS(raw) tls_cert_layer = tls_parsed.getlayer(TLSCertificate) if tls_cert_layer: print("[-] Found TLS Certificate.") cert = tls_cert_layer.certs for _, x509_wrapper in cert: cert_list.append(x509_wrapper) print("[-] Extracted a TLS Certificate.") else: print("[-] Found TLS packet.") except Exception as e: print(f"[-] Error: {e}") continue return cert_list
deffind_matching_private_key(target_modulus: int, keys_directory: str) -> str | None: print(f"[*] Searching for matching private key in {keys_directory} ...")
for key_file in glob(os.path.join(keys_directory, "*")): try: withopen(key_file, "rb") as f: private_key = serialization.load_pem_private_key( f.read(), password=None, backend=default_backend() )