Scapy ARP Poisoning - scapy

The Scapy documentation gives the following example of ARP Cache Poisoning:
send(Ether(dst=clientMAC)/ARP(op="who-has", psrc=gateway, pdst=client))
Question 1:
My understanding is that this is the broadcast of an ARP request from a client.
Shouldn't the ARP Poison be executed by the attacker responding with:
send(Ether(dst=clientMAC)/ARP(op="is-at", psrc=gateway, pdst=client))
Question 2:
In a post on stackoverflow about Scapy, the OP posted:
This sends the victim an ARP reply packet with the local machine masquerading as the router:
send(ARP(op=ARP.is_at, psrc=router_ip, hwdst=victim_mac, pdst=victim_ip))
This sends the router an ARP reply packet with the local machine masquerading as the victim:
send(ARP(op=ARP.is_at, psrc=victim_ip, hwdst=router_mac, pdst=router_ip))
In both of these packets, the hwsrc field is filled by default with the local machine's MAC address.
But the Scapy documentation doesn't mention that hwdst is required.
I'd like to know why.
Question 3:
In the Scapy documentation:
send(Ether(dst=clientMAC)/ARP(op="who-has", psrc=gateway, pdst=client))
But in the OP's post from Question 2, the Ether(dst-clientMAC) is not supplied.
Does that mean it's not required?
Thanks.

In computer networking, ARP spoofing, ARP cache poisoning, or ARP
poison routing, is a technique by which an attacker sends (spoofed)
Address Resolution Protocol (ARP) messages onto a local area network.
Generally, the aim is to associate the attacker's MAC address with the
IP address of another host, such as the default gateway, causing any
traffic meant for that IP address to be sent to the attacker instead.
Wiki
As it is mentioned in Scapy documentation,
ARP cache poisoning attack prevents a client from joining the gateway
by poisoning its ARP cache through a VLAN hopping attack.
What they mean by that is that the poor client will not be able to send his packets to the gateway (Access Point in this case) and will fail to communicate with external resources. Note, however, that the very same client will still be able to communicate with other hosts within the VLAN. Even with the attacker (assuming it is also connected to the same WiFi network).
Let's go through this attack step-by-step.
Before, we move further, let's check the current ARP table on the Client side (before the attack is executed). On Linux to view the ARP table you need to run the following command:
$ sudo arp -n
Address HWtype HWaddress Flags Mask Iface
192.168.1.1 ether 54:f6:15:f5:51:55 C wlan0
As you can see, the ARP table has only one record which lists the Gateway IP address (192.168.1.1) and it's MAC (54:f6:15:f5:51:55).
When the Attacker executes the following command in Scapy:
send(Ether(dst=clientMAC)/ARP(op="who-has", psrc=gateway, pdst=client))
it creates and sends the following packet:
At the Ether layer, the destination MAC address dst is set to point to the Client's (victim's) MAC. At the same time, Scapy automatically fills in other Ether layer fields, most importantly, the src field which is set to attacker's MAC address. This means that on Ether layer the packet seems to come from the Attacker. Other Ether layer fields remained unchanged and contain default values. You can see it yourself if you run the following command in Scapy:
a = Ether(dst="clientMAC")
a.show()
Now, on IP layer the attacker crafts an ARP request packet, in which he sets the psrc (source IP) field to point to the IP of the gateway node (AP in this case). Now, remember that previously, on the Ether layer Scapy filled in the src field for us and set it to point to Attacker's MAC address. This means, that the final packet which is sent to the Client (victim) will look like it came from host that has Attacker's MAC and Gateway's IP address. We will get to it later. For now, let's move on. Finally, Client's IP address is set as a destination for the packet in a pdst field.
The packet is created and sent to the Client (victim).
The Client receives this packet and checks the packet's content. It sees that the ARP request arrived from Gateway IP (let's assume it's 192.168.1.1). It checks the MAC address field psrc in the Ether layer of the packet (let's assume it's a9:2b:24:9c:fd:c7) and updates it's ARP table, which now looks as following:
$ sudo arp -n
Address HWtype HWaddress Flags Mask Iface
192.168.1.1 ether a9:2b:24:9c:fd:c7 C wlan0
As you can see the IP address remained the same, but the MAC address changed. So, now, whenever the Client sends packets to the Gateway node, it actually sends them to the Attacker's MAC. If the Attacker's goal is to prevent the Client from communicating with the Gateway, these packets will be dropped and never delivered to the desired destination.
While the Attacker keeps sending crafted ARP packets to the Client, the Client will not be able to communicate with the Gateway. Once the Attacker stops, the real ARP request from the Gateway with real IP and MAC addresses will eventually arrive to eh Client restoring the normal communication. That is why, you, as an attacker, would probably want to create a loop for sending malicious packets, like this:
sendp(Ether(dst=”CLIENT-MAC”)/ARP(op="who-has", psrc=”GATEWAY-IP”, pdst=”CLIENT-IP”), inter=0.2, loop=1)
With this never ending loop, you effectively jam the communication between the Client and Gateway.

