Less obvious fake TLS certificate generation

This patch adds the following:
 * Pre-defined CA certificate subjects
 * Pre-defined popular website domain names
 * Fake certificate generation for pre-defined popular website domain signed by fake CA with pre-defined subject

It should look less suspicious than "example.com" certificates
This commit is contained in:
ValdikSS 2019-03-19 18:09:13 +03:00
parent 116347ef66
commit f66cfc9a5e
2 changed files with 104 additions and 26 deletions

View file

@ -3,6 +3,7 @@ import logging
import os import os
import ssl import ssl
import hashlib import hashlib
import random
from Config import config from Config import config
from util import SslPatch from util import SslPatch
@ -11,6 +12,7 @@ from util import helper
class CryptConnectionManager: class CryptConnectionManager:
def __init__(self): def __init__(self):
# TODO: UGLY UGLY UGLY
# OpenSSL params # OpenSSL params
if sys.platform.startswith("win"): if sys.platform.startswith("win"):
self.openssl_bin = "src\\lib\\opensslVerify\\openssl.exe" self.openssl_bin = "src\\lib\\opensslVerify\\openssl.exe"
@ -19,6 +21,11 @@ class CryptConnectionManager:
self.openssl_env = {"OPENSSL_CONF": "src/lib/opensslVerify/openssl.cnf"} self.openssl_env = {"OPENSSL_CONF": "src/lib/opensslVerify/openssl.cnf"}
self.crypt_supported = [] # Supported cryptos self.crypt_supported = [] # Supported cryptos
self.cacert_pem = config.data_dir+"/cacert-rsa.pem"
self.cakey_pem = config.data_dir+"/cakey-rsa.pem"
self.cert_pem = config.data_dir+"/cert-rsa.pem"
self.cert_csr = config.data_dir+"/cert-rsa.csr"
self.key_pem = config.data_dir+"/key-rsa.pem"
# Select crypt that supported by both sides # Select crypt that supported by both sides
# Return: Name of the crypto # Return: Name of the crypto
@ -36,8 +43,8 @@ class CryptConnectionManager:
ciphers += "!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK" ciphers += "!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK"
if server: if server:
sock_wrapped = ssl.wrap_socket( sock_wrapped = ssl.wrap_socket(
sock, server_side=server, keyfile='%s/key-rsa.pem' % config.data_dir, sock, server_side=server, keyfile=self.key_pem,
certfile='%s/cert-rsa.pem' % config.data_dir, ciphers=ciphers) certfile=self.cert_pem, ciphers=ciphers)
else: else:
sock_wrapped = ssl.wrap_socket(sock, ciphers=ciphers) sock_wrapped = ssl.wrap_socket(sock, ciphers=ciphers)
if cert_pin: if cert_pin:
@ -50,7 +57,7 @@ class CryptConnectionManager:
def removeCerts(self): def removeCerts(self):
if config.keep_ssl_cert: if config.keep_ssl_cert:
return False return False
for file_name in ["cert-rsa.pem", "key-rsa.pem"]: for file_name in ["cert-rsa.pem", "key-rsa.pem", "cacert-rsa.pem", "cakey-rsa.pem", "cert-rsa.csr"]:
file_path = "%s/%s" % (config.data_dir, file_name) file_path = "%s/%s" % (config.data_dir, file_name)
if os.path.isfile(file_path): if os.path.isfile(file_path):
os.unlink(file_path) os.unlink(file_path)
@ -66,15 +73,60 @@ class CryptConnectionManager:
# Try to create RSA server cert + sign for connection encryption # Try to create RSA server cert + sign for connection encryption
# Return: True on success # Return: True on success
def createSslRsaCert(self): def createSslRsaCert(self):
if os.path.isfile("%s/cert-rsa.pem" % config.data_dir) and os.path.isfile("%s/key-rsa.pem" % config.data_dir): casubjects = [
"/C=US/O=Amazon/OU=Server CA 1B/CN=Amazon",
"/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3",
"/C=US/O=DigiCert Inc/OU=www.digicert.com/CN = DigiCert SHA2 High Assurance Server CA",
"/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN = COMODO RSA Domain Validation Secure Server CA"
]
fakedomains = [
"yahoo.com",
"amazon.com",
"live.com",
"microsoft.com",
"mail.ru",
"csdn.net",
"bing.com",
"amazon.co.jp",
"office.com",
"imdb.com",
"msn.com",
"samsung.com",
"huawei.com",
"ztedevices.com",
"godaddy.com",
"w3.org",
"gravatar.com",
"creativecommons.org",
"hatena.ne.jp",
"adobe.com",
"opera.com",
"apache.org",
"rambler.ru",
"one.com",
"nationalgeographic.com",
"networksolutions.com",
"php.net",
"python.org",
"phoca.cz",
"debian.org",
"ubuntu.com",
"nazwa.pl",
"symantec.com"
]
self.openssl_env['CN'] = random.choice(fakedomains)
if os.path.isfile(self.cert_pem) and os.path.isfile(self.key_pem):
return True # Files already exits return True # Files already exits
import subprocess import subprocess
cmd = "%s req -x509 -newkey rsa:2048 -sha256 -batch -keyout %s -out %s -nodes -config %s" % helper.shellquote( # Generate CAcert and CAkey
cmd = "%s req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj %s -keyout %s -out %s -batch -config %s" % helper.shellquote(
self.openssl_bin, self.openssl_bin,
config.data_dir+"/key-rsa.pem", random.choice(casubjects),
config.data_dir+"/cert-rsa.pem", self.cakey_pem,
self.openssl_env["OPENSSL_CONF"] self.cacert_pem,
self.openssl_env["OPENSSL_CONF"],
) )
proc = subprocess.Popen( proc = subprocess.Popen(
cmd.encode(sys.getfilesystemencoding()), cmd.encode(sys.getfilesystemencoding()),
@ -82,9 +134,46 @@ class CryptConnectionManager:
) )
back = proc.stdout.read().strip() back = proc.stdout.read().strip()
proc.wait() proc.wait()
logging.debug("Generating RSA cert and key PEM files...%s" % back) logging.debug("Generating RSA CAcert and CAkey PEM files...%s" % back)
if os.path.isfile("%s/cert-rsa.pem" % config.data_dir) and os.path.isfile("%s/key-rsa.pem" % config.data_dir): if not (os.path.isfile(self.cacert_pem) and os.path.isfile(self.cakey_pem)):
logging.error("RSA ECC SSL CAcert generation failed, CAcert or CAkey files not exist.")
return False
# Generate certificate key and signing request
cmd = "%s req -new -newkey rsa:2048 -keyout %s -out %s -subj %s -sha256 -nodes -batch -config %s" % helper.shellquote(
self.openssl_bin,
self.key_pem,
self.cert_csr,
"/CN="+self.openssl_env['CN'],
self.openssl_env["OPENSSL_CONF"],
)
proc = subprocess.Popen(
cmd.encode(sys.getfilesystemencoding()),
shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, env=self.openssl_env
)
back = proc.stdout.read().strip()
proc.wait()
logging.debug("Generating certificate key and signing request...%s" % back)
# Sign request and generate certificate
cmd = "%s x509 -req -in %s -CA %s -CAkey %s -CAcreateserial -out %s -days 730 -sha256 -extensions x509_ext -extfile %s" % helper.shellquote(
self.openssl_bin,
self.cert_csr,
self.cacert_pem,
self.cakey_pem,
self.cert_pem,
self.openssl_env["OPENSSL_CONF"],
)
proc = subprocess.Popen(
cmd.encode(sys.getfilesystemencoding()),
shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, env=self.openssl_env
)
back = proc.stdout.read().strip()
proc.wait()
logging.debug("Generating RSA cert...%s" % back)
if os.path.isfile(self.cert_pem) and os.path.isfile(self.key_pem):
return True return True
else: else:
logging.error("RSA ECC SSL cert generation failed, cert or key files not exist.") logging.error("RSA ECC SSL cert generation failed, cert or key files not exist.")

