Sniffing a system from outside a network: TCP reverse shell + ARP poisoning using Scapy

Nimish Mishra
Analytics Vidhya
Published in
10 min readJun 30, 2020
Source: https://resources.infosecinstitute.com/hacker-tools-sniffers/#gref

Sniffing in a network is simply monitoring network traffic and extracting interesting information from it. In order to understand basics of sniffing, it is worthwhile to understand how local networks operate. With the ever increasing number of systems/nodes in the world, the IPv4 addresses are insufficient to uniquely identify all systems connected to the internet. Because of this, certain IP address spaces, called non-routable addresses, are used to identify nodes in a local network, all of which communicate with the outer world through a gateway.

Gateway. Source: https://bytesofgigabytes.com/networking/what-is-gateway-in-networking/

From the viewpoint of the outside world, all traffic comes from and goes to the gateway, which then operates such that traffic is delivered to the original node within the local network. Several concepts like NAT and ARP (or the replaced Neighbor Discovery Protocol in case of IPv6) are at play. We are interested in ARP (Address Resolution Protocol) that maintains a periodically updated table of MAC-IP mappings.

Sample ARP table mapping IPv4 addresses to MAC addresses

MAC addresses being unique can be treated as hardware addresses, while IPv4 addresses are dynamically assigned once a node joins a network. The gateway, when receiving incoming network traffic, uses NAT to translate destination IP address to one of its local IPv4 address. It then looks up the corresponding MAC address in the ARP table, creates a new Ethernet layer with the recently discovered MAC address, and sends the packet.

We are looking to sniff such traffic. From outside the network!!!

Overview of the attack

TCP reverse shell has been explained and demonstrated in this article. We thus focus on ARP in this article.

From the discussion on ARP and NAT, the following possibility of ARP poisoning arises (this attack is detected by firewalls and is invalid in case of Neighbor Discover Protocol). In our case, however, firewalls guarding the entire network will fail to detect any anomaly as connection to the outside is first requested from inside the network itself (TCP reverse shell). Custom firewalls guarding traffic to the target node will be able to detect anomalies.

Source: https://tournasdimitrios1.wordpress.com/2011/02/08/4426/

In this case, Bob and Alice had their ARP tables that communicated to the switch (the gateway). Now comes an attacker who launches an ARP poison attack (also called MIT, or man in the middle attack) such that they modify Bob’s, Alice’s, and the switch’s ARP cache as follows:

  1. Switch ARP: Bob’s IP → attacker MAC
  2. Switch ARP: Alice’s IP → attacker MAC
  3. Bob’s ARP: Switch’s IP → attacker MAC
  4. Alice’s ARP: Switch’s IP → attacker MAC

Quite evidently, the cache is poisoned to believe the node the system is trying to communicate with is actually sitting at the attacker’s hardware destination. For instance, if Bob has to send a packet to the switch, they will send to the switch’s IP (which is correct) which in turn goes to attacker’s IP (due to poisoned/incorrect mapping). The attacker then sniffs the packet, modifies if needed, and forwards to the switch.

IP forwarding (enable/disable method) is enabled on the attacker’s machine and allows the incoming packet intended for switch’s IP to be forwarded to the switch. Hence, without a firewall, Bob doesn’t face any anomaly in browsing the internet, while in reality their network traffic is being forwarded through a proxy.

But from outside a network?

This attack is carried out from within the local network. The attacker must be connected to the same gateway. We are rather looking to carry out sniffing from outside the network. The following simple combination works well:

  1. Open a TCP reverse shell on a low hanging fruit in the target network. A node/system you have access to or can engineer to let the TCP reverse shell run. Let this node be M.
  2. Discover the nodes in the local network, and identify the target. Let this node be T.
  3. Carry out ARP poisoning from M to T, and transfer information to the attacker using the TCP reverse shell.

The TCP reverse shell can be managed across networks.

Note on tool/library usage

There sure exist tools you can fire with simple commands on your terminal and libraries you can import and call functions/methods that reduce the amount you have to code. There is a tender tradeoff between abstraction and low-level stuff: more of low level stuff forces you to deal with lots of issues at their core thereby skyrocketing learning while slowing down development speed, while abstracted tools/libraries may stagnate learning.

