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
- clone-cert: https://github.com/SySS-Research/clone-cert
- SAML Raider: https://github.com/CompassSecurity/SAMLRaider