View file

@ -1,5 +1,5 @@
[ req ] [ req ]
prompt = no prompt = yes
default_bits = 2048 default_bits = 2048
default_keyfile = server-key.pem default_keyfile = server-key.pem
distinguished_name = subject distinguished_name = subject
@ -32,8 +32,8 @@ authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
subjectAltName = @alternate_names subjectAltName = @alternate_names
nsComment = "OpenSSL Generated Certificate"
# RFC 5280, Section 4.2.1.12 makes EKU optional # RFC 5280, Section 4.2.1.12 makes EKU optional
# CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused # CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
@ -46,8 +46,8 @@ subjectKeyIdentifier = hash
basicConstraints = CA:FALSE basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
subjectAltName = @alternate_names subjectAltName = @alternate_names
nsComment = "OpenSSL Generated Certificate"
# RFC 5280, Section 4.2.1.12 makes EKU optional # RFC 5280, Section 4.2.1.12 makes EKU optional
# CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused # CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
@ -55,16 +55,5 @@ nsComment = "OpenSSL Generated Certificate"
[ alternate_names ] [ alternate_names ]
DNS.1 = example.com DNS.1 = $ENV::CN
DNS.2 = www.example.com DNS.2 = www.$ENV::CN
DNS.3 = mail.example.com
DNS.4 = ftp.example.com
# Add these if you need them. But usually you don't want them or
# need them in production. You may need them for development.
# DNS.5 = localhost
# DNS.6 = localhost.localdomain
# DNS.7 = 127.0.0.1
# IPv6 localhost
# DNS.8 = ::1