Introduction

X.509 certificates are used to secure communications online by encrypting data and verifying identities, such as in HTTPS or VPNs. During penetration tests, it’s important to check if systems correctly handle cloned certificates. Cloned certificates are fake copies that look like real ones but aren’t properly signed by a trusted CA.

I wrote a simple python script called dollyx509 that creates clones of X.509 certificates.

Script and Usage

The script can be found on GitHub: dollyx509.

The usage is quite simple:

usage: dollyx509 [-h] -i inputcert -c outputcert -k outputkey [--inform {der,pem}] [--outform {der,pem}]

dollyx509

Clone X.509 certificates by reading a certificate and generating new key material.

Author: Emanuel Duss

options:
  -h, --help            show this help message and exit
  -i inputcert, --certin inputcert
                        Certificate to clone
  -c outputcert, --certout outputcert
                        Output file of cloned certificate
  -k outputkey, --keyout outputkey
                        Output file of generated private key
  --inform {der,pem}    Input format of certificate
  --outform {der,pem}   Output format of certificate/key

How it Works

The script is quite small and the following excerpt shows the magic:

class Certificate:
    def __init__(self, file, format='pem'):
        self.import_certificate(file, format)

    # [...]

    def import_certificate(self, file, format='pem'):
        with open(file, "r") as f:
            self.cert = OpenSSL.crypto.load_certificate(self.__get_filetype(format), f.read())

    # [...]

    def clone(self):
        self.key = OpenSSL.crypto.PKey()
        self.key.generate_key(self.cert.get_pubkey().type(), self.cert.get_pubkey().bits())
        self.cert.set_pubkey(self.key)
        self.cert.sign(self.key,'sha256')

This code reads the certificate from the provided file, creates new key material and self-signs the certificate.

Example Usage

We have the following certificate:

$ openssl x509 -in original.pem -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            03:d9:ef:8c:0b:37:dd:20:37:17:63:6a:5f:70:62:69:f5:2c
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=Let's Encrypt, CN=R3
        Validity
            Not Before: Aug 22 17:31:47 2023 GMT
            Not After : Nov 20 17:31:46 2023 GMT
        Subject: CN=emanuelduss.ch
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)
                Modulus:
                    00:bd:cb:b1:0e:13:08:1c:f0:37:f8:31:95:f9:33:
                    cf:3d:a7:b2:9a:01:04:2c:cb:43:fc:60:6c:cd:81:
                    [...]
                    60:93:bc:8b:84:d7:07:fc:de:45:08:e2:9d:37:50:
                    88:a2:43
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier: 
                09:6F:45:8A:00:A0:18:DB:CB:9A:38:00:81:B5:8F:08:B6:AF:A6:2F
            X509v3 Authority Key Identifier: 
                14:2E:B3:17:B7:58:56:CB:AE:50:09:40:E6:1F:AF:9D:8B:14:C2:C6
            Authority Information Access: 
                OCSP - URI:http://r3.o.lencr.org
                CA Issuers - URI:http://r3.i.lencr.org/
            X509v3 Subject Alternative Name: 
                DNS:*.emanuelduss.ch, DNS:emanuelduss.ch
            X509v3 Certificate Policies: 
                Policy: 2.23.140.1.2.1
            CT Precertificate SCTs: 
                Signed Certificate Timestamp:
                    Version   : v1 (0x0)
                    Log ID    : B7:3E:FB:24:DF:9C:4D:BA:75:F2:39:C5:BA:58:F4:6C:
                                5D:FC:42:CF:7A:9F:35:C4:9E:1D:09:81:25:ED:B4:99
                    Timestamp : Aug 22 18:31:47.483 2023 GMT
                    Extensions: none
                    Signature : ecdsa-with-SHA256
                                30:46:02:21:00:B1:45:75:03:81:F3:D0:23:E9:13:B2:
                                [...]
                                32:41:97:A5:6D:8F:5E:2F
                Signed Certificate Timestamp:
                    Version   : v1 (0x0)
                    Log ID    : AD:F7:BE:FA:7C:FF:10:C8:8B:9D:3D:9C:1E:3E:18:6A:
                                B4:67:29:5D:CF:B1:0C:24:CA:85:86:34:EB:DC:82:8A
                    Timestamp : Aug 22 18:31:47.555 2023 GMT
                    Extensions: none
                    Signature : ecdsa-with-SHA256
                                30:45:02:20:77:BF:35:D3:A3:B7:BB:6E:85:39:60:A4:
                                [...]
                                E6:8B:CA:EE:7C:B6:65
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        08:8b:68:29:d4:59:b4:58:d8:38:45:12:9b:67:ff:ca:9f:96:
        [...]
        35:96:44:1c

