Skip to content

Commit

Permalink
Adds compression pointer loop detection in Domain parsing (#87)
Browse files Browse the repository at this point in the history
* Adds compression pointer loop detection in Domain parsing

This adds a simple loop detection to the Domain parsing method.
Whenever a pointer offset has been seen before, the function
aborts by throwing an exception.
This prevents an infinite loop that could cause a DoS attack
by a specially crafted DNS response packet.

* Fix style

Co-authored-by: Mirza Kapetanovic <mirza.kapetanovic@gmail.com>
  • Loading branch information
danieljoos and kapetan committed Nov 24, 2021
1 parent cf7105a commit 18d8c5d
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 4 deletions.
12 changes: 10 additions & 2 deletions DNS/Protocol/Domain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ public static Domain FromArray(byte[] message, int offset, out int endOffset) {
bool endOffsetAssigned = false;
endOffset = 0;
byte lengthOrPointer;
HashSet<int> visitedOffsetPointers = new HashSet<int>();

while ((lengthOrPointer = message[offset++]) > 0) {
// Two heighest bits are set (pointer)
// Two highest bits are set (pointer)
if (lengthOrPointer.GetBitValueAt(6, 2) == 3) {
if (!endOffsetAssigned) {
endOffsetAssigned = true;
Expand All @@ -40,8 +41,15 @@ public static Domain FromArray(byte[] message, int offset, out int endOffset) {
ushort pointer = lengthOrPointer.GetBitValueAt(0, 6);
offset = (pointer << 8) | message[offset];

if (visitedOffsetPointers.Contains(offset)) {
throw new ArgumentException("Compression pointer loop detected");
}
visitedOffsetPointers.Add(offset);

continue;
} else if (lengthOrPointer.GetBitValueAt(6, 2) != 0) {
}

if (lengthOrPointer.GetBitValueAt(6, 2) != 0) {
throw new ArgumentException("Unexpected bit pattern in label length");
}

Expand Down
Binary file added Tests/Fixtures/Domain/pointer-loop
Binary file not shown.
12 changes: 10 additions & 2 deletions Tests/Protocol/ParseDomainTest.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using Xunit;
using System;
using Xunit;
using DNS.Protocol;

namespace DNS.Tests.Protocol {

public class ParseDomainTest {
[Fact]
public void EmptyDomain() {
Expand Down Expand Up @@ -91,5 +92,12 @@ public void PointerDomainWithMultipleLabelsPreceededByHeader() {
Assert.Equal(16, domain.Size);
Assert.Equal(30, endOffset);
}

[Fact]
public void PointerDomainLoopDetection() {
int endOffset = 0;
byte[] content = Helper.ReadFixture("Domain", "pointer-loop");
Assert.Throws<ArgumentException>(() => Domain.FromArray(content, 16, out endOffset));
}
}
}

0 comments on commit 18d8c5d

Please sign in to comment.