From 2927cc71ced18de78715cb655b28e9716f03f0aa Mon Sep 17 00:00:00 2001 From: ArnoStiefvater Date: Fri, 28 Aug 2020 15:04:47 +0200 Subject: [PATCH 1/7] Add new interface for adding alive test methods Instead of using a bit flag which entails all alive tests we can now also use xml elements for every alive test method. --- ospd/protocol.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/ospd/protocol.py b/ospd/protocol.py index bcfb5a0e..259f19ff 100644 --- a/ospd/protocol.py +++ b/ospd/protocol.py @@ -146,6 +146,32 @@ def process_credentials_elements(cred_tree: Element) -> Dict: return credentials + @staticmethod + def process_alive_test_methods(cred_tree: Element, options: Dict) -> None: + """ Receive an XML object with the alive test methods to run + a scan with. Methods are added to the options Dict. + + @param + + + + + + 0 + + """ + for child in cred_tree: + if child.tag == 'icmp': + options['icmp'] = child.text + if child.tag == 'tcp_ack': + options['tcp_ack'] = child.text + if child.tag == 'tcp_syn': + options['tcp_syn'] = child.text + if child.tag == 'arp': + options['arp'] = child.text + if child.tag == 'consider_alive': + options['consider_alive'] = child.text + @classmethod def process_target_element(cls, scanner_target: Element) -> Dict: """Receive an XML object with the target, ports and credentials to run @@ -222,6 +248,9 @@ def process_target_element(cls, scanner_target: Element) -> Dict: ports = child.text if child.tag == 'credentials': credentials = cls.process_credentials_elements(child) + if child.tag == 'alive_test_methods': + options['alive_test_methods'] = '1' + cls.process_alive_test_methods(child, options) if child.tag == 'alive_test': options['alive_test'] = child.text if child.tag == 'alive_test_ports': From 2a24d95ee8d223efcd0fd4d16a3413bd4f38af73 Mon Sep 17 00:00:00 2001 From: ArnoStiefvater Date: Mon, 12 Oct 2020 14:57:43 +0200 Subject: [PATCH 2/7] Add documentation for alive_test_methods element --- doc/OSP.xml | 69 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/doc/OSP.xml b/doc/OSP.xml index d334639d..40ed4380 100644 --- a/doc/OSP.xml +++ b/doc/OSP.xml @@ -179,8 +179,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. credentials exclude_hosts finished_hosts - alive_test alive_test_ports + + alive_test + alive_test_methods + reverse_lookup_unify reverse_lookup_only @@ -196,45 +199,89 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. credentials - One or many credentials containing the credential for the given hosts. + One or many credentials containing the credential for the given hosts credential exclude_hosts - One or many hosts to exclude. The list is comma-separated. Each entry can be a IP address, a CIDR notation, a hostname, a IP range. IPs can be v4 or v6. Each wrapper must handle the exclude hosts. + One or many hosts to exclude. The list is comma-separated. Each entry can be a IP address, a CIDR notation, a hostname, a IP range. IPs can be v4 or v6. Each wrapper must handle the exclude hosts string finished_hosts - One or many finished hosts to exclude when the client resumes a task. The list is comma-separated. Each entry can be an IP address, a CIDR notation, a hostname, a IP range. IPs can be v4 or v6. The listed hosts will be set as finished before starting the scan. Each wrapper must handle the finished hosts. + One or many finished hosts to exclude when the client resumes a task. The list is comma-separated. Each entry can be an IP address, a CIDR notation, a hostname, a IP range. IPs can be v4 or v6. The listed hosts will be set as finished before starting the scan. Each wrapper must handle the finished hosts string alive_test - Alive test type to be performed against the target. - string + Alive test type to be performed against the target + integer + + + alive_test_methods + Alive test methods to be performed against the target + + icmp + + + icmp + ICMP ping + boolean + + + tcp_syn + + + tcp_syn + TCP-SYN ping + boolean + + + tcp_ack + + + tcp_ack + TCP-ACK ping + boolean + + + arp + + + arp + ARP ping + boolean + + + consider_alive + + + consider_alive + Consider the target to be alive + boolean + alive_test_ports - Dedicated port list for alive detection. Used for TCP-SYN and TCP-ACK ping when Boreas (scanner preference test_alive_hosts_only) is enabled. If no port list is provided ports 80, 137, 587, 3128, 8081 are used as defaults. + Dedicated port list for alive detection. Used for TCP-SYN and TCP-ACK ping when Boreas (scanner preference test_alive_hosts_only) is enabled. If no port list is provided ports 80, 137, 587, 3128, 8081 are used as defaults string reverse_lookup_only - Only scan IP addresses that can be resolved into a DNS name. + Only scan IP addresses that can be resolved into a DNS name string reverse_lookup_unify - If multiple IP addresses resolve to the same DNS name the DNS name will only get scanned once. + If multiple IP addresses resolve to the same DNS name the DNS name will only get scanned once string - Target without credentials. + Target without credentials example.org @@ -247,7 +294,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - Target with two credentials. + Target with two credentials 192.168.1.0/24 From a08403890c64933925ada016227c53ffe48baf97 Mon Sep 17 00:00:00 2001 From: ArnoStiefvater Date: Tue, 13 Oct 2020 09:21:56 +0200 Subject: [PATCH 3/7] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42dbcac3..a938913b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Add target option for supplying dedicated port list for alive detection (Boreas only) via OSP. [#323](https://github.com/greenbone/ospd/pull/323) +- Add target option for supplying alive test methods via separate elements. [#329](https://github.com/greenbone/ospd/pull/329) ### Removed - Remove python3.5 support and deprecated methods. [#316](https://github.com/greenbone/ospd/pull/316) From 384756c36baada11e1c03906ddae95e49cdf1b50 Mon Sep 17 00:00:00 2001 From: ArnoStiefvater Date: Tue, 13 Oct 2020 09:36:37 +0200 Subject: [PATCH 4/7] Fix formatting. --- ospd/protocol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ospd/protocol.py b/ospd/protocol.py index 259f19ff..48291014 100644 --- a/ospd/protocol.py +++ b/ospd/protocol.py @@ -148,7 +148,7 @@ def process_credentials_elements(cred_tree: Element) -> Dict: @staticmethod def process_alive_test_methods(cred_tree: Element, options: Dict) -> None: - """ Receive an XML object with the alive test methods to run + """Receive an XML object with the alive test methods to run a scan with. Methods are added to the options Dict. @param From 4a5305b90f938644c5981623aca014ec45574a84 Mon Sep 17 00:00:00 2001 From: ArnoStiefvater Date: Tue, 13 Oct 2020 12:44:34 +0200 Subject: [PATCH 5/7] Add changelog entry to protocol description --- doc/OSP.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/OSP.xml b/doc/OSP.xml index 40ed4380..d9b80fb7 100644 --- a/doc/OSP.xml +++ b/doc/OSP.xml @@ -1533,6 +1533,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21.4 + + START_SCAN + Add support for supplying alive test methods via separate elements. + Target element received new optional target option alive_test_methods with subelements imcp, tcp_ack, tcp_syn, arp and consider_alive. + + 21.4 + + GET_VTS Returned object extended with solution method From f22f3f5d0aa29e318b137e18e302dd9871dea474 Mon Sep 17 00:00:00 2001 From: ArnoStiefvater Date: Wed, 14 Oct 2020 12:34:10 +0200 Subject: [PATCH 6/7] Do not add empty option to options dict --- ospd/protocol.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/ospd/protocol.py b/ospd/protocol.py index 48291014..d5056fdc 100644 --- a/ospd/protocol.py +++ b/ospd/protocol.py @@ -147,30 +147,37 @@ def process_credentials_elements(cred_tree: Element) -> Dict: return credentials @staticmethod - def process_alive_test_methods(cred_tree: Element, options: Dict) -> None: + def process_alive_test_methods( + alive_test_tree: Element, options: Dict + ) -> None: """Receive an XML object with the alive test methods to run a scan with. Methods are added to the options Dict. @param - - - - - 0 + boolean(1 or 0) + boolean(1 or 0) + boolean(1 or 0) + boolean(1 or 0) + boolean(1 or 0) """ - for child in cred_tree: + for child in alive_test_tree: if child.tag == 'icmp': - options['icmp'] = child.text + if child.text is not None: + options['icmp'] = child.text if child.tag == 'tcp_ack': - options['tcp_ack'] = child.text + if child.text is not None: + options['tcp_ack'] = child.text if child.tag == 'tcp_syn': - options['tcp_syn'] = child.text + if child.text is not None: + options['tcp_syn'] = child.text if child.tag == 'arp': - options['arp'] = child.text + if child.text is not None: + options['arp'] = child.text if child.tag == 'consider_alive': - options['consider_alive'] = child.text + if child.text is not None: + options['consider_alive'] = child.text @classmethod def process_target_element(cls, scanner_target: Element) -> Dict: From eaa4f3264397a4bbe5b5739b501d63c5aedfa84c Mon Sep 17 00:00:00 2001 From: ArnoStiefvater Date: Wed, 14 Oct 2020 12:41:35 +0200 Subject: [PATCH 7/7] Add tests for supplying alive test via elements Test for all available methods. Test for empty or missing methods. --- tests/test_scan_and_result.py | 91 +++++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 5 deletions(-) diff --git a/tests/test_scan_and_result.py b/tests/test_scan_and_result.py index 9ab57c71..fdeed807 100644 --- a/tests/test_scan_and_result.py +++ b/tests/test_scan_and_result.py @@ -238,7 +238,8 @@ def test_get_vts_filter_negative(self): ) fs = FakeStream() self.daemon.handle_command( - '', fs, + '', + fs, ) response = fs.get_response() @@ -741,7 +742,8 @@ def test_get_scan_results_clean(self): fs = FakeStream() self.daemon.handle_command( - '' % scan_id, fs, + '' % scan_id, + fs, ) res_len = len( @@ -771,7 +773,8 @@ def test_get_scan_results_restore(self): fs = FakeStream(return_value=False) self.daemon.handle_command( - '' % scan_id, fs, + '' % scan_id, + fs, ) res_len = len( @@ -893,6 +896,82 @@ def test_scan_get_target_options(self): target_options = self.daemon.get_scan_target_options(scan_id) self.assertEqual(target_options, {'alive_test': '0'}) + def test_scan_get_target_options_alive_test_methods(self): + fs = FakeStream() + self.daemon.handle_command( + '' + '' + '' + '' + '192.168.0.1' + '22' + '' + '1' + '1' + '1' + '1' + '1' + '' + '' + '' + '', + fs, + ) + self.daemon.start_queued_scans() + + response = fs.get_response() + + scan_id = response.findtext('id') + time.sleep(1) + target_options = self.daemon.get_scan_target_options(scan_id) + self.assertEqual( + target_options, + { + 'alive_test_methods': '1', + 'icmp': '1', + 'tcp_syn': '1', + 'tcp_ack': '1', + 'arp': '1', + 'consider_alive': '1', + }, + ) + + def test_scan_get_target_options_alive_test_methods_dont_add_empty_or_missing( # pylint: disable=line-too-long + self, + ): + fs = FakeStream() + self.daemon.handle_command( + '' + '' + '' + '' + '192.168.0.1' + '22' + '' + '1' + '' + '' + '' + '' + '' + '', + fs, + ) + self.daemon.start_queued_scans() + + response = fs.get_response() + + scan_id = response.findtext('id') + time.sleep(1) + target_options = self.daemon.get_scan_target_options(scan_id) + self.assertEqual( + target_options, + { + 'alive_test_methods': '1', + 'icmp': '1', + }, + ) + def test_progress(self): fs = FakeStream() @@ -1087,7 +1166,8 @@ def test_get_scan_progress_xml(self): fs = FakeStream() self.daemon.handle_command( - '' % scan_id, fs, + '' % scan_id, + fs, ) response = fs.get_response() @@ -1164,7 +1244,8 @@ def test_scan_exists(self, mock_create_process, _mock_os): ) self.daemon.handle_command( - cmd, fs, + cmd, + fs, ) self.daemon.start_queued_scans()