InjCname - CNAME Record Injection

InjCname - CNAME Record Injection

This module was designed for cache poisoning experiments, specifically for injecting unsolicited CNAME records into responses.

The module can handle queries for the following record types:

  • A (Address Record)
  • AAAA (IPv6 Address Record)
  • CNAME (Canonical Name)
  • DNAME (Delegation Name)
  • MX (Mail Exchange)
  • NS (Name Server)
  • PTR (Pointer)

When a query for any of these record types is received, the module responds with a standard answer based on the requested type. Additionally, it includes an unsolicited CNAME record in the response, aiming for the resolver to pick it up and store it in its cache.

If successful, this means we can inject DNS records into the resolver's cache by including unsolicited records in the responses from the server-side.

Category: Cache poisoning

Format

injcname[N].[3rp].[rpq].[adq].[rev].[als].[oi].yourdomain.com

Where:

  • The N optional parameter is an arbitrary number used as an identifier appended to the injected domain name. This helps label and distinguish the specific domain name being injected.
  • The 3rp optional parameter uses a 3rd-party parent domain (such as a3rdparty.net) for the injected record, instead of the yourdomain.com (default). If successful, the impact would be much more serious, as it would allow the injection of information for an arbitrary 3rd-party domain.
  • The rpq (replace question) optional parameter replaces the question in the query section with the domain name matching the injected record, potentially convincing the resolver that it originally requested the unsolicited record.
  • The adq (add question) optional parameter adds an additional question in the query section asking for the injected record, which could similarly convince the resolver that it requested the unsolicited record.
  • The rev (reverse) optional parameter reverses the order of answers — placing the unsolicited record first, followed by the actual answer to the query.
  • The als (all sections) optional parameter places the unsolicited records in all three sections (ANSWER, AUTHORITY and ADDITIONAL), instead of just in the ANSWER section. This approach can potentially increase the likelihood of the injected information being picked up and stored.
  • The oi (only injected) optional parameter causes the response to contain only the unsolicited record, omitting the actual answer to the query entirely.

Note that all these parameters can be combined with one another to produce different injection variants.

Examples

In this example, we demonstrate the basic functionality. By default, the injected record appears as the second answer, following the first (legitimate) answer. The injected record unsolicitedly resolves a subdomain under the same parent domain. In the subsequent query, we verify whether the resolver picked up and cached the unsolicited record:

# dig injcname.yourdomain.com @10.211.55.2

; <<>> DiG 9.18.10-2-Debian <<>> injcname.yourdomain.com @10.211.55.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30059
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;injcname.yourdomain.com.	IN	A

;; ANSWER SECTION:
injcname.yourdomain.com. 60	IN	A	1.2.3.4
injected.yourdomain.com. 60	IN	CNAME	always940900.yourdomain.com.

;; Query time: 3 msec
;; SERVER: 10.211.55.2#53(10.211.55.2) (UDP)
;; WHEN: Tue Jan 14 13:27:23 +04 2025
;; MSG SIZE  rcvd: 121


# dig injected.yourdomain.com @10.211.55.2 +norecurse

; <<>> DiG 9.18.10-2-Debian <<>> injected.yourdomain.com @10.211.55.2 +norecurse
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 25096
;; flags: qr aa; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;injected.yourdomain.com.	IN	A

;; Query time: 7 msec
;; SERVER: 10.211.55.2#53(10.211.55.2) (UDP)
;; WHEN: Tue Jan 14 13:27:23 +04 2025
;; MSG SIZE  rcvd: 41

Download PCAP File

We can see that the injected record was not cached, as we received NXDOMAIN (No such name) status. This means that the injection did not succeed.


In this example, we use the identifier 123 to label the injected domain name, resulting in the generation of a specific domain name with the same label:

# dig injcname123.yourdomain.com @10.211.55.2

; <<>> DiG 9.18.10-2-Debian <<>> injcname123.yourdomain.com @10.211.55.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3799
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;injcname123.yourdomain.com.	IN	A

;; ANSWER SECTION:
injcname123.yourdomain.com. 60	IN	A	1.2.3.4
injected123.yourdomain.com. 60	IN	CNAME	always495849.yourdomain.com.

;; Query time: 3 msec
;; SERVER: 10.211.55.2#53(10.211.55.2) (UDP)
;; WHEN: Tue Jan 14 13:27:24 +04 2025
;; MSG SIZE  rcvd: 127

Download PCAP File

This helps in identifying specific test cases during the testing process.


As mentioned earlier, this module can respond to various record types, not just A records. In this example, we request an NS record. As a result, we receive a valid NS record followed by an unsolicited CNAME record:

# dig NS injcname.yourdomain.com @10.211.55.2

; <<>> DiG 9.18.10-2-Debian <<>> NS injcname.yourdomain.com @10.211.55.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56323
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;injcname.yourdomain.com.	IN	NS

;; ANSWER SECTION:
injcname.yourdomain.com. 60	IN	NS	always326907.yourdomain.com.
injected.yourdomain.com. 60	IN	CNAME	always259864.yourdomain.com.

;; Query time: 3 msec
;; SERVER: 10.211.55.2#53(10.211.55.2) (UDP)
;; WHEN: Tue Jan 14 13:27:25 +04 2025
;; MSG SIZE  rcvd: 146

Download PCAP File

The module can handle A, AAAA, CNAME, DNAME, MX, NS and PTR record queries.


In the following example, we use the 3rp (3rd-party) parameter to request that the unsolicited record contain a subdomain under a 3rd-party parent domain. If successful, this scenario would have a much greater impact. In the subsequent query, we verify again whether the resolver picked up and cached the unsolicited record:

# dig injcname123.3rp.yourdomain.com @10.211.55.2

; <<>> DiG 9.18.10-2-Debian <<>> injcname123.3rp.yourdomain.com @10.211.55.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30293
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;injcname123.3rp.yourdomain.com.	IN	A

;; ANSWER SECTION:
injcname123.3rp.yourdomain.com.	60 IN	A	1.2.3.4
injected123.a3rdparty.net. 60	IN	CNAME	always079390.yourdomain.com.

;; Query time: 7 msec
;; SERVER: 10.211.55.2#53(10.211.55.2) (UDP)
;; WHEN: Tue Jan 14 13:27:27 +04 2025
;; MSG SIZE  rcvd: 130


# dig injected123.a3rdparty.net @10.211.55.2 +norecurse

; <<>> DiG 9.18.10-2-Debian <<>> injected123.a3rdparty.net @10.211.55.2 +norecurse
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 15734
;; flags: qr aa; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;injected123.a3rdparty.net.	IN	A

;; Query time: 0 msec
;; SERVER: 10.211.55.2#53(10.211.55.2) (UDP)
;; WHEN: Tue Jan 14 13:27:27 +04 2025
;; MSG SIZE  rcvd: 43

Download PCAP File

We can see that the injected record was not cached, as we received NXDOMAIN (No such name) status. This means that the injection did not succeed.


In this example, we use the rev parameter to reverse the order of answers — the unsolicited record appears first, followed by the legitimate one. This arrangement could potentially increase the likelihood of the injected information being picked up and cached:

# dig injcname123.3rp.rev.yourdomain.com @10.211.55.2

; <<>> DiG 9.18.10-2-Debian <<>> injcname123.3rp.rev.yourdomain.com @10.211.55.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14613
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;injcname123.3rp.rev.yourdomain.com. IN	A

;; ANSWER SECTION:
injected123.a3rdparty.net. 60	IN	CNAME	always189711.yourdomain.com.
injcname123.3rp.rev.yourdomain.com. 60 IN A	1.2.3.4

;; Query time: 7 msec
;; SERVER: 10.211.55.2#53(10.211.55.2) (UDP)
;; WHEN: Tue Jan 14 13:27:28 +04 2025
;; MSG SIZE  rcvd: 134

Download PCAP File


In this example, we use the rpq parameter to replace the question in the query section with information from the unsolicited record, in an attempt to convince the resolver that it originally requested this record:

# dig injcname12345.rpq.yourdomain.com @10.211.55.2

;; ;; Question section mismatch: got injected12345.yourdomain.com/CNAME/IN
;; communications error to 10.211.55.2#53: timed out
;; ;; Question section mismatch: got injected12345.yourdomain.com/CNAME/IN
;; communications error to 10.211.55.2#53: timed out
;; ;; Question section mismatch: got injected12345.yourdomain.com/CNAME/IN
;; communications error to 10.211.55.2#53: timed out

; <<>> DiG 9.18.10-2-Debian <<>> injcname12345.rpq.yourdomain.com @10.211.55.2
;; global options: +cmd
;; no servers could be reached

We can see that the client (dig) did not accept the response because the question (in the response) did not match the question in the original query. Here is the actual DNS response that was sent back to dig in this case:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53715
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;injected12345.yourdomain.com.  IN      CNAME

;; ANSWER SECTION:
injcname12345.rpq.yourdomain.com. 60      IN      A       1.2.3.4
injected12345.yourdomain.com. 60      IN      CNAME   always198181.yourdomain.com.

Download PCAP File

We can see that the question (query) was replaced to match the unsolicited record. The question remains as to how different resolvers would handle such a scenario — some resolvers may potentially accept this response.


In the next example, we use the adq parameter to add the question in the response asking for the unsolicited record, as another attempt to convince the resolver that it originally requested this record. We can see again that the client (dig) does not accept this response because the question does not match the original query:

# dig injcname12345.adq.yourdomain.com @10.211.55.2

;; Warning: Message parser reports malformed message packet.
;; ;; Question section mismatch: got injected12345.yourdomain.com/CNAME/IN
;; communications error to 10.211.55.2#53: timed out
;; Warning: Message parser reports malformed message packet.
;; ;; Question section mismatch: got injected12345.yourdomain.com/CNAME/IN
;; communications error to 10.211.55.2#53: timed out
;; Warning: Message parser reports malformed message packet.
;; ;; Question section mismatch: got injected12345.yourdomain.com/CNAME/IN
;; communications error to 10.211.55.2#53: timed out

; <<>> DiG 9.18.10-2-Debian <<>> injcname12345.adq.yourdomain.com @10.211.55.2
;; global options: +cmd
;; no servers could be reached

The question remains as to how different resolvers would handle this scenario. Here is the actual DNS response that was generated and returned to dig in this case:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38401
;; flags: qr aa; QUERY: 2, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;injcname12345.adq.yourdomain.com. IN      A
;injected12345.yourdomain.com.  IN      CNAME

;; ANSWER SECTION:
injcname12345.adq.yourdomain.com. 60      IN      A       1.2.3.4
injected12345.yourdomain.com. 60      IN      CNAME   always391458.yourdomain.com.

Download PCAP File

We can see that there are two questions — the original query and an additional one matching the unsolicited record.


In this example, the oi (only injected) parameter causes the answers to include only the injected (unsolicited) record, without the actual answer to the original query:

# dig injcname.oi.yourdomain.com @10.211.55.2

; <<>> DiG 9.18.10-2-Debian <<>> injcname.oi.yourdomain.com @10.211.55.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3194
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;injcname.oi.yourdomain.com.	IN	A

;; ANSWER SECTION:
injected.yourdomain.com. 60	IN	CNAME	always314551.yourdomain.com.

;; Query time: 3 msec
;; SERVER: 10.211.55.2#53(10.211.55.2) (UDP)
;; WHEN: Tue Jan 14 13:28:02 +04 2025
;; MSG SIZE  rcvd: 108

Download PCAP File

Note that the question remains the same as in the original query.


Here, we also request to replace the question in the query section with the unsolicited domain name. We can see that the dig client does not accept the response again because the question does not match the original query:

# dig injcname.oi.rpq.yourdomain.com @10.211.55.2

;; ;; Question section mismatch: got injected.yourdomain.com/CNAME/IN
;; communications error to 10.211.55.2#53: timed out
;; ;; Question section mismatch: got injected.yourdomain.com/CNAME/IN
;; communications error to 10.211.55.2#53: timed out
;; ;; Question section mismatch: got injected.yourdomain.com/CNAME/IN
;; communications error to 10.211.55.2#53: timed out

; <<>> DiG 9.18.10-2-Debian <<>> injcname.oi.rpq.yourdomain.com @10.211.55.2
;; global options: +cmd
;; no servers could be reached

The question remains as to how different resolvers would handle such a scenario. Here is the actual DNS response that was sent back to dig in this case:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41971
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;injected.yourdomain.com.       IN      CNAME

;; ANSWER SECTION:
injected.yourdomain.com. 60      IN      CNAME   always860204.yourdomain.com.

Download PCAP File

Some resolvers may potentially accept this response.


Lastly, in this example, we use the als (all sections) parameter to include the records in all sections of the DNS response:

# dig injcname.als.yourdomain.com @10.211.55.2

; <<>> DiG 9.18.10-2-Debian <<>> injcname.als.yourdomain.com @10.211.55.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13355
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;injcname.als.yourdomain.com.	IN	A

;; ANSWER SECTION:
injcname.als.yourdomain.com. 60	IN	A	1.2.3.4
injected.yourdomain.com. 60	IN	CNAME	always461965.yourdomain.com.

;; AUTHORITY SECTION:
injcname.als.yourdomain.com. 60	IN	A	1.2.3.4
injected.yourdomain.com. 60	IN	CNAME	always461965.yourdomain.com.

;; ADDITIONAL SECTION:
injcname.als.yourdomain.com. 60	IN	A	1.2.3.4
injected.yourdomain.com. 60	IN	CNAME	always461965.yourdomain.com.

;; Query time: 8 msec
;; SERVER: 10.211.55.2#53(10.211.55.2) (UDP)
;; WHEN: Tue Jan 14 13:28:20 +04 2025
;; MSG SIZE  rcvd: 285

Download PCAP File

This could potentially increase the likelihood of the injected information being picked up and stored.

Keep in mind that all these parameters can be combined to create different injection variants.


From the same category


Go back to catalogue.