Related

Linux socket UDP server - exchanging messages between 2 servers on 2 machines

I am working on a small linux socket project. The goal is to have multiple servers (ie. 1,2,3,4,5) that listen for send get and ACK packets from each of their respective clients. I am currently attempting to implement a routing table protocol whereby 2 servers (A, B) exchange their routing tables (vectors containing respective clients, server name, and number of hops). The issue I am having is with binding a socket to B's external address from A and vice-versa. From what I have read you do not bind to anything other than a local address except in certain cases. What I am wondering is how do I simply fire off a UDP packet from one server to another knowing the (static) IP address of each server?
What I am wondering is how do I simply fire off a UDP packet from one
server to another knowing the (static) IP address of each server?
The short answer is, you can't. At least on the Internet proper, only unicast is widely supported, which means that in order to send a UDP packet to another machine, you'll need to know its IP address (somehow).
The longer answer is: The first thing you often need to do is discover the target machines' IP addresses. That might be a matter of having the user manually enter a list of IP addresses, or if the target machines are on the same LAN, you can program a mechanism for auto-discovering them by having your program send out a broadcast or multicast UDP query packet. Make sure any instances of your program running on the same LAN receive that packet and respond to it by sending back a response UDP packet (the responses can be sent by by unicast or multicast or broadcast, your choice), and then your query-originating computer can know from the responses it receives which other IP addresses your program is presently also running on.
Note that a lot of computers and network devices run firewalls that reject incoming UDP packets by default, so if you packets don't seem to be getting through that is a likely reason why.

Accuracy of remote IP address retrieved from packet

If it were possible to retrieve the remote IP from a packet received by my Apache2 server (through a custom plugin perhaps), would it always be guaranteed to be accurate? Or is this value as easy to spoof as the referrer header?
My intended use case is to rate-limit unauthenticated API calls.
If it's a TCP packet, then it'll be accurate as to the sending host. IPs in TCP packets cannot be spoofed unless you've got control of the routers involved. With spoofed source packets, only the initial SYN packet will come back, and then the SYN+ACK response from the server will go to the spoofed address, not wherever the forgery came from - e.g. you cannot do the full 3-way handshake unless you can control packet routing from the targetted machine.
UDP packets, on the other hand, can be trivially forged and you cannot trust anything about them.
As well, even simple things like proxy servers and NAT gateways can cloak the 'real' ip from where the packet originated. You'll get an IP, but it'll be the IP of the gateway/proxy, not the original machine.
It is not reliable. Not only because it can be spoofed, but also because a network element can make your server see a different IP address.
For example, it is very typical in a company to access the Internet through a proxy. Depending on the configuration, from your server point of view, all the different users come from the same IP address.
In any case is a filter you can use in many scenarios. For example, show a captcha when you detect too many login requests from the same IP address.
If your intention is to rate-limit invalid API calls you might want to consider using a service like spamhaus. They list IP's that are likely bots and probes. There are other companies and lists as well. But if your intention is to ever ID the 'bad guy' the source IP is very unlikely to be correct.

howto make locally terminated tcp connections go through prerouting and postrouting?

