Skip to content

Commit a57d3d9

Browse files
committed
Reject parsing incomplete DNS response messages
1 parent 6f2f761 commit a57d3d9

2 files changed

Lines changed: 43 additions & 19 deletions

File tree

src/Protocol/Parser.php

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ private function parse($data, Message $message)
6666

6767
public function parseHeader(Message $message)
6868
{
69-
if (strlen($message->data) < 12) {
69+
if (!isset($message->data[12 - 1])) {
7070
return;
7171
}
7272

@@ -97,19 +97,11 @@ public function parseHeader(Message $message)
9797

9898
public function parseQuestion(Message $message)
9999
{
100-
if (strlen($message->data) < 2) {
101-
return;
102-
}
103-
104100
$consumed = $message->consumed;
105101

106102
list($labels, $consumed) = $this->readLabels($message->data, $consumed);
107103

108-
if (null === $labels) {
109-
return;
110-
}
111-
112-
if (strlen($message->data) - $consumed < 4) {
104+
if ($labels === null || !isset($message->data[$consumed + 4 - 1])) {
113105
return;
114106
}
115107

@@ -133,19 +125,11 @@ public function parseQuestion(Message $message)
133125

134126
public function parseAnswer(Message $message)
135127
{
136-
if (strlen($message->data) < 2) {
137-
return;
138-
}
139-
140128
$consumed = $message->consumed;
141129

142130
list($labels, $consumed) = $this->readLabels($message->data, $consumed);
143131

144-
if (null === $labels) {
145-
return;
146-
}
147-
148-
if (strlen($message->data) - $consumed < 10) {
132+
if ($labels === null || !isset($message->data[$consumed + 10 - 1])) {
149133
return;
150134
}
151135

@@ -163,6 +147,10 @@ public function parseAnswer(Message $message)
163147
list($rdLength) = array_values(unpack('n', substr($message->data, $consumed, 2)));
164148
$consumed += 2;
165149

150+
if (!isset($message->data[$consumed + $rdLength - 1])) {
151+
return;
152+
}
153+
166154
$rdata = null;
167155

168156
if (Message::TYPE_A === $type || Message::TYPE_AAAA === $type) {
@@ -262,6 +250,7 @@ private function readLabels($data, $consumed)
262250

263251
$consumed += 2;
264252
list($newLabels) = $this->readLabels($data, $offset);
253+
265254
if ($newLabels === null) {
266255
return array(null, null);
267256
}

tests/Protocol/ParserTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,41 @@ public function testParseInvalidOffsetPointerToStartOfMessageInQuestionNameThrow
690690
$this->parser->parseMessage($data);
691691
}
692692

693+
/**
694+
* @expectedException InvalidArgumentException
695+
*/
696+
public function testParseIncompleteAnswerFieldsThrows()
697+
{
698+
$data = "";
699+
$data .= "72 62 81 80 00 01 00 01 00 00 00 00"; // header
700+
$data .= "04 69 67 6f 72 02 69 6f 00"; // question: igor.io
701+
$data .= "00 01 00 01"; // question: type A, class IN
702+
$data .= "c0 0c"; // answer: offset pointer to igor.io
703+
704+
$data = $this->convertTcpDumpToBinary($data);
705+
706+
$this->parser->parseMessage($data);
707+
}
708+
709+
/**
710+
* @expectedException InvalidArgumentException
711+
*/
712+
public function testParseIncompleteAnswerRecordDataThrows()
713+
{
714+
$data = "";
715+
$data .= "72 62 81 80 00 01 00 01 00 00 00 00"; // header
716+
$data .= "04 69 67 6f 72 02 69 6f 00"; // question: igor.io
717+
$data .= "00 01 00 01"; // question: type A, class IN
718+
$data .= "c0 0c"; // answer: offset pointer to igor.io
719+
$data .= "00 01 00 01"; // answer: type A, class IN
720+
$data .= "00 01 51 80"; // answer: ttl 86400
721+
$data .= "00 04"; // answer: rdlength 4
722+
723+
$data = $this->convertTcpDumpToBinary($data);
724+
725+
$this->parser->parseMessage($data);
726+
}
727+
693728
private function convertTcpDumpToBinary($input)
694729
{
695730
// sudo ngrep -d en1 -x port 53

0 commit comments

Comments
 (0)