mirror of
https://github.com/jtesta/ssh-audit.git
synced 2024-12-23 06:27:41 +01:00
Fix banner protocol (1.99) recognition and clean banner comments. Add banner tests.
This commit is contained in:
parent
5269b63e64
commit
489a24c564
@ -655,8 +655,8 @@ class SSH(object):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
class Banner(object):
|
class Banner(object):
|
||||||
_RXP, _RXR = r'SSH-\d\.\s*?\d+', r'(-([^\s]*)(?:\s+(.*))?)?'
|
_RXP, _RXR = r'SSH-\d\.\s*?\d+', r'(-\s*([^\s]*)(?:\s+(.*))?)?'
|
||||||
RX_PROTOCOL = re.compile(_RXP.replace('\d', '(\d)'))
|
RX_PROTOCOL = re.compile(re.sub(r'\\d(\+?)','(\\d\g<1>)', _RXP))
|
||||||
RX_BANNER = re.compile(r'^({0}(?:(?:-{0})*)){1}$'.format(_RXP, _RXR))
|
RX_BANNER = re.compile(r'^({0}(?:(?:-{0})*)){1}$'.format(_RXP, _RXR))
|
||||||
|
|
||||||
def __init__(self, protocol, software, comments):
|
def __init__(self, protocol, software, comments):
|
||||||
@ -704,6 +704,8 @@ class SSH(object):
|
|||||||
if software is None and (mx.group(2) or '').startswith('-'):
|
if software is None and (mx.group(2) or '').startswith('-'):
|
||||||
software = ''
|
software = ''
|
||||||
comments = (mx.group(4) or '').strip() or None
|
comments = (mx.group(4) or '').strip() or None
|
||||||
|
if comments is not None:
|
||||||
|
comments = re.sub('\s+', ' ', comments)
|
||||||
return cls(protocol, software, comments)
|
return cls(protocol, software, comments)
|
||||||
|
|
||||||
class Fingerprint(object):
|
class Fingerprint(object):
|
||||||
|
68
test/test_banner.py
Normal file
68
test/test_banner.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
class TestBanner(object):
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def init(self, ssh_audit):
|
||||||
|
self.ssh = ssh_audit.SSH
|
||||||
|
|
||||||
|
def test_simple_banners(self):
|
||||||
|
banner = lambda x: self.ssh.Banner.parse(x)
|
||||||
|
b = banner('SSH-2.0-OpenSSH_7.3')
|
||||||
|
assert b.protocol == (2, 0)
|
||||||
|
assert b.software == 'OpenSSH_7.3'
|
||||||
|
assert b.comments is None
|
||||||
|
assert str(b) == 'SSH-2.0-OpenSSH_7.3'
|
||||||
|
b = banner('SSH-1.99-Sun_SSH_1.1.3')
|
||||||
|
assert b.protocol == (1, 99)
|
||||||
|
assert b.software == 'Sun_SSH_1.1.3'
|
||||||
|
assert b.comments is None
|
||||||
|
assert str(b) == 'SSH-1.99-Sun_SSH_1.1.3'
|
||||||
|
b = banner('SSH-1.5-Cisco-1.25')
|
||||||
|
assert b.protocol == (1, 5)
|
||||||
|
assert b.software == 'Cisco-1.25'
|
||||||
|
assert b.comments is None
|
||||||
|
assert str(b) == 'SSH-1.5-Cisco-1.25'
|
||||||
|
|
||||||
|
def test_invalid_banners(self):
|
||||||
|
b = lambda x: self.ssh.Banner.parse(x)
|
||||||
|
assert b('Something') is None
|
||||||
|
assert b('SSH-XXX-OpenSSH_7.3') is None
|
||||||
|
|
||||||
|
def test_banners_with_spaces(self):
|
||||||
|
b = lambda x: self.ssh.Banner.parse(x)
|
||||||
|
s = 'SSH-2.0-OpenSSH_4.3p2'
|
||||||
|
assert str(b('SSH-2.0-OpenSSH_4.3p2 ')) == s
|
||||||
|
assert str(b('SSH-2.0- OpenSSH_4.3p2')) == s
|
||||||
|
assert str(b('SSH-2.0- OpenSSH_4.3p2 ')) == s
|
||||||
|
s = 'SSH-2.0-OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu'
|
||||||
|
assert str(b('SSH-2.0- OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu')) == s
|
||||||
|
assert str(b('SSH-2.0-OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu ')) == s
|
||||||
|
assert str(b('SSH-2.0- OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu ')) == s
|
||||||
|
|
||||||
|
def test_banners_without_software(self):
|
||||||
|
b = lambda x: self.ssh.Banner.parse(x)
|
||||||
|
assert b('SSH-2.0').protocol == (2, 0)
|
||||||
|
assert b('SSH-2.0').software is None
|
||||||
|
assert b('SSH-2.0').comments is None
|
||||||
|
assert str(b('SSH-2.0')) == 'SSH-2.0'
|
||||||
|
assert b('SSH-2.0-').protocol == (2, 0)
|
||||||
|
assert b('SSH-2.0-').software == ''
|
||||||
|
assert b('SSH-2.0-').comments is None
|
||||||
|
assert str(b('SSH-2.0-')) == 'SSH-2.0-'
|
||||||
|
|
||||||
|
def test_banners_with_comments(self):
|
||||||
|
b = lambda x: self.ssh.Banner.parse(x)
|
||||||
|
assert repr(b('SSH-2.0-OpenSSH_7.2p2 Ubuntu-1')) == '<Banner(protocol=2.0, software=OpenSSH_7.2p2, comments=Ubuntu-1)>'
|
||||||
|
assert repr(b('SSH-1.99-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3')) == '<Banner(protocol=1.99, software=OpenSSH_3.4p1, comments=Debian 1:3.4p1-1.woody.3)>'
|
||||||
|
assert repr(b('SSH-1.5-1.3.7 F-SECURE SSH')) == '<Banner(protocol=1.5, software=1.3.7, comments=F-SECURE SSH)>'
|
||||||
|
|
||||||
|
def test_banners_with_multiple_protocols(self):
|
||||||
|
b = lambda x: self.ssh.Banner.parse(x)
|
||||||
|
assert str(b('SSH-1.99-SSH-1.99-OpenSSH_3.6.1p2')) == 'SSH-1.99-OpenSSH_3.6.1p2'
|
||||||
|
assert str(b('SSH-2.0-SSH-2.0-OpenSSH_4.3p2 Debian-9')) == 'SSH-2.0-OpenSSH_4.3p2 Debian-9'
|
||||||
|
assert str(b('SSH-1.99-SSH-2.0-dropbear_0.5')) == 'SSH-1.99-dropbear_0.5'
|
||||||
|
assert str(b('SSH-2.0-SSH-1.99-OpenSSH_4.2p1 SSH Secure Shell (non-commercial)')) == 'SSH-1.99-OpenSSH_4.2p1 SSH Secure Shell (non-commercial)'
|
||||||
|
assert str(b('SSH-1.99-SSH-1.99-SSH-1.99-OpenSSH_3.9p1')) == 'SSH-1.99-OpenSSH_3.9p1'
|
Loading…
Reference in New Issue
Block a user