I am developing an application that filters and mangles packets using netfilter queue's. It's rather complicated and needs to perform well so I would like to automate some rigorous testing. To do this I need to be to be able to route some TCP connections through my system, however, I don't want to have to rely on two other machines to act as client and server. I would prefer to run a local client that sends data and a local server that checks the mangled result.
The problem is that my application needs to intercept packets at the PREROUTING stage and so packets generated by the local client can't just be routed to the loopback interface.
So I need some way to inject packets before the prerouting stage and intercept them back after postrouting. If I could somehow use stream sockets to send and receive the data that would be great!
The most straightforward way I can think of doing this is to use a tun device. The tun device allows you to inject packets from userspace that appear to arrive through the tun interface. You could either write code to create and manipulate the tun interface yourself, or you can make use of an application like OpenVPN that already does this. With OpenVPN it would be easy: no special raw sockets or anything: you just send it IP packets encapsulated in UDP and it will make them arrive through a tun interface.
I've been thinking a bit about this and using the tun devices my client and server test applications should be able to use plain linux sockets. I will explain how this can work by describing the path of a packet sent by the test client.
Prerequisites:
a) Two tun devices each providing access to a distinct subnetwork
b) routing table was set up to route traffic to the correct tun device
1) the client sends a packet to an address in the tun1 subnetwork
2) the app attached to tun1 (tun1app) will translate the dst address of the packet to an address in tun2 subnetwork and the source address to an address in the tun1 subnetwork different from the address of the tun1 interface
3) tun1app will send the modified packet back out
4) after routing tun2app will receive the packet and translate the destination address to the tun2 interface and the source address to an address in the tun2 network different from the interface address
5) tun2app will send it back out and the server will receive the packet assuming the destination port is the one the server is listening on
Packets from the server will follow the inverse path.
This seems like the core idea of a very useful tool. Does anyone know of a tool that is able to do this?
All connections from-and-to localhost itself do go over PREROUTING and POSTROUTING. Whoever tells something else is mistaken. (You can verify that with ip6tables -t raw -I OUTPUT -j TRACE, and you will see that it passes through OUTPUT-POSTROUTING-PREROUTING-INPUT when, for example, you ping6 ::1 yourself.)

Resolving MAC address for IP address using C++ on Linux

I need to generate an Ethernet header that includes the destination MAC address, (since libnfnetlink gives only the IP header before prerouting takes place), the outgoing interface number is also known, so the lookup can be made in the correct network.
What's the library/function to resolve the MAC address from an IP address?
It's unclear why you need the MAC address, since that's usually handled for you at a lower level.
However, assuming your target is on your local Ethernet segment, you can use the arp command to look up values in the local cache. If the value is not cached... Well, that's a problem. Perhaps arping would help...
(Normally you'd send a packet to, for example, IP address 10.10.10.10, and your system would send an ARP packet out querying who-has 10.10.10.10, and a response would come back from that target system with its MAC address, and then it would be cached. (You can watch this happening with tcpdump.) Or when a system comes on line it would send out a broadcast message informing everyone else of its MAC address. Naturally, if your destination is on another Ethernet segment, you're routing to a gateway rather than directly to the destination, and no destination-MAC address is available.)
You might read further at:
http://linux.die.net/man/8/arp
http://linux.die.net/man/8/arping
http://linux.die.net/man/7/arp
http://www.kernel.org/doc/man-pages/online/pages/man7/arp.7.html
Obviously you can only find the MAC address for directly connected IP addresses, but there's no platform-independent way of doing it. On Linux, you can look in /proc/net/arp after sending something to the target to trigger the kernel to send the ARP.
Edit to add you could also use the SIOCGARP ioctl() though that just looks in the ARP cache, so it won't send an ARP if there isn't one already there.
Otherwise, you would have to craft your own ARP request packet. You could probably reuse a bunch of code from arping if you go that route.
You cannot in general get the MAC address from the IP address, and in fact as IP can run on data link protocols other than ethernet, some IP addresses have no corresponding MAC address.
The MAC address is only available and only relevant on the same ethernet segment. On that segment, it can be retrieved by an ARP request.

First packet to be sent when starting to browse

