Giter Club home page Giter Club logo

mitm_relay's Introduction

mitm_relay

Hackish way to intercept and modify non-HTTP protocols through Burp & others with support for SSL and STARTTLS interception

This script is a very simple, quick and easy way to MiTM any arbitrary protocol through existing traffic interception software such as Burp Proxy or Proxenet. It can be particularly useful for thick clients security assessments. It saves you from the pain of having to configure specific setup to intercept exotic protocols, or protocols that can't be easily intercepted. TCP and UDP are supported.

STARTTLS is supported, which makes it usable against protocols like XMPP, IMAP, SMTP, IRC, etc.

It's "hackish" in the way that it was specifically designed to use interception and modification capabilities of existing proxies, but for arbitrary protocols. In order to achieve that, each client request and server response is wrapped into the body of a HTTP POST request, and sent to a local dummy "echo-back" web server via the proxy. Therefore, the HTTP responses or headers that you will see in your intercepting proxy are meaningless and can be disregarded. Yet the dummy web server is necessary in order for the interception tool to get the data back and feed it back to the tool.

  • The requests from client to server will appear as a request to a URL containing "CLIENT_REQUEST"
  • The responses from server to client will appear as a request to a URL containing "SERVER_RESPONSE"

This way, it is completely asynchronous. Meaning that if the server sends responses in successive packets it won't be a problem.

To intercept only server responses, configure your interception rules like so:

Intercept responses

"Match and Replace" rules can be used. However, using other Burp features such as repeater, intruder or scanner is pointless. That would only target the dummy webserver used to echo the data back.

The normal request traffic flow during typical usage would be as below:

Traffic flow

Usage

  • If you don't specify a proxy, the traffic will simply be dumped to stdout.
  • You can setup multiple relays, using -r [local port]:[dest_host]:[dest_port]
usage: mitm_relay.py [-h] [-l <listen>] -r <relay> [<relay> ...] [-s <script>] [-p <proxy>] [-c <cert>] [-k <key>] [-cc <clientcert>] [-ck <clientkey>] [-t <timeout>]

mitm_relay version 3.00

options:
  -h, --help            show this help message and exit
  -l <listen>, --listen <listen>
                        Address the relays will listen on. Default: 0.0.0.0
  -r <relay> [<relay> ...], --relay <relay> [<relay> ...]
                        Create new relays. Several relays can be created by repeating the paramter. If the protocol is omitted, TCP will be assumed. Format: [udp:|tcp:]lport:rhost:rport
  -s <script>, --script <script>
                        Python script implementing the handle_request() and handle_response() functions (see example). They will be called before forwarding traffic to the proxy, if specified.
  -p <proxy>, --proxy <proxy>
                        Proxy to forward all requests/responses to. If omitted, traffic will only be printed to the console (monitoring mode unless a script is specified). Format: host:port
  -c <cert>, --cert <cert>
                        Certificate file to use for SSL/TLS interception
  -k <key>, --key <key>
                        Private key file to use for SSL/TLS interception
  -cc <clientcert>, --clientcert <clientcert>
                        Client certificate file to use for connecting to server
  -ck <clientkey>, --clientkey <clientkey>
                        Client private key file to use for connecting to server
  -t <timeout>, --timeout <timeout>
                        Socket receive timeout

User scripts

The tool offers the possibility to use custom scripts for traffic analysis and modification. Scripts can be used in replacement or in addition to forwarding the traffic to the proxy. If both a script and a proxy are specified on the command line, the traffic will be sent to the script first and then to the proxy, before being finally forwarded to either to client or the server, depending on where the message came from.

There are several scenarios where you may want to use a script. For example:

  • Update a field of the protocol that specifies the length of a part of the message. If you're modifying data in a protocol that specifies the length of others portions of the message in a specific field, you will want to update that field as well. Of course, some knowledge of the protocol that you're working with is necessary.

  • Fuzz specific parts of a protocol. You could try to change some values arbitrarily in some parts of the messages your thick client is sending.

  • Deserialize objects, do some modifications on them, and re-serialize.

  • Monitor traffic flow or log data to a file (example: extract usernames and passwords)

Scripts can implement either of both of the 'handle_request' and 'handle_response' functions (see example script). A script that disables compression on an IMAP session could look like the following:

