Mitigate ARP poisoning by preventing overwrite#58
Mitigate ARP poisoning by preventing overwrite#58danielinux wants to merge 3 commits intowolfSSL:masterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR hardens wolfIP’s ARP neighbor learning to mitigate ARP-table poisoning by preventing existing neighbor entries from being overwritten by unsolicited ARP traffic, while still allowing updates when an ARP reply corresponds to a recently-sent ARP request.
Changes:
- Add tracking for recently-issued ARP requests (pending requests with TTL) to distinguish solicited vs unsolicited ARP replies.
- Prevent ARP requests and unsolicited ARP replies from overwriting an existing neighbor cache entry.
- Add unit tests covering: no-overwrite on unsolicited reply, overwrite allowed when reply matches a pending request, and no-overwrite on ARP request.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/wolfip.c | Adds pending-request tracking and changes ARP neighbor update rules to block unsolicited overwrites. |
| src/test/unit/unit.c | Adds/adjusts ARP unit tests to validate the new overwrite-prevention behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
When receiving unsolicited ARP traffic, wolfIP accepts neighbors addresses. This prevents overwriting/poisoning ARP tables when an attacker is trying to impersonate an existing neighbor. For latency/performance optimizations, wolfIP is currently still populating the neighbor cache based on valid ARP requests from neighbors, if neighbors were not known.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/wolfip.c:5284
arp_pending_record()is called before the send filter check and before verifying the ARP request is actually transmitted. IfwolfIP_filter_notify_eth()blocks sending (orll->sendis NULL), a pending entry is still recorded and an attacker can then send a spoofed ARP reply within the TTL that will be treated as solicited and allowed to update/overwrite the neighbor entry. Move the pending record to only occur after the send filter passes (and ideally only when the request is actually sent).
arp.tip = ee32(tip);
arp_pending_record(s, if_idx, tip);
if (ll->send) {
if (wolfIP_filter_notify_eth(WOLFIP_FILT_SENDING, s, if_idx, &arp.eth,
sizeof(struct arp_packet)) != 0)
return;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
| } | ||
|
|
||
| static int arp_neighbor_index(struct wolfIP *s, unsigned int if_idx, ip4 ip) |
There was a problem hiding this comment.
nit: missing docs.
this applies for all the new functions that were introduced.
in particular for this one I think it should be made clear that it returns index or -1, and that it envicts/removesss an entry if it aged out with the new mechanism of aging.
| arp->sip = ee32(conf->ip); | ||
| arp_store_neighbor(s, if_idx, ee32(sender_ip), sender_mac); | ||
| if (arp_neighbor_index(s, if_idx, ee32(sender_ip)) < 0) { | ||
| arp_store_neighbor(s, if_idx, ee32(sender_ip), sender_mac); |
There was a problem hiding this comment.
let me know if I understood this correctly: since the ARP_AGING_TIMEOUT is @ 120s, let's say a valid neighbor is added.
and like this neighbor only sends arp requests and no replies, it technicallly will age out right? and it will be removed via the index function, but then it will be ad dded later on again, it uses an entry for no reason and then it will get re-added again
| struct arp_neighbor neighbors[MAX_NEIGHBORS]; | ||
| struct arp_pending_req pending[WOLFIP_ARP_PENDING_MAX]; | ||
| } arp; | ||
| struct arp_pending_entry arp_pending[WOLFIP_ARP_PENDING_MAX]; |
There was a problem hiding this comment.
nit: maybe a a one-liner comment on arp_pending_req explaining the difference between arp_pending_req and arp_pending_entry would probably make it more readable to understand why two arrays are required
When receiving unsolicited ARP traffic, wolfIP
accepts neighbors addresses. This prevents overwriting/poisoning ARP tables when an attacker is trying to impersonate an existing neighbor.
For latency/performance optimizations, wolfIP is currently still populating the neighbor cache based on valid ARP requests from neighbors, if neighbors were not known.
Fenrir/226
edit: after Copilot's review, I decided to add an aging mechanism to limit issues with renewal of neighbors records. Also added tests to check aging.