Deciding the sweet point for your learning path is an important task to do. You might use tools/libraries to achieve all described below simply and quickly, or you might code everything from ground zero. It all depends how much you understand the basics before moving to abstractions. As for the article, we stick to pure Python and sockets for the TCP reverse shell, but resort to Scapy for ARP poisoning (or in general for faster packet creation and dissection, which is burdensome in pure Python). We still restrain from in-built Scapy functions that carry out the ARP poisoning attack.

Setting up the TCP reverse shell

The article explains in detail the mechanism to set up a TCP reverse shell. That was, however, for communication within the same network. To communicate across networks, few changes are required.

The first point is to discover the global IP of the attacker. Entering hostname -I or ifconfig in the terminal (or if that doesn’t work, visit https://whatismyipaddress.com). For this, we shall go with the IPv6 address.

Changes in target side script of TCP reverse shell

The following changes suffice. Same updates are made to the attacker side script before binding the AF_INET6 socket on port 12345. Test it out and the connection works as described in this post.

Discovering nodes in the local network

The next step is to discover the nodes in the local network, from the machine we have opened our TCP reverse shell on. Before moving on, be sure to be familiar with the basics of Scapy.

Discovering nodes on local network

Here we see the power of Scapy in packet manipulation. Refer the following format.

ARP packet format. Source: https://support.huawei.com/enterprise/en/doc/EDOC1000166600/6bb92fd8/arp-implementation

As given, we create the Ethernet layer first, which can be considered as the hardware level layer containing MAC addresses of the source and destination. Ethernet(dst=) serves to create such a layer with destination ff:ff:ff:ff:ff:ff or unspecified MAC addresses (and thus this packet is pinged to all nodes in the local network which answer based on the second layer ARP). The second layer controls which nodes answer to the packet. Nodes answer the ARP packet if they find their IP address in the ARP layer ( IP address of destination section of the format). srp serves to send packets and receive response ( timeout implies how long this sending and receiving goes on). ans (or the packets answered) is a beautifully set up list of tuples, where each element is a tuple containing the packet send and the corresponding response received. received[ARP] accesses the ARP layer of the received packet, after which we may extract any information needed:

  1. psrc : the protocol source (or the source IP address)
  2. pdst : the protocol destination (or the destination IP address)
  3. hwsrc : the hardware source (or the source MAC address)
  4. hwdst : the hardware destination (or the destination MAC address)

For now, we are concerned with the IP addresses. Thus the term received[ARP].psrc . Now that we understand the receiving nodes would answer the ARP packet iff their addresses are mentioned as pdst in ARP() , we specify a range of IP addresses, send packets to all, and accept response.

Fire up a terminal and type in ifconfig | grep inet or equivalent command that can show you the IP address of your machine and the subnet mask. Sample response is of the type: inet 192.168.43.34 netmask 0xffffff00 broadcast 192.168.43.255 . From this, fire the script and call the function as discovery('192.168.43.1/24', 10) .

Sample response of the discovery function. Two nodes responded. The address 192.168.43.38 is a new entry.
Notice updates in the ARP table

ARP poison attack

The attack proceeds in the following stages (be sure to enable IP forwarding):

  1. Get the MAC of the gateway and target
  2. Poison and sniff
  3. Restore: to cover tracks in the ARP table once you are done.
Discover MAC address of the specified IP address

ff:ff:ff:ff:ff:ff serves to broadcast this packet to all hardware addresses with the question who-has ip_address . We get a packet in response with the answer is_at hwsrc . We extract the hardware address of the received packet since this hardware address responded to our ARP packet.

Poisoning the ARP caches

op is an option we aren’t much concerned about. The poisoning proceeds as follows:

1 . [Target to gateway]: Gateway receives a packet that says

a) hwdst or destination MAC as the gateway MAC. The gateway knows thus the packet is meant for it. Similarly, pdst is also fine, or the IP is that of the gateway.

b) hwsrc is left empty. When sent, the attacker machine’s MAC is filled in this field.