def handle_request(client_request):

  # Example: remove compression on an IMAP session
  modified_request = client_request.replace('COMPRESS=DEFLATE', 'COMPRESS=NONE')

  return modified_request

Certificates

For SSL interception, the tool requires a server certificate and private key. When creating your certificate, you may want to specify a CommonName matching what the client expects. During my tests I had trouble to get SSL/STARTTLS interception to work. This was because my client was checking for a specific Common Name. You can grab it from the actual server's certificate anyway.

Below are commands that you can use to create your self-signed cert and key.

$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.key -outform pem -out server.pem -subj "/CN=*.acmecorp.com"

Now this will be a self-signed cert. If however the client that you're testing does certificate validation, you can try and import your proxy's CA in your trust store and then generate a CA-signed server certificate. Assuming your proxy is Burp and your client runs on Windows, here is how to do it:

  • Under Burp Proxy listeners options, click "Import / Exoprt CA Certificate".
  • Export both the CA cert and the key in DER format, name them "cacert.cer" and "cakey.cer".
  • In Windows, double-click on the cacert.cer file and choose to "Install certificate", place it in the "Trusted root certification authorities" store.
  • Now you need to convert that into PEM format:
$ openssl x509 -inform der -in cacert.cer -outform pem -out cacert.pem
$ openssl rsa -inform der -in cakey.cer -outform pem -out cakey.pem
  • And finally create a CA-signed certificate:
$ openssl genrsa -out server.key 2048
$ openssl req -new -key server.key -out server.csr -subj "/CN=*.acmecorp.com"
$ openssl x509 -req -in server.csr -CA cacert.pem -CAkey cakey.pem -CAcreateserial -out server.pem -days 365 -sha256
  • Now you can use server.pem and server.key with mitm_relay and it will be trusted by your client. (if it does not do certificate pinning of course.)

Host configuration

To configure interception for arbitrary protocols, the simplest way is to figure out which DNS addresses the client is trying to resolve and then update your hosts file to point it to your mitm_relay listener (make it listen on the same port as the destination server).

If however the client uses hard-coded addresses, a solution can be the following. First, run your client in a bridged or host-only VM. Run your client, sniff the network traffic and figure out which IP addresses it is connecting to. Then, a bit of setup is necessary on your host, assuming it is running Linux.

In the examples below, my VM is using IP address 192.168.56.10, my host is 192.168.10.101, and the destination server is running at 1.2.3.4:4567

  • Create DNAT rules to redirect relevant traffic to the correct relay ports:
  • iptables -t nat -A PREROUTING -s 192.168.56.10/32 -p tcp --dport 4567 -d 1.2.3.4 -j DNAT --to-destination 192.168.10.101
  • Now just run mitm_relay with listen ports matching the destination ports the client tries to connect to.

You may also want to enable NAT + IP forwarding on your host so that any "non-intercepted" network communications can still reach the destination server (or if you simply need internet access/DNS in your VM):

  • In the VM set your Host's IP address as the default gateway, and use a public DNS server
  • On your host enable IP forwarding and NAT (replace $INTERNAL and $EXTERNAL by the relevant interfaces names):
$ echo 1 > /proc/sys/net/ipv4/ip_forward
$ iptables -t nat -A POSTROUTING -o $EXTERNAL -j MASQUERADE
$ iptables -A FORWARD -i $EXTERNAL -o $INTERNAL -m state --state RELATED,ESTABLISHED -j ACCEPT
$ iptables -A FORWARD -i $INTERNAL -o $EXTERNAL -j ACCEPT

That should do it.

Demo

The demo below shows how to intercept and modify DNS lookups using mitm_relay + Burp.

DNS Interception

This demo shows an SSH session relayed through mitm_relay + Burp. This is pretty useless as it's SSH anyway and can't be altered (except maybe the initial handshake and list of ciphers), but it shows how you can work with binary protocols.

SSH Interception

That one shows interception and modification of a MySQL session. Note this is a PoC only as if your modification changes the length of the SQL message, you'll need to update the corresponding fields in the protocol as well, otherwise the session would be corrupted and terminated. See the 'User scripts' section and see this for an example of how to do it.

SQL Interception

Screenshot: SMB/CIFS Traffic interception:

CIFS

Screenshot: Disabling compression on a Gmail IMAP session to capture plain text exchanges:

IMAP

mitm_relay's People

Contributors

