improving certificate parsing

https://github.com/projectdiscovery/httpx/issues/221
This commit is contained in:
Mzack9999 2021-04-09 16:12:01 +02:00 committed by sandeep
parent 2bcaa9c24f
commit d7fb3384fe

View File

@ -1,32 +1,111 @@
package httpx
import (
"bytes"
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"encoding/hex"
"errors"
"fmt"
"net/http"
)
// TLSData contains the relevant Transport Layer Security information
type TLSData struct {
DNSNames []string `json:"dns_names,omitempty"`
Emails []string `json:"emails,omitempty"`
CommonName []string `json:"common_name,omitempty"`
Organization []string `json:"organization,omitempty"`
IssuerCommonName []string `json:"issuer_common_name,omitempty"`
IssuerOrg []string `json:"issuer_organization,omitempty"`
TLSVersion string `json:"tls_version,omitempty"`
CipherSuite string `json:"cipher_suite,omitempty"`
NegotiatedProtocol string `json:"negotiated_protocol,omitempty"`
ExtensionServerName string `json:"extension_server_name,omitempty"`
OCSPResponse []byte `json:"ocsp_response,omitempty"`
DNSNames []string `json:"dns_names,omitempty"`
Emails []string `json:"emails,omitempty"`
CommonName []string `json:"common_name,omitempty"`
Organization []string `json:"organization,omitempty"`
IssuerCommonName []string `json:"issuer_common_name,omitempty"`
IssuerOrg []string `json:"issuer_organization,omitempty"`
FingerprintMD5 string `json:"fingerprint_md5,omitempty"`
FingerprintSHA1 string `json:"fingerprint_sha1,omitempty"`
FingerprintSHA256 string `json:"fingerprint_sha256,omitempty"`
FingerprintMD5OpenSSL string `json:"fingerprint_md5_openssl,omitempty"`
FingerprintSHA1OpenSSL string `json:"fingerprint_sha1_openssl,omitempty"`
FingerprintSHA256OpenSSL string `json:"fingerprint_sha256_openssl,omitempty"`
RawCertificateChain []*x509.Certificate `json:"raw_certificate_chain,omitempty"`
}
// TLSGrab fills the TLSData
func (h *HTTPX) TLSGrab(r *http.Response) *TLSData {
if r.TLS != nil {
var tlsdata TLSData
for _, certificate := range r.TLS.PeerCertificates {
tlsdata.DNSNames = append(tlsdata.DNSNames, certificate.DNSNames...)
tlsdata.Emails = append(tlsdata.Emails, certificate.EmailAddresses...)
tlsdata.CommonName = append(tlsdata.CommonName, certificate.Subject.CommonName)
tlsdata.Organization = append(tlsdata.Organization, certificate.Subject.Organization...)
tlsdata.IssuerOrg = append(tlsdata.IssuerOrg, certificate.Issuer.Organization...)
tlsdata.IssuerCommonName = append(tlsdata.IssuerCommonName, certificate.Issuer.CommonName)
// Only PeerCertificates[0] contains useful information
cert := r.TLS.PeerCertificates[0]
tlsdata.DNSNames = append(tlsdata.DNSNames, cert.DNSNames...)
tlsdata.Emails = append(tlsdata.Emails, cert.EmailAddresses...)
tlsdata.CommonName = append(tlsdata.CommonName, cert.Subject.CommonName)
tlsdata.Organization = append(tlsdata.Organization, cert.Subject.Organization...)
tlsdata.IssuerOrg = append(tlsdata.IssuerOrg, cert.Issuer.Organization...)
tlsdata.IssuerCommonName = append(tlsdata.IssuerCommonName, cert.Issuer.CommonName)
tlsdata.CipherSuite = tls.CipherSuiteName(r.TLS.CipherSuite)
tlsdata.NegotiatedProtocol = r.TLS.NegotiatedProtocol
tlsdata.ExtensionServerName = r.TLS.ServerName
tlsdata.OCSPResponse = r.TLS.OCSPResponse
if v, ok := tlsVersionStringMap[r.TLS.Version]; ok {
tlsdata.TLSVersion = v
}
if fingerprintMD5, fingerprintSHA1, fingerprintSHA256, err := calculatFingerprints(r); err == nil {
tlsdata.FingerprintMD5 = asHex(fingerprintMD5)
tlsdata.FingerprintSHA1 = asHex(fingerprintSHA1)
tlsdata.FingerprintSHA256 = asHex(fingerprintSHA256)
tlsdata.FingerprintMD5OpenSSL = asOpenSSL(fingerprintMD5)
tlsdata.FingerprintSHA1OpenSSL = asOpenSSL(fingerprintSHA1)
tlsdata.FingerprintSHA256OpenSSL = asOpenSSL(fingerprintSHA256)
}
tlsdata.RawCertificateChain = r.TLS.PeerCertificates
return &tlsdata
}
return nil
}
var tlsVersionStringMap = map[uint16]string{
0x0300: "SSL30",
0x0301: "TLS10",
0x0302: "TLS11",
0x0303: "TLS12",
0x0304: "TLS13",
}
func calculatFingerprints(r *http.Response) (fingerprintMD5, fingerprintSHA1, fingerprintSHA256 []byte, err error) {
if len(r.TLS.PeerCertificates) == 0 {
err = errors.New("no certificates found")
return
}
cert := r.TLS.PeerCertificates[0]
dataMD5 := md5.Sum(cert.Raw)
fingerprintMD5 = dataMD5[:]
dataSHA1 := sha1.Sum(cert.Raw)
fingerprintSHA1 = dataSHA1[:]
dataSHA256 := sha256.Sum256(cert.Raw)
fingerprintSHA256 = dataSHA256[:]
return
}
func asOpenSSL(b []byte) string {
var buf bytes.Buffer
for i, f := range b {
if i > 0 {
fmt.Fprintf(&buf, ":")
}
fmt.Fprintf(&buf, "%02X", f)
}
return buf.String()
}
func asHex(b []byte) string {
return hex.EncodeToString(b)
}