Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make installing certificates easier. #11

Closed
synchronizing opened this issue Feb 8, 2022 · 11 comments
Closed

Make installing certificates easier. #11

synchronizing opened this issue Feb 8, 2022 · 11 comments
Assignees
Labels
enhancement New feature or request

Comments

@synchronizing
Copy link
Owner

A few issues/discussion posts have been opened regarding mitm's certificates & and its use with Chrome. It would be a nice addition to have an easy method for installing certificates on different machines.

@synchronizing synchronizing added the enhancement New feature or request label Feb 8, 2022
@synchronizing synchronizing self-assigned this Feb 8, 2022
@flikhamud45
Copy link

Hi, when do you think will you find time to work on this? I can help you qif you want.

@synchronizing
Copy link
Owner Author

Hey @flikhamud45 - I'm working on this currently. I'll reach out back in here as soon as I need testers that are using Windows. Thank you for offering!

@flikhamud45
Copy link

flikhamud45 commented Apr 19, 2022

Hi,
I had time to work on that a little (because i needed this for my project), so i have made the following changes so it changes the common name of the certificate for each new website (and installs it to the os):

i have changed the new_pair function so it takes the host name for the cn:

async def new_pair(
    host: str,
    key_path: Optional[pathlib.Path] = None,
    cert_path: Optional[pathlib.Path] = None,
) -> Tuple[bytes, bytes]:
    """
    Generates an RSA and self-signed X509 certificate for use with TLS/SSL.

    The X509 certificate is self-signed and is not signed by any other certificate
    authority, containing default values for its fields.

    Args:
        key_path: Optional path to save key.
        cert_path: Optional path to save cert.

    Returns:
        tuple: Key and certificate bytes ready to be saved.
    """
    rsa = new_RSA()
    cert = new_X509(common_name=host, organization_name="oops", organization_unit_name="oops")
    # Sets the certificate public key, and signs it.
    cert.set_pubkey(rsa)
    cert.sign(rsa, "sha256")
    # Dumps the .crt and .key files as bytes.
    key = cry.dump_privatekey(cry.FILETYPE_PEM, rsa)
    crt = cry.dump_certificate(cry.FILETYPE_PEM, cert)
    # Stores they .crt and .key file if specified.
    if key_path:
        key_path.parent.mkdir(parents=True, exist_ok=True)
        with key_path.open("wb") as file:
            file.write(key)
    if cert_path:
        cert_path.parent.mkdir(parents=True, exist_ok=True)
        with cert_path.open("wb") as file:
            file.write(crt)
    return key, crt

i have made a new function to build the context instead of the function "mitm_ssl_default_context":

async def create_crypto(host: str) -> ssl.SSLContext:
    rsa_key, rsa_cert = __data__ / f"{host}.key", __data__ / f"{host}.crt"
    await new_pair(host, key_path=rsa_key, cert_path=rsa_cert)
    context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
    context.load_cert_chain(certfile=rsa_cert, keyfile=rsa_key)
    print(rsa_cert)
    install_cert(rsa_cert)
    return context

than i added a Middleware class that changes the new cetificate every time a new connection is made.

class Https_Middleware(middleware.Middleware):
    async def mitm_started(host: str, port: int):
        self.installed_hosts = {}

    async def client_data(connection: Connection, data: bytes) -> bytes:
        file.write("Client to server: \n\n\t%s\n" % data)
        await self.start_connection(connection, data)
        return data

    async def start_connection(connection: Connection, data):
        if b"CONNECT" in data:
            host = str(data[data.find(b" ")+1: data.find(b":")])[2:-1]
        else:
            return
        if host not in self.installed_hosts:
            context = await create_crypto(host)
            self.installed_hosts[host] = context
        connection.ssl_context = installed_hosts[host]

Tell me waht you think.

@mitch0s
Copy link

mitch0s commented Apr 21, 2022

Haven't read too much into this, but does it work similar to how CloudFlare's" Client to CF only" encryption? If so, and it works, that's awesome...

@flikhamud45
Copy link

I am not sure how CloudFlare works but I actually have just realized some problems with code I posted. I needed to make a root certificate first ans than sighn all the others with the sighn root certificate. I will make the necessary changes and post the corrected one.

@flikhamud45
Copy link

if someone wants, i have created a middleware class that inplements the certificates instaling and creatinf for https

@mitch0s
Copy link

mitch0s commented May 3, 2022

@flikhamud45 That would be great! IF you could, could you create a fork of the current project, but with your TLS stuff? Cheers 👍

@synchronizing
Copy link
Owner Author

Sorry guys, I've been recuperating from a surgery & work has taken over my time. In regards to the code above, while this is nice, it doesn't solve the original issue where we have to install the certificate - BUT, you are on the right track, you are just missing one piece.

When mitm boots-up it needs to generate a certificate authority (CA) that is installable, and then, using the CA, generate certificates for every connection. I have some code locally that I haven't gotten around to finishing just yet - lmk if you would like me to share it for the MR.

@flikhamud45
Copy link

Sorry guys, I've been recuperating from a surgery & work has taken over my time. In regards to the code above, while this is nice, it doesn't solve the original issue where we have to install the certificate - BUT, you are on the right track, you are just missing one piece.

When mitm boots-up it needs to generate a certificate authority (CA) that is installable, and then, using the CA, generate certificates for every connection. I have some code locally that I haven't gotten around to finishing just yet - lmk if you would like me to share it for the MR.

Yes as I said the code I have posted above is not finnished. I have managed to make it work completely and have it locally as well if you want to.

@flikhamud45
Copy link

flikhamud45 commented May 6, 2022

@flikhamud45 That would be great! IF you could, could you create a fork of the current project, but with your TLS stuff? Cheers 👍

Sorry guys, I've been recuperating from a surgery & work has taken over my time. In regards to the code above, while this is nice, it doesn't solve the original issue where we have to install the certificate - BUT, you are on the right track, you are just missing one piece.
When mitm boots-up it needs to generate a certificate authority (CA) that is installable, and then, using the CA, generate certificates for every connection. I have some code locally that I haven't gotten around to finishing just yet - lmk if you would like me to share it for the MR.

Yes as I said the code I have posted above is not finnished. I have managed to make it work completely and have it locally as well if you want to.

I created a fork with my code if you want to see it. It has an option to use the openssl exe to create the certificates as well as with the python openssl package. (The one with the exe worked for me better)

@synchronizing
Copy link
Owner Author

synchronizing commented May 22, 2022

mitm version 1.3.0 has been officially released with support for certificate authority and dummy cert generation. See:

Closing this for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants