From b8e911a40af83a93b02d8dbdd87854510d00a623 Mon Sep 17 00:00:00 2001 From: Vitali Sepetnitsky Date: Wed, 16 Feb 2022 18:39:15 +0200 Subject: [PATCH 1/2] avoid infinite loop in V9ExportPacket's constructor --- netflow/v9.py | 12 ++++++++++++ tests/lib.py | 30 +++++++++++++++++++++++++++++- tests/test_netflow.py | 6 +++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/netflow/v9.py b/netflow/v9.py index 348deb8..6be32a1 100644 --- a/netflow/v9.py +++ b/netflow/v9.py @@ -499,6 +499,8 @@ class V9ExportPacket: if id_ not in self._templates: self._new_templates = True self._templates[id_] = template + if tfs.length == 0: + break offset += tfs.length continue @@ -510,6 +512,8 @@ class V9ExportPacket: self._new_templates = True self._templates[id_] = template offset += otfs.flowset_length + if otfs.flowset_length == 0: + break continue # Data / option flowsets @@ -518,6 +522,8 @@ class V9ExportPacket: # Could not be parsed, continue to check for templates skipped_flowsets_offsets.append(offset) offset += flowset_length + if flowset_length == 0: + break continue matched_template = self._templates[flowset_id] @@ -525,11 +531,17 @@ class V9ExportPacket: if isinstance(matched_template, V9TemplateRecord): dfs = V9DataFlowSet(data[offset:], matched_template) self._flows += dfs.flows + if dfs.length == 0: + break offset += dfs.length elif isinstance(matched_template, V9OptionsTemplateRecord): odfs = V9OptionsDataFlowset(data[offset:], matched_template) self._options += odfs.option_data_records + if odfs.length == 0: + break + if odfs.length == 0: + break offset += odfs.length else: diff --git a/tests/lib.py b/tests/lib.py index 5a06bda..0fdbb61 100644 --- a/tests/lib.py +++ b/tests/lib.py @@ -185,9 +185,37 @@ PACKETS_V9 = [ "0000bfee0000002f00000000000000000050ae56061b04007f0000017f000001fb3ddbb3fb3c1a18" "00000982000000270000000000000000ae560050061b04007f0000017f000001fb3ddbb3fb3c1a18" "0000130e0000001200000000000000000050e820061b04007f0000017f000001fb3ddbb3fb3c1a18" - "0000059c000000140000000000000000e8200050061b0400" + "0000059c000000140000000000000000e8200050061b0400", ] +PACKET_V9_WITH_PL = ( + "000900057b72e830620b717d78cf34e30102000001040048000000000000006e0000000101000000" + "000a20076a06065c0800000d6b15c80000000b7b72e4487b72e448080000000000000438bf6401c7" + "65ad1e0d6b15c8000000000001040048000000000000006700000001110000c951ac180b0306065c" + "080035010000010000000b7b72e4487b72e448000000000000000443177b01c765ada501000001c3" + "9c00350001040048000000000000004a000000010100000000ac19bc3206065c080000287048cd00" + "00000b7b72e8307b72e83008000000000000048f071a01c765ae42287048cd000000000001040048" + "000000000000004600000001060002cbef0a30681f06065c0801bb142a49180000000b7b72e8307b" + "72e8300000000000000004801c7801c765ae1d142a49185a2b01bb00010400480000000000000046" + "00000001060002fe800a2f601206065c0801bb142a49180000000b7b72e8307b72e8300000000000" + "0000040806b001c765ae28142a4918d4b501bb000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" +) + # Example export for IPFIX (v10) with 4 templates, 1 option template and 8 data flow sets PACKET_IPFIX_TEMPLATE = "000a05202d45a4700000001300000000000200400400000e00080004000c00040016000400150004" \ "0001000400020004000a0004000e000400070002000b00020004000100060001003c000100050001" \ diff --git a/tests/test_netflow.py b/tests/test_netflow.py index c145bef..a89bef2 100755 --- a/tests/test_netflow.py +++ b/tests/test_netflow.py @@ -13,7 +13,7 @@ import random import unittest from tests.lib import send_recv_packets, NUM_PACKETS, \ - PACKET_INVALID, PACKET_V1, PACKET_V5, \ + PACKET_INVALID, PACKET_V1, PACKET_V5, PACKET_V9_WITH_PL, \ PACKET_V9_TEMPLATE, PACKET_V9_TEMPLATE_MIXED, PACKETS_V9 @@ -119,6 +119,10 @@ class TestFlowExportNetflow(unittest.TestCase): pkts, _, _ = send_recv_packets([PACKETS_V9[0]]) self.assertEqual(len(pkts), 0) # no export is parsed due to missing template + # send an invalid packet with zero bytes, must fail to parse + pkts, _, _ = send_recv_packets([PACKET_V9_WITH_PL]) + self.assertEqual(len(pkts), 0) # no export is parsed due to missing template + # send packet with two templates and eight flows, should parse correctly since the templates are known pkts, _, _ = send_recv_packets([PACKET_V9_TEMPLATE]) self.assertEqual(len(pkts), 1) From 8b5675913decf25ef6278a9111a1b1a7311d8863 Mon Sep 17 00:00:00 2001 From: Dominik Pataky Date: Mon, 25 Apr 2022 20:26:04 +0200 Subject: [PATCH 2/2] Small changes to PR #37 preventing infinite loops; bump version Closes #37 --- netflow/v9.py | 2 -- setup.py | 2 +- tests/lib.py | 2 +- tests/test_netflow.py | 4 ++-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/netflow/v9.py b/netflow/v9.py index 6be32a1..d197dd0 100644 --- a/netflow/v9.py +++ b/netflow/v9.py @@ -538,8 +538,6 @@ class V9ExportPacket: elif isinstance(matched_template, V9OptionsTemplateRecord): odfs = V9OptionsDataFlowset(data[offset:], matched_template) self._options += odfs.option_data_records - if odfs.length == 0: - break if odfs.length == 0: break offset += odfs.length diff --git a/setup.py b/setup.py index b76f436..814a137 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ with open("README.md", "r") as fh: setup( name='netflow', - version='0.11.0', + version='0.11.1', description='NetFlow v1, v5, v9 and IPFIX tool suite implemented in Python 3', long_description=long_description, long_description_content_type='text/markdown', diff --git a/tests/lib.py b/tests/lib.py index 0fdbb61..7db164a 100644 --- a/tests/lib.py +++ b/tests/lib.py @@ -188,7 +188,7 @@ PACKETS_V9 = [ "0000059c000000140000000000000000e8200050061b0400", ] -PACKET_V9_WITH_PL = ( +PACKET_V9_WITH_ZEROS = ( "000900057b72e830620b717d78cf34e30102000001040048000000000000006e0000000101000000" "000a20076a06065c0800000d6b15c80000000b7b72e4487b72e448080000000000000438bf6401c7" "65ad1e0d6b15c8000000000001040048000000000000006700000001110000c951ac180b0306065c" diff --git a/tests/test_netflow.py b/tests/test_netflow.py index a89bef2..3949687 100755 --- a/tests/test_netflow.py +++ b/tests/test_netflow.py @@ -13,7 +13,7 @@ import random import unittest from tests.lib import send_recv_packets, NUM_PACKETS, \ - PACKET_INVALID, PACKET_V1, PACKET_V5, PACKET_V9_WITH_PL, \ + PACKET_INVALID, PACKET_V1, PACKET_V5, PACKET_V9_WITH_ZEROS, \ PACKET_V9_TEMPLATE, PACKET_V9_TEMPLATE_MIXED, PACKETS_V9 @@ -120,7 +120,7 @@ class TestFlowExportNetflow(unittest.TestCase): self.assertEqual(len(pkts), 0) # no export is parsed due to missing template # send an invalid packet with zero bytes, must fail to parse - pkts, _, _ = send_recv_packets([PACKET_V9_WITH_PL]) + pkts, _, _ = send_recv_packets([PACKET_V9_WITH_ZEROS]) self.assertEqual(len(pkts), 0) # no export is parsed due to missing template # send packet with two templates and eight flows, should parse correctly since the templates are known