Note:

  • The subject is CN=emanuelduss.ch
  • The certificate was issued on Aug 22 17:31:47 2023 GMT
  • The modulus of the public key start with 00:bd:cb:b1
  • The signature starts with 08:8b:68:29

Cloning the certificate using dollyx509:

$ dollyx509 -i original.pem -c cloned.pem -k cloned.key 

The following files were created:

$ file cloned.key cloned.pem 
cloned.key: OpenSSH private key (no password)
cloned.pem: PEM certificate

The cloned certificate looks like this:

$ openssl x509 -in cloned.pem -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            03:d9:ef:8c:0b:37:dd:20:37:17:63:6a:5f:70:62:69:f5:2c
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=Let's Encrypt, CN=R3
        Validity
            Not Before: Aug 22 17:31:47 2023 GMT
            Not After : Nov 20 17:31:46 2023 GMT
        Subject: CN=emanuelduss.ch
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)
                Modulus:
                    00:a9:31:05:57:cc:95:5d:48:15:f1:cf:0f:12:2d:
                    47:c0:a0:64:3f:f5:ed:a0:de:8f:37:d2:d1:0f:1a:
                    [...]
                    66:29:ce:a6:a0:71:c3:12:8f:c3:dd:ec:63:26:31:
                    c1:21:9d
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier: 
                09:6F:45:8A:00:A0:18:DB:CB:9A:38:00:81:B5:8F:08:B6:AF:A6:2F
            X509v3 Authority Key Identifier: 
                14:2E:B3:17:B7:58:56:CB:AE:50:09:40:E6:1F:AF:9D:8B:14:C2:C6
            Authority Information Access: 
                OCSP - URI:http://r3.o.lencr.org
                CA Issuers - URI:http://r3.i.lencr.org/
            X509v3 Subject Alternative Name: 
                DNS:*.emanuelduss.ch, DNS:emanuelduss.ch
            X509v3 Certificate Policies: 
                Policy: 2.23.140.1.2.1
            CT Precertificate SCTs: 
                Signed Certificate Timestamp:
                    Version   : v1 (0x0)
                    Log ID    : B7:3E:FB:24:DF:9C:4D:BA:75:F2:39:C5:BA:58:F4:6C:
                                5D:FC:42:CF:7A:9F:35:C4:9E:1D:09:81:25:ED:B4:99
                    Timestamp : Aug 22 18:31:47.483 2023 GMT
                    Extensions: none
                    Signature : ecdsa-with-SHA256
                                30:46:02:21:00:B1:45:75:03:81:F3:D0:23:E9:13:B2:
                                [...]
                                32:41:97:A5:6D:8F:5E:2F
                Signed Certificate Timestamp:
                    Version   : v1 (0x0)
                    Log ID    : AD:F7:BE:FA:7C:FF:10:C8:8B:9D:3D:9C:1E:3E:18:6A:
                                B4:67:29:5D:CF:B1:0C:24:CA:85:86:34:EB:DC:82:8A
                    Timestamp : Aug 22 18:31:47.555 2023 GMT
                    Extensions: none
                    Signature : ecdsa-with-SHA256
                                30:45:02:20:77:BF:35:D3:A3:B7:BB:6E:85:39:60:A4:
                                [..]
                                E6:8B:CA:EE:7C:B6:65
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        7e:1f:26:b4:af:b9:a4:45:a1:1c:43:0f:4d:e8:28:a4:3c:65:
        8c:54:46:f2:e0:3f:b5:97:cf:66:cc:4e:62:e1:77:e2:45:68:
        [...]
        c6:10:88:c3:e5:9d:56:03:06:85:13:16:04:4a:ad:4e:49:23:
        61:18:42:88:8d:bf:6b:90

Note:

  • The subject is still the same: CN=emanuelduss.ch
  • The certificate issued date is still the same: Aug 22 17:31:47 2023 GMT
  • The modulus of the public key has changed and starts now with 00:a9:31:05
  • The signature value has changed and starts now with 7e:1f:26:b4

So, basically everything is exactly the same except the public key and signature.

This can also be seen when the two certificates are compared, e.g. using vimdiff:

vimdiff <(openssl x509 -in original.pem -noout -text) <(openssl x509 -in cloned.pem -noout -text)

Only the public key and signature has changed:

These cloned certificates can now be used to test if the involved systems correctly verify the signature.

Alternatives

There is another nice bash script which can also be used to clone certificates: clone-cert.

The Burp Suite extension SAML Raider has also the ability to clone certificates. In addition, it can also be used to change the properties of the certificates to other values: SAML Raider.

References