
Uma maneira um pouco menos hackish de interceptar e modificar protocolos não-HTTP através do Burp e outros.
Uma forma um pouco menos 'hackish' de interceptar e modificar protocolos não HTTP por meio do Burp e outros com suporte a interceptação SSL e TLS. Esta ferramenta é para pesquisadores e testadores de penetração de aplicações que realizam avaliações de segurança de clientes thick.
Uma versão melhorada do fantástico projeto mitm_relay.
Como parte do nosso trabalho no departamento de pesquisa da CyberArk Labs, precisávamos de uma forma de inspecionar a comunicação SSL e TLS sobre TCP e ter a opção de modificar o conteúdo dos pacotes em tempo real. Existem muitas formas de fazer isso (por exemplo, a conhecida extensão do Burp Suite NoPE), mas nenhuma delas funcionou para nós em alguns casos. No final, encontramos o mitm_relay.
mitm_relay é uma forma rápida e fácil de realizar MITM de qualquer protocolo baseado em TCP através de softwares de interceptação HTTP existentes, como o proxy do Burp Suite. É particularmente útil para avaliações de segurança de clientes thick. Mas não funcionou completamente para nós, então precisamos personalizá-lo. Após muitas personalizações, cada nova alteração exigia muito trabalho, e acabamos reescrevendo tudo de uma forma mais modular.
Esperamos que outros achem este script útil, e esperamos que adicionar funcionalidades seja fácil.
Para começar, os endereços e portas dos listeners precisam ser configurados. Para cada listener, também precisa ser configurado um alvo (endereço e porta). Cada dado recebido do listener será encapsulado no corpo de uma requisição HTTP POST com a URL contendo 'CLIENT_REQUEST'. Cada dado recebido do alvo será encapsulado no corpo de uma requisição HTTP POST com a URL contendo 'SERVER_RESPONSE'. Essas requisições são enviadas para um servidor de interceptação HTTP local.
Há a opção de configurar um proxy HTTP e usar uma ferramenta como o burp suite como ferramenta de interceptação HTTP e visualizar as mensagens lá. Dessa forma, é fácil modificar as mensagens usando 'Match and Replace' do Burp, extensões ou até mesmo manualmente (Lembre-se, o mecanismo de timeout do protocolo interceptado pode ser muito curto).
Outra forma de modificar as mensagens é usando um script Python que o servidor de interceptação HTTP executará quando receber mensagens.
O corpo das mensagens enviadas ao servidor de interceptação HTTP será impresso no shell. As mensagens serão impressas após as alterações se o script de modificação for fornecido. Após todas as modificações, o servidor de interceptação também ecoará de volta como corpo da resposta HTTP.
Para descriptografar a comunicação SSL/TLS, o mitm_intercept precisa receber um certificado e uma chave que o cliente aceitará ao iniciar um handshake com o listener. Se o servidor alvo exigir um certificado específico para handshake, há a opção de fornecer um certificado e uma chave.
Um pequeno gráfico para mostrar o fluxo de tráfego típico:

mitm_intercept é compatível com versões mais recentes do Python 3 (Python 3.9) e também é compatível com Windows (por exemplo, socket.MSG_DONTWAIT não existe no Windows). Mantivemos a opção de usar 'STARTTLS', e a chamamos de modo 'Mixed'. O uso do arquivo de log de chaves SSL foi atualizado (a opção embutida para usá-lo é nova desde Python 3.8), e adicionamos a opção de alterar o cabeçalho SNI. Agora, o gerenciamento da comunicação de entrada e saída é feito por socketserver, e todos os dados são enviados para uma subclasse de ThreadingHTTPServer que lida com a representação e modificação dos dados. Dessa forma, é possível ver as alterações aplicadas pelo script de modificação na resposta (conveniente para usar Burp). Além disso, agora podemos alterar as cifras disponíveis que o script usa usando o formato de lista de cifras OpenSSL.
$ python -m pip install requestsusage: mitm_intercept.py [-h] [-m] -l [u|t:]<interface>:<port> [[u|t:]<interface>:<port> ...] -t
[u|t:]<addr>:<port> [[u|t:]<addr>:<port> ...] [-lc <cert_path>]
[-lk <key_path>] [-tc <cert_path>] [-tk <key_path>] [-w <interface>:<port>]
[-p <addr>:<port>] [-s <script_path>] [--sni <server_name>]
[-tv <defualt|tls12|tls11|ssl3|tls1|ssl2>] [-ci <ciphers>]
mitm_intercept version 1.6
options:
-h, --help show this help message and exit
-m, --mix-connection Perform TCP relay without SSL handshake. If one of the relay sides starts an
SSL handshake, wrap the connection with SSL, and intercept the
communication. A listener certificate and private key must be provided.
-l [u|t:]<interface>:<port> [[u|t:]<interface>:<port> ...], --listen [u|t:]<interface>:<port> [[u|t:]<interface>:<port> ...]
Creates SSLInterceptServer listener that listens on the specified interface
and port. Can create multiple listeners with a space between the parameters.
Adding "u:" before the address will make the listener listen in UDP
protocol. TCP protocol is the default but adding "t:" for cleanliness is
possible. The number of listeners must match the number of targets. The i-th
listener will relay to the i-th target.
-t [u|t:]<addr>:<port> [[u|t:]<addr>:<port> ...], --target [u|t:]<addr>:<port> [[u|t:]<addr>:<port> ...]
Directs each SSLInterceptServer listener to forward the communication to a
target address and port. Can create multiple targets with a space between
the parameters. Adding "u:" before the address will make the target
communicate in UDP protocol.TCP protocol is the default but adding "t:" for
cleanliness is possible. The number of listeners must match the number of
targets. The i-th listener will relay to the i-th target.
-lc <cert_path>, --listener-cert <cert_path>
The certificate that the listener uses when a client contacts him. Can be a
self-sign certificate if the client will accept it.
-lk <key_path>, --listener-key <key_path>
The private key path for the listener certificate.
-tc <cert_path>, --target-cert <cert_path>
The certificate that used to create a connection with the target. Can be a
self-sign certificate if the target will accept it. Doesn't necessary if the
target doesn't require a specific certificate.
-tk <key_path>, --target-key <key_path>
The private key path for the target certificate.
-w <interface>:<port>, --webserver <interface>:<port>
Specifies the interface and the port the InterceptionServer webserver will
listens on. If omitted the default is 127.0.0.1:49999
-p <addr>:<port>, --proxy <addr>:<port>
Specifies the address and the port of a proxy between the InterceptionServer
webserver and the SSLInterceptServer. Can be configured so the communication
will go through a local proxy like Burp. If omitted, the communication will
be printed in the shell only.
-s <script_path>, --script <script_path>
A path to a script that the InterceptionServer webserver executes. Must
contain the function handle_request(message) that will run before sending it
to the target or handle_response(message) after receiving a message from the
target. Can be omitted if doesn't necessary.
--sni <server_name> If there is a need to change the server name in the SSL handshake with the
target. If omitted, it will be the server name from the handshake with the
listener.
-tv <defualt|tls12|tls11|ssl3|tls1|ssl2>, --tls-version <defualt|tls12|tls11|ssl3|tls1|ssl2>
If needed can be specified a specific TLS version.
-ci <ciphers>, --ciphers <ciphers>
Sets different ciphers than the python defaults for the TLS handshake. It
should be a string in the OpenSSL cipher list format
(https://www.openssl.org/docs/manmaster/man1/ciphers.html).
For dumping SSL (pre-)master secrets to a file, set the environment variable SSLKEYLOGFILE with a
file path. Useful for Wireshark.
A comunicação precisa ser direcionada ao listener para interceptar protocolos arbitrários. A forma de fazer isso depende de como o cliente opera. Às vezes ele usa um endereço DNS, e alterar o arquivo hosts será suficiente para resolver o endereço do listener. Se o endereço estiver codificado, então formas mais criativas precisam ser aplicadas (geralmente algumas modificações na tabela de roteamento, correção do cliente ou uso de VM e iptables).
O servidor de interceptação HTTP pode executar um script fornecido a ele com a flag -s. Este script é executado quando as requisições HTTP são recebidas. A resposta do servidor de interceptação HTTP é a requisição recebida após a execução do script.
Quando um proxy é configurado (como Burp), as modificações na requisição ocorrerão antes da execução do script, e as modificações na resposta ocorrerão depois disso. Alterações na requisição e na resposta feitas pelo proxy ou pelo script de modificação alterarão a mensagem original antes de ir para o destino.
O script deve conter as funções handle_request(message) e handle_response(message). O servidor de interceptação HTTP chamará handle_request(message) quando a mensagem for do cliente para o servidor e handle_response(message) quando a mensagem for do servidor para o cliente.
Um exemplo de script que adiciona um byte nulo no final da mensagem:
def handle_request(message):
return message + b"\x00"
def handle_response(message):
# Both functions must return a message.
return message
A ferramenta requer um certificado de servidor e uma chave privada para interceptação SSL. Informações sobre como gerar um certificado autoassinado ou o certificado do Burp podem ser encontradas aqui.
Se o servidor exigir um certificado específico, um certificado e uma chave podem ser fornecidos à ferramenta.
A demonstração abaixo mostra como interceptar uma conexão com MSSQL (esta demonstração foi realizada no DVTA):
A conexão ao MSSQL é feita pelo protocolo TDS sobre TCP. A autenticação em si é realizada com TLS sobre o protocolo TDS. Para interceptar esse processo TLS, precisaremos de dois scripts de modificação improvisados.
demo_script.py:
from time import time
from struct import pack
from pathlib import Path
def handle_request(message):
if message.startswith(b"\x17\x03"):
return message
with open("msg_req" + str(time()), "wb") as f:
f.write(message[:8])
return message[8:]
def handle_response(message):
if message.startswith(b"\x17\x03"):
return message
path = Path(".")
try:
msg_res = min(i for i in path.iterdir() if i.name.startswith("msg_res"))
data = msg_res.read_bytes()
msg_res.unlink()
except ValueError:
data = b'\x12\x01\x00\x00\x00\x00\x01\x00'
return data[:2] + pack(">h", len(message)+8) + data[4:] + message
demo_script2.py:
from time import time
from struct import pack
from pathlib import Path
def handle_request(message):
if message.startswith(b"\x17\x03"):
return message
path = Path(".")
try:
msg_req = min(i for i in path.iterdir() if i.name.startswith("msg_req"))
data = msg_req.read_bytes()
msg_req.unlink()
except ValueError:
data = b'\x12\x01\x00\x00\x00\x00\x01\x00'
return data[:2] + pack(">h", len(message)+8) + data[4:] + message
def handle_response(message):
if message.startswith(b"\x17\x03"):
return message
with open("msg_res" + str(time()), "wb") as f:
f.write(message[:8])
return message[8:]
Veremos parte da comunicação TLS com esses scripts improvisados, mas então o cliente falhará (porque com esses scripts hackers, alteramos mal a comunicação TDS, exceto a parte TLS).
Copyright (c) 2022 CyberArk Software Ltd. Todos os direitos reservados
Este repositório está licenciado sob a Licença Apache-2.0 - veja LICENSE para mais detalhes.