antnks avatar bcoles avatar jrmdev avatar kmarty avatar parsiya avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mitm_relay's Issues

Cannot make it work on a private VM network

Hi,

Thank you very much for your contributions.
In my case, I am running a client on my host machine (Mac Ventura) and an SMB server on my VM (Ubuntu 14.04).
The VM is configured to use the private network (interface: vmenet3) with the host.

Here are the IP addresses and the port numbers:

Server on my VM has the IP 192.168.139.130, and listens on port 445.
Client connects to the VM using the IP 192.168.139.1, and connects using the port 55419.

I would like to run the relay server on my host machine running the client.
Therefore, relay's IP address will also be 192.168.139.1 but it will listen on 445 (the same with the SMB server on my VM).

Here is my host configuration below.
I first enable IP forwarding, then forward the packets to the relay using pfctl.

sysctl -w net.inet.ip.forwarding=1
echo "rdr pass inet proto tcp from any to any port 445 -> 192.168.139.1 port 445" | sudo pfctl -ef -

Then, I run the script as below.
sudo python3 mitm_relay.py -l 192.168.139.1 -r 445:192.168.139.130:445

However, it does not capture any packets. Do you have any intuition why?
Any help is much appreciated,

TLS + SIP Mitm

I want to use mitm_relay + burpsuite to intercept my root andriod rcs messages.
I configure Android using the ip of linux running mitm_relay and burpsuite as router ip. (the provider's rcs service port is 5260)
And I use iptables to redirect tcp to 5261 port (from 5260) locally.
Then error occured:
---------------------- Wrapping sockets ----------------------
Exception in thread Thread-8:
Traceback (most recent call last):
File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "/usr/lib/python3.8/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "mitm_relay.py", line 419, in handle_tcp_client
do_relay_tcp(client_sock, server_sock, cfg)
File "mitm_relay.py", line 301, in do_relay_tcp
receiving, _, _ = select([client_sock, server_sock], [], [])
ValueError: file descriptor cannot be a negative integer (-1)
Exiting...

License file has no ownership information

The LICENSE file is still in template form.

To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright {yyyy} {name of copyright owner}

Password for client key

For client authentication on need a client certificate and client key file. The client key file usually is password protected.
mitm_relay asks for the password several times after starting.

Is it possible to enter the password as parameter in the program call?

Burp Repeater support

If it is possible to add something for mitm_relay to support Burp Repeater, where I can use my crafted SIP message? (maybe, Burp Repeater -> mitm_web_server -> ... -> SIP endpoint).
As in the description of intercept procedure in your README, ,we can use Burp Proxy to intercept and modify messages. (like, thick client -> listeners ->Burp Proxy -> web sever -> ... -> endpoint).

Or, say it, like Burp Proxy procedure (intercept and modify messages, then send it to dummy web sever... then to endpoint through mitm_relay), is it possible to do similar thing using Burp Repeater (send crafted messages directly to dummy web sever... then to endpoint through mitm_relay).

What do you mean with "relay"?

First, great code :D
But I wanna ask something, I'm really bad in Networking. What do you mean by relay ? Is that a proxy server or something? And what you mean by the argument "-l" is that something like a IP address of the server? Which you can intercept | listen all incoming request that was made for it?
Thanks

SSL and TLS issues

Hi There,
i am tring to use the following flag with mitm_relay script :
-c , --cert
Certificate file to use for SSL/TLS interception
-k , --key
Private key file to use for SSL/TLS interception
i did the whole guide on creating the relevant certificate and key.
I can see everything encrypted within burp suite.
Any ideas?

SSLv3 Support

SSLv3 has been deprecated in the standard ssl library for Python 2 and 3.

Is there a solution for downgrading the ssl library to support ssl.PROTOCOL_SSLv3?

There is PROTOCOL_SSLv23, but I was unable to get this to send an SSLv3 handshake.

param -r issue

Now I want to exec the script and listen on my desktop, meanwhile let mobile device connect to it, all requests are sent by APP, but there are Http and non-Http requests in the whole process, so how should I write the param -r? Is my command right?
python mitm_relay.py -l 0.0.0.0 -p 127.0.0.1:8888 -r 4500:.*.com:8082 -c server.pem -k server.key

Forwarding to Burp/proxy does not happen with -p set

Since the major update of 2022 the tool works great, however when setting a proxy with -p it does not actually forward traffic to the proxy, because the urlopen call is never told to use a proxy.
I was able to fix this by prefixing the call to mitm_relay.py with the environment variable HTTP_PROXY like this:

HTTP_PROXY=127.0.0.1:8080 python3 mitm_relay -p 127.0.0.1:8080

Setup Confusing

Hi, Please i'm trying to set this up to use with burp suite on a windows system. I didn't totally understand what you said.

Would appreciate if you could drop clearer steps/videos to help noobs like me. Thank you

BIND_WEBSERVER should be configurable

Hi, I may be wrong, but I think BIND_WEBSERVER should be configurable. I have mitm_relay configured in a RPi and Burp in another machine. Thus, mitm_relay is proxifing the requests to Burp with success, but Burp can not send them back to mitm_relay as they are pointing to 127.0.0.1 instead of the actual RPi IP where the mitm_relay webserver is listening to and not in the machine where Burp is running as there is nothing listening in there.

Regards,

Question on mitm_relay - mitm ssl

Hello - I was wondering if in the case of ssl interception if there are times where you are mitm the traffic and it will fallback to a transparent mode where the certificate and key are not used and the traffic is just forwarded like a transparent proxy? So I have a listener and a relay but no -p flag to intercept. I'm seeing a message Wrapping sockets and an error:

ValueError: file descriptor cannot be a negative integer (-1) in the beginning of comms but then it starts to appear to work. The inner traffic appears proprietary/encrypted but I haven't been able to get ssl dissectors in wireshark to work yet.

So in short, does this tool fail silently and turn into a packet forwarded and all I am observing after the initial error is SSL/TLS traffic that is encrypted and mitm_relay is not utilizing the cert and key I am telling it to?

Burp Repeater support

I use mitm_relay to relay SIP protocol. It works perfect.
But I want to send some packet myself, Repeater of burp is more convenient.
Is this possible to support Burp Repeater ?

How are you going to bind it?

First of all, looks like a nice/simple project.
Secondly, I'm trying to bind it like this:

python mitm_relay.py -l 127.0.0.1 -p 127.0.0.1:8081 -r port:164.132.238.228:port

it's an online website. I've found that IP source through wireshark. What do you mean with putting two ports (before and after the IP address you're targeting at?).
Thanks.

I cannot make it work

Sorry for posting this to issues but i cannot make it work... i have a windows client that does not support proxy.. I used another application to proxify the client and sent all the traffic to your script but after the first request i never get a response.

Your traffic flow diagram confused me . Do i need to instances of your script ?

Thank you

EOF occurred in violation of protocol (_ssl.c:1122)

Hi,
I wanted to ask whether anyone encountered the error "EOF occurred in violation of protocol (_ssl.c:1122)" when trying to capture and decrypt TLS 1.2 traffic with cipher suite EOF occurred in violation of protocol (_ssl.c:1122).

Everything works perfectly with capturing the raw traffic (without TLS inspection), however when I specify the cert and key, the above error appears. What might be the optimal way to debug this error (e.g.: some code change to print more data instead of just "EOF occured")?

Any help is appreciated, thanks!

Modification of TCP packets

Hi,

I would like to say this is by far the best and most practical non-HTTP proxy that I’ve used!

I am currently doing research on thick client testing. The app that I’m testing uses the TCP protocol to connect to a remote database. One of the requests that the app sends contains a SELECT query that dynamically generates a SQL statement based on the credentials provided in the login form.

I would like to change the SQL query’s …WHERE username = ‘admin’ clause to …WHERE username = ‘bob’

I am able to replace admin with bob using the following script:

 def handle_request(client_request):
	#'admin' is '61646d696e' in HEX
	#'bob' is '626f62' in HEX

	modified_request = client_request.replace('\x00\x61\x00\x64\x00\x6d\x00\x69\x00\x6e\x00', '\x00\x62\x00\x6f\x00\x62\x00')
	return modified_request

However, due to the fact that the length of the modified TCP packet is different to the original packet the thick client that I’m testing just crashes after I receive the FIN, ACK response from the database server.

Your MySQL demo states that the corresponding fields in the TCP protocol will have to be changed if I make changes to the length of the SQL message. Do you have any ideas/suggestions how I should do that? I presume I will have to add some python code to the above script that I’m sending using your tool? I am not fluent in Python so I'm not sure how easy it will be to achieve this task.

Thank you!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.