Imagine a user sitting at an Ethernet-connected PC. He has a browser open. He types "www.google.com" in the address bar and hits enter.
Now tell me what the first packet to appear on the Ethernet is.
I found this question here: Interview Questions on Socket Programming and Multi-Threading
As I'm not a networking expert, I'd like to hear the answer (I'd assume it is "It depends" ;) ).
With a tool like Wireshark, I can obviously check my own computers behaviour. I'd like to know whether the packets I see (e.g. ARP, DNS, VRRP) are the same in each ethernet configuration (is it dependent on the OS? the driver? the browser even :)?) and which are the conditions in which they appear. Being on the data-link layer, is it maybe even dependent on the physical network (connected to a hub/switch/router)?
The answers that talk about using ARP to find the DNS server are generally wrong.
In particular, IP address resolution for off-net IP addresses is never done using ARP, and it's not the router's responsibility to answer such an ARP query.
Off-net routing is done by the client machine knowing which IP addresses are on the local subnets to which it is connected. If the requested IP address is not local, then the client machine refers to its routing table to find out which gateway to send the packet to.
Hence in most circumstances the first packet sent out will be an ARP request to find the MAC address of the default gateway, if it's not already in the ARP cache.
Only then can it send the DNS query via the gateway. In this case the packet is sent with the DNS server's IP address in the IP destination field, but with the gateway's MAC address on the ethernet packet.
You can always download wireshark and take a look.
Though to spoil the fun.
Assuming, the IP address of the host is not cached, and the MAC address of the DNS server is not cached, the first thing that will be sent will be a broadcast ARP message trying to find out the MAC address of the DNS server (which the router will respond to with its own address).
Next, the host name will be resolved using DNS. Then the returned IP address will be resolved using ARP (again the router will respond with its own address), and finally, the HTTP message will actually be sent.
Actually, it depends on a variety of initial conditions you left unspecified.
Assuming the PC is running an operating system containing a local DNS caching resolver (mine does), the first thing that happens before any packets are sent is the cache is searched for an IP address. This is complicated, because "www.google.com" isn't a fully-qualified domain name, i.e. it's missing the trailing dot, so the DNS resolver will accept any records already in its cache that match its search domain list first. For example, if your search domain list is "example.com." followed by "yoyodyne.com." then cached resources matching the names "www.google.com.example.com." "www.google.com.yoyodyne.com." and finally "www.google.com." will be used if available. Also note: if the web browser is one of the more popular ones, and the PC is running a reasonably current operating system, and the host has at least one network interface with a global scope IPv6 address assigned (and the host is on a network where www.google.com has AAAA records in its DNS horizon), then the remote address of the server might be IPv6 not IPv4. This will be important later.
If the remote address of the Google web server was locally cached in DNS, and the ARP/ND6 cache contains an entry for the IPv4/IPv6 address (respectively) of a default router, then the first transmitted packet will be a TCP SYN packet sourced from the interface address attached to the router and destined for the cached remote IPv4/IPv6 address. Alternatively, the default router could be reachable over some kind of layer-2 or layer-3 tunnel, in which case, the SYN packet will be appropriately encapsulated.
If the remote address of the Google web server was not locally cached, then the host will first need to query for the A and/or AAAA records in the DNS domain search list in sequence until it gets a positive response. If the first DNS resolving server address in the resolver configuration is in one of the local IPv4 subnet ranges, or in a locally attached IPv6 prefix with the L=1 bit set in the router advertisement, and the ARP/ND6 cache already contains an entry for the address in question, then the first packet the host will send is a direct DNS query for either an A record or a AAAA record matching the first fully-qualified domain name in the domain search list. Alternatively, if the first DNS server is not addressable on-link, and a default router has an ARP/ND6 cache entry already, then the DNS query packet will be sent to the default router to forward to the DNS server.
In the event the local on-link DNS server or a default router (respectively, as the case above may be) has no entry in the ARP/ND6 cache, then the first packet the host will send is either an ARP request or an ICMP6 neighbor solicitation for the corresponding address.
Oh, but wait... it's even more horrible. There are tweaky weird edge cases where the first packet the host sends might be a LLMNR query, an IKE initiation, or... or... or... how much do you really care about all this, buckaroo?
It depends
Got that right. E.g. does the local DNS cache contain the address? If not then a DNS lookup is likely to be the first thing.
If the host name is not in DNS cache nor in hosts file, first packet will go to DNS.
Otherwise, the first packet will be HTTP GET.
Well, whatever you try to do, the first thing happening is some Ethernet protocol related data. Notably, Ethernet adapters have to decide whether the Ethernet bus is available (so there's some collision detection taking place here)
It's hard to answer your question because it depends a lot on the type of ethernet network you're using. More information on Ethernet transmission can be found here and here

Resources