Why do spoofed DNS packets get ignored?

3

0

First off, let me clarify that this question refers to a private project that is intended for educational purpose only.

I tried to write my own "DNS spoofer". Don't worry, this question is not related to any coding practices.

The current setup

The operating machine is a MacBook (with OSX) in a local network (so there're some other unimportant devices as well). There's a basic router that uses another machine (also in the local network) as local DNS server. Although this setup is a little unusual, it should not be the cause of the issue (described below).

The goal

DNS Spoofing - when the MacBook sends a DNS request, send an answer with a fake IP address.

My current approach

I use BPF (Berkeley Packet Filter) to get raw access to the data link layer.

Now, I'm listening for/capturing any queries on the Ethernet network interface of the MacBook (referred to as "MB" in the following part).

I disabled IPv6 on the MB.

I delete the DNS cache on the MB with the following commands:

sudo killall -HUP mDNSResponder;sudo killall mDNSResponderHelper;sudo dscacheutil -flushcache

Procedure

  1. MB sends a DNS request with some queries
  2. I create a DNS response with the same queries and answers to all A-Type (IPv4) queries and send this response
  3. The MB receives two responses: my fake response first, then the real one sent by the real local DNS server

Each fake DNS response packet will include:

  • the Ethernet MAC address of the requested DNS server as Ethernet source address
  • the IP address of the requested DNS server as IP source address
  • the port 53 as source port
  • the port as destination port that the DNS request originated from
  • a correct IP header checksum
  • a correct UDP checksum
  • a correct Frame Check Sequence/Ethernet Checksum.

Each DNS response is sent over the same network interface I'm listening on.

Whenever a query is sent, there'll be two responses:

  1. the first one sent immediately by the "DNS spoofer", the 'fake' packet/DNS response, arrives before the second
  2. the second one, the 'real' DNS response, sent by the local DNS server.

I also assumed (although I'm not sure about this) that OSX always picks the first DNS response it gets to resolve a domain name to its IP address.

To sum this up; both DNS responses are equal except that the checksums and the DNS answer IP addresses are different. Also, the 'real' DNS server does not send (for what reason ever) an FCS (Frame Check Sequence). I do, although it is not calculated and just set to zero (zeroed-out).

Issue

OSX seems to ignore the fake DNS responses. Might also be that the OS is overstrained; the behaviour when using Safari to open a Website is the following:

When using Safari and typing "http://some-url.com" into the address bar, nothing happens. It does not connect to the real site nor does it connect to the fake page. The page seems to load forever. Sometimes, after a decade, it connects to the real page.

Example (captured with Wireshark)

A random example.

Request: 
0000   b8 27 eb b9 a0 0f a0 ce c8 10 75 8c 08 00 45 00   
0010   00 33 74 2c 00 00 ff 11 62 06 c0 a8 b2 1f c0 a8   .3t,..ÿ.b.À¨².À¨
0020   b2 16 f2 7e 00 35 00 1f 49 71 67 00 01 00 00 01   ².ò~.5..Iqg.....
0030   00 00 00 00 00 00 01 32 03 63 6f 6d 00 00 01 00   .......2.com....
0040   01                                                .



Fake Response:
0000   a0 ce c8 10 75 8c b8 27 eb b9 a0 0f 08 00 45 00   
0010   00 43 12 34 00 00 40 11 82 ef c0 a8 b2 16 c0 a8   .C.4..@..ïÀ¨².À¨
0020   b2 1f 00 35 f2 7e 00 2f 46 44 67 00 81 80 00 01   ²..5ò~./FDg.....
0030   00 01 00 00 00 00 01 32 03 63 6f 6d 00 00 01 00   .......2.com....
0040   01 c0 0c 00 01 00 01 00 00 07 08 00 04 ac d9 17   .À...........¬Ù.
0050   8e 22 4f 80 1c                                    ."O..



Real Response:
0000   a0 ce c8 10 75 8c b8 27 eb b9 a0 0f 08 00 45 00   
0010   00 7c 9c 19 40 00 40 11 b8 d0 c0 a8 b2 16 c0 a8   .|..@.@.¸ÐÀ¨².À¨
0020   b2 1f 00 35 f2 7e 00 68 83 00 67 00 81 83 00 01   ²..5ò~.h..g.....
0030   00 00 00 01 00 00 01 32 03 63 6f 6d 00 00 01 00   .......2.com....
0040   01 c0 0e 00 06 00 01 00 00 03 84 00 3d 01 61 0c   .À..........=.a.
0050   67 74 6c 64 2d 73 65 72 76 65 72 73 03 6e 65 74   gtld-servers.net
0060   00 05 6e 73 74 6c 64 0c 76 65 72 69 73 69 67 6e   ..nstld.verisign
0070   2d 67 72 73 c0 0e 5c 83 f7 73 00 00 07 08 00 00   -grsÀ.\.÷s......
0080   03 84 00 09 3a 80 00 01 51 80                     ....:...Q.

1] 2]

Any help is highly appreciated. If you need more detail, let me know. If you'd like a bounty, let me know.

user0800

Posted 2019-03-08T16:46:03.223

Reputation: 111

1what do you mean "genuine IP address 999.999.999.999"? – Attie – 2019-03-08T16:49:55.100

"genuine" shall mean "real", "true", "original" IP address. 999.999.999.999 is not a real IP address, I didn't want to use a real one. @Attie Is that the reason for the downvote? – user0800 – 2019-03-08T17:04:46.107

I didn't down vote... but you've asked so many questions, gone into depth in weird places, and made so many murky statements that this is very hard to respond to in its current state - 999.999.999.999, "malicious", "Frame Check Sequence". etc... Try to cut out 80% of the content of your question, and focus on what your problem is, asking a single question if possible, and give examples. – Attie – 2019-03-08T17:59:13.180

Look into things like HSTS and DKIM to understand why this might not be working for facebook.com... try using a random / non-existent domain to base your tests on initially. – Attie – 2019-03-08T18:03:02.600

@T.Meyer this is the sort of thing you bring to a professor at a university, get an answer for an hour, and several pieces of homework just to address the questions in the original text. SuperUser is not the place to get the answers to this. – Christopher Hostage – 2019-03-08T21:31:22.853

Alright, sorry, I didn't mean to put the blame on you. I just don't like people who downvote without leaving a comment about why they did so. I just tried to clarify my question. Thanks for your help. @Attie – user0800 – 2019-03-08T21:33:24.527

Hmm, you mean it's still too broad? Are you referring to the question after my latest change? I'm not in university. @ChristopherHostage – user0800 – 2019-03-08T21:39:04.793

1@ChristopherHostage maybe this seems daunting to you because you don't know these topics, but as someone who knows Ethernet and DNS internals well, and has done a fair bit of packet capture and injection, this seems like a completely tractable problem, nothing requiring an hour from a university professor. – Spiff – 2019-03-08T23:15:11.790

Please review https://superuser.com/help/how-to-ask .

– Christopher Hostage – 2019-03-08T23:40:10.017

Useful info: The basic DNS protocol does not authenticate responses to recursive queries. DNS spoofing is based on the fact the the first arriving UDP packet which satisfies these conditions is treated as a valid response from the authoritative server: (1) the query section and 16-bit transaction ID (TXID) of the response must match those of the query, and (2) the source IP address and destination port of the response must match, respectively, the destination IP address and source port of the query. Question: How are you getting all these values? – harrymc – 2019-05-29T14:16:08.550

Might the OS perform some authentication checks though? To answer your question - Sniffing? Doesn't Wireshark do the same? Nothing more. I basically "copy" the request, add my part (the response) to the packet, set the correct addresses, calculate some checksums and that's it. – user0800 – 2019-05-29T14:18:52.700

I know that it's difficult to find out the transaction ID (TXID). One exploit I know of is based on guessing very rapidly multiple times, because only one success is needed. – harrymc – 2019-05-29T15:50:12.920

Sorry, I don't get you @harrymc. What do you mean by "it's difficult to find out the TXID"? It's the first 16 bits of the DNS header. That's it. I don't know what you're referring to, sorry. Could you clarify or elaborate? – user0800 – 2019-05-29T17:59:09.290

Yes, if you are intercepting the request. I suppose you also spoof the source-IP of the packet you are sending? You are sure that the port number is correct and that the DNS client doesn't randomize it? – harrymc – 2019-05-30T13:41:21.760

I do. I basically „copy“ all layers up to DNS (and change the values accordingly). The DNS client (the MacBook) chooses a random port. But that‘s not a problem as I just copy the source port and send the response right back to it. @harrymc – user0800 – 2019-06-02T09:18:15.183

Cyber Security. Not having it, but building it. @BeowulfNode42 – user0800 – 2019-06-02T09:53:18.277

2I'd "divide and conquer": Test your spoofing against some application that won't care about the content, e.g. nc/netcat/socat listening for UDP packets. If that works, the problem is in the fake DNS response. If it doesn't work, the problem is in the spoofing. – dirkt – 2019-06-02T09:55:11.977

Answers

4

First, Ethernet frames always have FCSes on the wire, but not all Ethernet NICs keep the FCS attached when they pass the received frame up to the host, which means your sniffer can't always see the FCS or know if it was valid or invalid.

So you need to get your FCSes right.

If you don't know for a fact that the version of BPF on your injector/spoofer device's platform, or its NIC driver or hardware, is going to calculate the correct FCS for you if omit it or pad it with zeroes, then you probably have to figure that out first. My guess is that it will NOT fix it for you if you try to inject a packet without it set correctly, so you will probably need to calculate it yourself and insert the correct value at the end of your packet buffer before doing your bpf_write().

Second, I'm just eyeballing your hex dumps, but if I'm mentally decoding it correctly, your DiffServ field looks bogus. Default it to 0x00 instead of 0xff if you don't know what to do with it.

Third, your IP total length field looks bogus (zero). You probably need to calculate it and set it correctly. Be sure to do that before calculating your checksums.

Nothing else jumps out at me. So if I were you, I'd fix those three problems and try again.

Spiff

Posted 2019-03-08T16:46:03.223

Reputation: 84 656

That's a seriously nice answer, however, after fixing those three problems, DNS packets still get ignored. I added some photos to my question. – user0800 – 2019-03-09T11:32:19.620

@T.Meyer can you update your example dumps with a new set now that you've corrected the problems we already identified? – Spiff – 2019-03-09T17:08:49.520

Sure. Done @Spiff – user0800 – 2019-03-09T17:31:18.653

@T.Meyer I pasted your new dumps into a text file and used Wireshark's "File > Import from Hex Dump…" command to import them, and Wireshark likes the real packets but says your spoofed packet's FCS is still wrong: "Frame check sequence: 0x224f801c incorrect, should be 0x94b67845" – Spiff – 2019-03-09T17:48:39.147

1@T.Meyer Also, you're now using a multicast address as one of your should-be-unicast MAC addresses, so that's something else that needs to get fixed. – Spiff – 2019-03-09T17:53:21.900

Darn, that's because "foolish me" changed the MAC addresses before uploading. Changed them back. Sorry for the inconvenience. Wireshark totally accepts the fake packet. It just doesn't like the real one. @Spiff – user0800 – 2019-03-09T18:02:10.317

"Wireshark totally accepts the fake packet" I didn't mean that the fake packets are now accepted by the NIC. They're still ignored, only Wireshark likes them. They still get dropped. Just to clarify. @Spiff – user0800 – 2019-03-10T11:23:10.203