tintinweb / scapy-ssl_tls

SSL/TLS layers for scapy the interactive packet manipulation tool
GNU General Public License v2.0
419 stars 156 forks source link

Decoding Scapy ASN1 encoded SSL/TLS certificate fields #116

Closed xer0xe9 closed 6 years ago

xer0xe9 commented 6 years ago

hello, I am extracting SSL/TLS certificate fields from serverhello packet using scapy-ssl_tls library which I installed using pip.

The problem is, I'm not able to figure out a way to extract values from ASN1 encoded fields:

sign_algo2:  <ASN1_OID['.1.2.840.113549.1.1.11']>
sa2_value:  <ASN1_NULL[0L]>
not_before:  <ASN1_UTC_TIME['170321131500Z']>
not_after:  <ASN1_UTC_TIME['200321131500Z']>
pubkey_algo:  <ASN1_OID['.1.2.840.113549.1.1.1']>
version:  <ASN1_INTEGER[2L]>
sn:  <ASN1_INTEGER[6348220899422160075L]>
sign_algo:  <ASN1_OID['.1.2.840.113549.1.1.11']>
pubkey:  <ASN1_BIT_STRING['\x000\x']>

I've dug out scapy.layers.ssl_tls, ssl_tls_crypto, scapy.layers.x509 modules but couldn't get any hint to decode it. I also tried using Asn1Value.load() from asn1crypto.core package but it fails with following error:

TypeError: encoded_data must be a byte string, not scapy.asn1.asn1.ASN1_UTC_TIME

It'd be great if anyone could help me getting this resolved using scapy's native decoding preferably or any other way possible.

Note: Please note that I've to extract these values from SSL/TLS serverhello packets which I'm reading from a pcap file as I need other fields from packet headers as well. I know many solutions exist on stackoverflow or wireshark/tshark for extracting/reading certificates from .pem files or possibly from .der files (after having it exported from wireshark explicitly), they don't work in my case as I need a solution which works around extracting certificates or certificate fields from packets.

tintinweb commented 6 years ago

Hi @precociouss,

We're using standard scapy X509v3 and they're built with scapy ASN1 fields. Here're some examples on how to use them with scapy-ssl_tls.

//based on examples/client_hello_rsa.py // if you want to play around with it, add a sys.argv=[];interact() at the end to get an interactive shell

...
# resp holds the raw socket response to a client_hello

tls_response = TLS(resp)
tls_response.show()  # show the structure

# iterate all certificates
for cert in tls_response[TLSCertificateList].payload.certificates:
    # .payload as the structure is [...][TLSCertificateList][TLS10Certificate].certificates = [x509Cert,x509Cert,...]
    # we'll have a TLSCertificateList object at this point; get the scapy X509Cert Object
    tlscert = cert[X509Cert]
    print repr(str(tlscert.sign_algo)) # raw bytes -> '\x06\t*\x86H\x86\xf7\r\x01\x01\x0b'
    print repr(tlscert.sign_algo) # <ASN1_OID['.1.2.840.113549.1.1.11']>
    print tlscert.sign_algo.val # 1.2.840.113549.1.1.11
    print repr(tlscert.version) # <ASN1_INTEGER[2L]>
    print tlscert.version.val # 2

Hope that helps.

cheers, tin

xer0xe9 commented 6 years ago

Hi tin,

Thanks for help, pretty much done with it, just wanted to clear one more point: I can't seem to find a way to identify what algorithms are being used in this case:

sign_algo: 1.2.840.113549.1.1.11 pubkey_algo: 1.2.840.113549.1.1.1

How it is supposed to be done? Thanks!

tintinweb commented 6 years ago

Hi @precociouss,

the algorithm object identifiers (OID) are defined in the corresponding rfc's 3279, 3370 (and others...). Someone was also so kind and created a brief summary of OIDs.

cheers, tin