c) psrc is the IP of the target machine. Now the gateway checks its ARP table and sees psrc and hwsrc do not match. It thus updates the table.

Similarly, [Gateway to target] route is poisoned. The main idea is to forge a packet that carries the source IP of a one machine and source MAC of a different machine. The receiving node notices this discrepancy and updates the ARP table.

Sniffer

Once the poisoning is done, we set up a sniffer for ip host target_ip or all packets going through the attacker machine that come from source target_ip . We thus capture all packets from the target, and perform actions on the packet in a function referenced by prn (or what to do when a valid packet is sniffed). The function callback is straightforward; it looks for relevant layers, captures information, and writes it to a variable.

After we are through with the attack, restoration is done.

Restoration work

Restoring is similar to poisoning; in a way, we make a discovery call on behalf of the gateway and the target. After poisoning, say every packet from gateway to target is sent to hardware address of the attacker. We fix that by making a discovering/ARP call on behalf of the gateway that seeks to discover the hardware address of the target; or crafting a packet going from gateway to target (source IP and MAC that of the gateway, and destination IP of the target as before) with hwdst="ff:ff:ff:ff:ff:ff" . hwdst set to broadcast is simply so that when the target machine (or pdst) responds to the ARP request, the gateway receives the ARP response with the target’s MAC as hwsrc . The gateway again looks at the ARP table and finds a mismatch between hwsrc (which is set to attacker MAC in the poisoning phase) and psrc (which is set to target IP). The gateway fixes this; gateway’s ARP is thus restored.

Similar restoration is done by making a ARP call on behalf of the target that seeks the hardware address of the gateway. The interesting thing to note is since we have specified hwsrc and set to hwdst to broadcast , although we make this call from the attacker’s machine, the response goes to the gateway or the target as specified by psrc / hwsrc . Note differences from the discovering phase where hwsrc and psrc were set to attacker’s machine, and thus responses came to the attacker.

It is thus possible to create packets in one system the responses of which are received by another system. It is exactly this that aids in restoration.

Integrating the TCP reverse shell and ARP poison script

Updated run command method

The run_command method from TCP reverse shell is modified to handle two separate commands poison and discover . The entry function brings together all portions of ARP poisoning script.

Main function integrating all components of ARP poison attack

Quite evidently, the three stages of the attack are done in order here.

Sample run

The network setup is as follows:

  1. Network A:

a) Gateway: WiFi hotspot, Moto G6

b) TCP reverse shell: Macbook Air connected to moto G6

c) Target: Redmi connected to Moto G6

2. Network B:

a) Gateway: WiFi hotspot; Samsung

b) Attacker: HP Kali linux

The attacker opens a TCP reverse shell on the Macbook through the attacker’s global IP address.

Gateway information of the attacker. Note flag G denotes the gateway.
Gateway information for TCP reverse shell target. Note flag G denotes the gateway.

A series of commands issued by the attacker to mount an attack.

Attacker side commands

Using ifconfig and netstat the target network configurations are determined, mainly the netmask and inet addresses. Using this information, a discover 192.168.43.1/24 10 is fired where the first argument denotes the target address range to discover and the second argument denotes the timeout. We receive three responses, and upon investigating the ARP table, find a redminote5pro-redmi sitting at 192.168.43.125 . We launch a ARP poison attack from the Macbook Air to Redmi, and transfer the data sniffed back to the Kali node sitting outside the local network.

Sniffed packets’ data on the attacker’s machine
Commands executed on TCP reverse shell target.

Conclusion

Some things need to be kept in mind.

  1. We might try to develop a reverse shell in Scapy, but that is unreliable and often breaks down. Moreover, Scapy routing is unreliable as compared to Socket routing. See this
  2. Scapy requires root permissions in order to open raw sockets. To properly run on TCP reverse shell target, refer this (must be played around with care).
  3. Is disclosing MAC addresses a problem? Refer this.
  4. A main problem is the need for attacker’s IPv6 address to start communication. IPv6 addresses change regularly, and we need a mechanism for the TCP reverse shell target to automatically adjust for this. As of now, I haven’t thought about overcoming this.

Have a good day!

--

--