mirror of
https://github.com/jtesta/ssh-audit.git
synced 2026-06-15 17:20:21 +02:00
Added support for scanning servers over UNIX sockets. (#351)
This commit is contained in:
@@ -93,7 +93,8 @@ optional arguments:
|
|||||||
used)
|
used)
|
||||||
-T targets.txt, --targets targets.txt
|
-T targets.txt, --targets targets.txt
|
||||||
a file containing a list of target hosts (one per
|
a file containing a list of target hosts (one per
|
||||||
line, format HOST[:PORT]). Use -p/--port to set the
|
line, format 'HOST[:PORT]'; for UNIX socket servers,
|
||||||
|
use 'unix:///path/socket'). Use -p/--port to set the
|
||||||
default port for all hosts. Use --threads to control
|
default port for all hosts. Use --threads to control
|
||||||
concurrent scans
|
concurrent scans
|
||||||
-t N, --timeout N timeout (in seconds) for connection and reading
|
-t N, --timeout N timeout (in seconds) for connection and reading
|
||||||
@@ -142,6 +143,7 @@ ssh-audit 127.0.0.1
|
|||||||
ssh-audit 127.0.0.1:222
|
ssh-audit 127.0.0.1:222
|
||||||
ssh-audit ::1
|
ssh-audit ::1
|
||||||
ssh-audit [::1]:222
|
ssh-audit [::1]:222
|
||||||
|
ssh-audit unix:///run/ssh-unix-local/socket
|
||||||
```
|
```
|
||||||
|
|
||||||
To run a standard audit against many servers (place targets into servers.txt, one on each line in the format of `HOST[:PORT]`):
|
To run a standard audit against many servers (place targets into servers.txt, one on each line in the format of `HOST[:PORT]`):
|
||||||
@@ -150,13 +152,13 @@ To run a standard audit against many servers (place targets into servers.txt, on
|
|||||||
ssh-audit -T servers.txt
|
ssh-audit -T servers.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
To audit a client configuration (listens on port 2222 by default; connect using `ssh -p 2222 anything@localhost`):
|
To audit a client configuration (listens on port 2222/tcp by default; connect using `ssh -p 2222 anything@localhost`):
|
||||||
|
|
||||||
```
|
```
|
||||||
ssh-audit -c
|
ssh-audit -c
|
||||||
```
|
```
|
||||||
|
|
||||||
To audit a client configuration, with a listener on port 4567:
|
To audit a client configuration, with a listener on port 4567/tcp:
|
||||||
```
|
```
|
||||||
ssh-audit -c -p 4567
|
ssh-audit -c -p 4567
|
||||||
```
|
```
|
||||||
@@ -260,6 +262,7 @@ For convenience, a web front-end on top of the command-line tool is available at
|
|||||||
- Migrated from deprecated `getopt` module to `argparse`; partial credit [oam7575](https://github.com/oam7575).
|
- Migrated from deprecated `getopt` module to `argparse`; partial credit [oam7575](https://github.com/oam7575).
|
||||||
- When running against multiple hosts, now prints each target host regardless of output level.
|
- When running against multiple hosts, now prints each target host regardless of output level.
|
||||||
- Batch mode (`-b`) no longer automatically enables verbose mode, due to sometimes confusing results; users can still explicitly enable verbose mode using the `-v` flag.
|
- Batch mode (`-b`) no longer automatically enables verbose mode, due to sometimes confusing results; users can still explicitly enable verbose mode using the `-v` flag.
|
||||||
|
- Added UNIX server socket scanning (specify the target with `unix:///path/to/socket`).
|
||||||
- Added built-in policy for OpenSSH 10.0.
|
- Added built-in policy for OpenSSH 10.0.
|
||||||
- Added hardening guides and policies for Debian 13.
|
- Added hardening guides and policies for Debian 13.
|
||||||
- Added 2 new key exchanges: `mlkem768nistp256-sha256`, `mlkem1024nistp384-sha384`.
|
- Added 2 new key exchanges: `mlkem768nistp256-sha256`, `mlkem1024nistp384-sha384`.
|
||||||
|
|||||||
+10
-2
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (C) 2023-2024 Joe Testa (jtesta@positronsecurity.com)
|
Copyright (C) 2023-2026 Joe Testa (jtesta@positronsecurity.com)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -435,7 +435,11 @@ class DHEat:
|
|||||||
s.setblocking(False)
|
s.setblocking(False)
|
||||||
|
|
||||||
# out.d("Creating socket (%u of %u already exist)..." % (len(socket_dict), concurrent_sockets), write_now=True)
|
# out.d("Creating socket (%u of %u already exist)..." % (len(socket_dict), concurrent_sockets), write_now=True)
|
||||||
ret = s.connect_ex((target_ip_address, aconf.port))
|
if target_address_family == socket.AF_UNIX:
|
||||||
|
ret = s.connect_ex(target_ip_address)
|
||||||
|
else:
|
||||||
|
ret = s.connect_ex((target_ip_address, aconf.port))
|
||||||
|
|
||||||
num_attempted_connections += 1
|
num_attempted_connections += 1
|
||||||
if ret in [0, errno.EINPROGRESS, errno.EWOULDBLOCK]:
|
if ret in [0, errno.EINPROGRESS, errno.EWOULDBLOCK]:
|
||||||
socket_dict[s] = now
|
socket_dict[s] = now
|
||||||
@@ -752,6 +756,10 @@ class DHEat:
|
|||||||
def _resolve_hostname(host: str, ip_version_preference: List[int]) -> Tuple[int, str]:
|
def _resolve_hostname(host: str, ip_version_preference: List[int]) -> Tuple[int, str]:
|
||||||
'''Resolves a hostname to its IPv4 or IPv6 address, depending on user preference.'''
|
'''Resolves a hostname to its IPv4 or IPv6 address, depending on user preference.'''
|
||||||
|
|
||||||
|
# First check if this is a UNIX socket.
|
||||||
|
if host.startswith("unix://"):
|
||||||
|
return int(socket.AF_UNIX), host[7:]
|
||||||
|
|
||||||
family = socket.AF_UNSPEC
|
family = socket.AF_UNSPEC
|
||||||
if len(ip_version_preference) == 1:
|
if len(ip_version_preference) == 1:
|
||||||
family = socket.AF_INET if ip_version_preference[0] == 4 else socket.AF_INET6
|
family = socket.AF_INET if ip_version_preference[0] == 4 else socket.AF_INET6
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"""
|
"""
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (C) 2017-2025 Joe Testa (jtesta@positronsecurity.com)
|
Copyright (C) 2017-2026 Joe Testa (jtesta@positronsecurity.com)
|
||||||
Copyright (C) 2017 Andris Raugulis (moo@arthepsy.eu)
|
Copyright (C) 2017 Andris Raugulis (moo@arthepsy.eu)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
@@ -915,19 +915,21 @@ def process_commandline(out: OutputBuffer, args: List[str]) -> 'AuditConf': # p
|
|||||||
Hardening_Guides.print_hardening_guide(out, argument.get_hardening_guide)
|
Hardening_Guides.print_hardening_guide(out, argument.get_hardening_guide)
|
||||||
sys.exit(exitcodes.GOOD)
|
sys.exit(exitcodes.GOOD)
|
||||||
|
|
||||||
|
# If we're doing a server audit against a single target.
|
||||||
if aconf.client_audit is False and aconf.target_file is None:
|
if aconf.client_audit is False and aconf.target_file is None:
|
||||||
if oport is not None:
|
host = argument.host
|
||||||
host = argument.host
|
if oport is None:
|
||||||
else:
|
|
||||||
host, port = Utils.parse_host_and_port(argument.host)
|
host, port = Utils.parse_host_and_port(argument.host)
|
||||||
|
|
||||||
if not host and aconf.target_file is None:
|
if not host and aconf.target_file is None:
|
||||||
out.fail("target host is not specified", write_now=True)
|
out.fail("target host is not specified", write_now=True)
|
||||||
sys.exit(exitcodes.UNKNOWN_ERROR)
|
sys.exit(exitcodes.UNKNOWN_ERROR)
|
||||||
|
|
||||||
if oport is None and aconf.client_audit: # The default port to listen on during a client audit is 2222.
|
# For client audits, if an explicit port isn't set, default to 2222/tcp.
|
||||||
|
if aconf.client_audit and oport is None:
|
||||||
port = 2222
|
port = 2222
|
||||||
|
|
||||||
|
# If an explicit port was set by the user, parse it.
|
||||||
if oport is not None:
|
if oport is not None:
|
||||||
port = Utils.parse_int(oport)
|
port = Utils.parse_int(oport)
|
||||||
if port < 1 or port > 65535:
|
if port < 1 or port > 65535:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (C) 2017-2025 Joe Testa (jtesta@positronsecurity.com)
|
Copyright (C) 2017-2026 Joe Testa (jtesta@positronsecurity.com)
|
||||||
Copyright (C) 2017 Andris Raugulis (moo@arthepsy.eu)
|
Copyright (C) 2017 Andris Raugulis (moo@arthepsy.eu)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
@@ -51,6 +51,7 @@ class SSH_Socket(ReadBuf, WriteBuf):
|
|||||||
|
|
||||||
SM_BANNER_SENT = 1
|
SM_BANNER_SENT = 1
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, outputbuffer: 'OutputBuffer', host: Optional[str], port: int, ip_version_preference: List[int] = [], timeout: Union[int, float] = 5, timeout_set: bool = False) -> None: # pylint: disable=dangerous-default-value
|
def __init__(self, outputbuffer: 'OutputBuffer', host: Optional[str], port: int, ip_version_preference: List[int] = [], timeout: Union[int, float] = 5, timeout_set: bool = False) -> None: # pylint: disable=dangerous-default-value
|
||||||
super(SSH_Socket, self).__init__()
|
super(SSH_Socket, self).__init__()
|
||||||
self.__outputbuffer = outputbuffer
|
self.__outputbuffer = outputbuffer
|
||||||
@@ -73,6 +74,7 @@ class SSH_Socket(ReadBuf, WriteBuf):
|
|||||||
self.client_host: Optional[str] = None
|
self.client_host: Optional[str] = None
|
||||||
self.client_port = None
|
self.client_port = None
|
||||||
|
|
||||||
|
|
||||||
def _resolve(self) -> Iterable[Tuple[int, Tuple[Any, ...]]]:
|
def _resolve(self) -> Iterable[Tuple[int, Tuple[Any, ...]]]:
|
||||||
"""Resolves a hostname into a list of IPs
|
"""Resolves a hostname into a list of IPs
|
||||||
Raises
|
Raises
|
||||||
@@ -95,11 +97,13 @@ class SSH_Socket(ReadBuf, WriteBuf):
|
|||||||
if socktype == socket.SOCK_STREAM:
|
if socktype == socket.SOCK_STREAM:
|
||||||
yield af, addr
|
yield af, addr
|
||||||
|
|
||||||
# Listens on a server socket and accepts one connection (used for
|
|
||||||
# auditing client connections).
|
|
||||||
def listen_and_accept(self) -> None:
|
def listen_and_accept(self) -> None:
|
||||||
|
'''Listens on a server socket and accepts one connection (used for auditing client connections).'''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
self.__outputbuffer.d(f"Listening on 0.0.0.0:{self.__port}...", write_now=True)
|
||||||
|
|
||||||
# Socket to listen on all IPv4 addresses.
|
# Socket to listen on all IPv4 addresses.
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
@@ -110,6 +114,8 @@ class SSH_Socket(ReadBuf, WriteBuf):
|
|||||||
print("Warning: failed to listen on any IPv4 interfaces: %s" % str(e), file=sys.stderr)
|
print("Warning: failed to listen on any IPv4 interfaces: %s" % str(e), file=sys.stderr)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
self.__outputbuffer.d(f"Listening on [::]:{self.__port}...", write_now=True)
|
||||||
|
|
||||||
# Socket to listen on all IPv6 addresses.
|
# Socket to listen on all IPv6 addresses.
|
||||||
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
||||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
@@ -150,18 +156,31 @@ class SSH_Socket(ReadBuf, WriteBuf):
|
|||||||
c.settimeout(self.__timeout)
|
c.settimeout(self.__timeout)
|
||||||
self.__sock = c
|
self.__sock = c
|
||||||
|
|
||||||
|
|
||||||
def connect(self) -> Optional[str]:
|
def connect(self) -> Optional[str]:
|
||||||
'''Returns None on success, or an error string.'''
|
'''Returns None on success, or an error string.'''
|
||||||
err = None
|
err = None
|
||||||
s = None
|
s = None
|
||||||
try:
|
try:
|
||||||
for af, addr in self._resolve():
|
|
||||||
s = socket.socket(af, socket.SOCK_STREAM)
|
# If we're connecting to a UNIX socket.
|
||||||
|
if self.__host.startswith("unix://"):
|
||||||
|
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
s.settimeout(self.__timeout)
|
s.settimeout(self.__timeout)
|
||||||
self.__outputbuffer.d(("Connecting to %s:%d..." % ('[%s]' % addr[0] if Utils.is_ipv6_address(addr[0]) else addr[0], addr[1])), write_now=True)
|
s.connect(self.__host[7:])
|
||||||
s.connect(addr)
|
|
||||||
self.__sock = s
|
self.__sock = s
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# We're connecting to an Internet host.
|
||||||
|
else:
|
||||||
|
for af, addr in self._resolve():
|
||||||
|
s = socket.socket(af, socket.SOCK_STREAM)
|
||||||
|
s.settimeout(self.__timeout)
|
||||||
|
self.__outputbuffer.d(("Connecting to %s:%d..." % ('[%s]' % addr[0] if Utils.is_ipv6_address(addr[0]) else addr[0], addr[1])), write_now=True)
|
||||||
|
s.connect(addr)
|
||||||
|
self.__sock = s
|
||||||
|
return None
|
||||||
|
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
err = e
|
err = e
|
||||||
self._close_socket(s)
|
self._close_socket(s)
|
||||||
@@ -170,8 +189,10 @@ class SSH_Socket(ReadBuf, WriteBuf):
|
|||||||
else:
|
else:
|
||||||
errt = (self.__host, self.__port, err)
|
errt = (self.__host, self.__port, err)
|
||||||
errm = 'cannot connect to {} port {}: {}'.format(*errt)
|
errm = 'cannot connect to {} port {}: {}'.format(*errt)
|
||||||
|
|
||||||
return '[exception] {}'.format(errm)
|
return '[exception] {}'.format(errm)
|
||||||
|
|
||||||
|
|
||||||
def get_banner(self) -> Tuple[Optional['Banner'], List[str], Optional[str]]:
|
def get_banner(self) -> Tuple[Optional['Banner'], List[str], Optional[str]]:
|
||||||
self.__outputbuffer.d('Getting banner...', write_now=True)
|
self.__outputbuffer.d('Getting banner...', write_now=True)
|
||||||
|
|
||||||
@@ -201,6 +222,7 @@ class SSH_Socket(ReadBuf, WriteBuf):
|
|||||||
|
|
||||||
return self.__banner, self.__header, e
|
return self.__banner, self.__header, e
|
||||||
|
|
||||||
|
|
||||||
def recv(self, size: int = 2048) -> Tuple[int, Optional[str]]:
|
def recv(self, size: int = 2048) -> Tuple[int, Optional[str]]:
|
||||||
if self.__sock is None:
|
if self.__sock is None:
|
||||||
return -1, 'not connected'
|
return -1, 'not connected'
|
||||||
@@ -221,6 +243,7 @@ class SSH_Socket(ReadBuf, WriteBuf):
|
|||||||
self._buf.seek(pos, 0)
|
self._buf.seek(pos, 0)
|
||||||
return len(data), None
|
return len(data), None
|
||||||
|
|
||||||
|
|
||||||
def send(self, data: bytes) -> Tuple[int, Optional[str]]:
|
def send(self, data: bytes) -> Tuple[int, Optional[str]]:
|
||||||
if self.__sock is None:
|
if self.__sock is None:
|
||||||
return -1, 'not connected'
|
return -1, 'not connected'
|
||||||
@@ -243,16 +266,19 @@ class SSH_Socket(ReadBuf, WriteBuf):
|
|||||||
kex.write(self)
|
kex.write(self)
|
||||||
self.send_packet()
|
self.send_packet()
|
||||||
|
|
||||||
|
|
||||||
def send_banner(self, banner: str) -> None:
|
def send_banner(self, banner: str) -> None:
|
||||||
self.send(banner.encode() + b'\r\n')
|
self.send(banner.encode() + b'\r\n')
|
||||||
self.__state = max(self.__state, self.SM_BANNER_SENT)
|
self.__state = max(self.__state, self.SM_BANNER_SENT)
|
||||||
|
|
||||||
|
|
||||||
def ensure_read(self, size: int) -> None:
|
def ensure_read(self, size: int) -> None:
|
||||||
while self.unread_len < size:
|
while self.unread_len < size:
|
||||||
s, e = self.recv()
|
s, e = self.recv()
|
||||||
if s < 0:
|
if s < 0:
|
||||||
raise SSH_Socket.InsufficientReadException(e)
|
raise SSH_Socket.InsufficientReadException(e)
|
||||||
|
|
||||||
|
|
||||||
def read_packet(self) -> Tuple[int, bytes]:
|
def read_packet(self) -> Tuple[int, bytes]:
|
||||||
try:
|
try:
|
||||||
header = WriteBuf()
|
header = WriteBuf()
|
||||||
@@ -284,6 +310,7 @@ class SSH_Socket(ReadBuf, WriteBuf):
|
|||||||
e = ex.args[0].encode('utf-8')
|
e = ex.args[0].encode('utf-8')
|
||||||
return -1, e
|
return -1, e
|
||||||
|
|
||||||
|
|
||||||
def send_packet(self) -> Tuple[int, Optional[str]]:
|
def send_packet(self) -> Tuple[int, Optional[str]]:
|
||||||
payload = self.write_flush()
|
payload = self.write_flush()
|
||||||
padding = -(len(payload) + 5) % 8
|
padding = -(len(payload) + 5) % 8
|
||||||
@@ -294,10 +321,12 @@ class SSH_Socket(ReadBuf, WriteBuf):
|
|||||||
data = struct.pack('>Ib', plen, padding) + payload + pad_bytes
|
data = struct.pack('>Ib', plen, padding) + payload + pad_bytes
|
||||||
return self.send(data)
|
return self.send(data)
|
||||||
|
|
||||||
|
|
||||||
def is_connected(self) -> bool:
|
def is_connected(self) -> bool:
|
||||||
"""Returns true if this Socket is connected, False otherwise."""
|
"""Returns true if this Socket is connected, False otherwise."""
|
||||||
return self.__sock is not None
|
return self.__sock is not None
|
||||||
|
|
||||||
|
|
||||||
def close(self) -> None:
|
def close(self) -> None:
|
||||||
self.__cleanup()
|
self.__cleanup()
|
||||||
self.reset()
|
self.reset()
|
||||||
@@ -305,6 +334,7 @@ class SSH_Socket(ReadBuf, WriteBuf):
|
|||||||
self.__header = []
|
self.__header = []
|
||||||
self.__banner = None
|
self.__banner = None
|
||||||
|
|
||||||
|
|
||||||
def _close_socket(self, s: Optional[socket.socket]) -> None:
|
def _close_socket(self, s: Optional[socket.socket]) -> None:
|
||||||
try:
|
try:
|
||||||
if s is not None:
|
if s is not None:
|
||||||
@@ -313,9 +343,11 @@ class SSH_Socket(ReadBuf, WriteBuf):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def __del__(self) -> None:
|
def __del__(self) -> None:
|
||||||
self.__cleanup()
|
self.__cleanup()
|
||||||
|
|
||||||
|
|
||||||
def __cleanup(self) -> None:
|
def __cleanup(self) -> None:
|
||||||
self._close_socket(self.__sock)
|
self._close_socket(self.__sock)
|
||||||
for sock in self.__sock_map.values():
|
for sock in self.__sock_map.values():
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (C) 2017-2020 Joe Testa (jtesta@positronsecurity.com)
|
Copyright (C) 2017-2026 Joe Testa (jtesta@positronsecurity.com)
|
||||||
Copyright (C) 2017 Andris Raugulis (moo@arthepsy.eu)
|
Copyright (C) 2017 Andris Raugulis (moo@arthepsy.eu)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
@@ -134,6 +134,10 @@ class Utils:
|
|||||||
host = host_and_port
|
host = host_and_port
|
||||||
port = default_port
|
port = default_port
|
||||||
|
|
||||||
|
# If we have a UNIX socket path, do no further processing.
|
||||||
|
if host.startswith("unix://"):
|
||||||
|
return host, 1
|
||||||
|
|
||||||
mx = re.match(r'^\[([^\]]+)\](?::(\d+))?$', host_and_port)
|
mx = re.match(r'^\[([^\]]+)\](?::(\d+))?$', host_and_port)
|
||||||
if mx is not None:
|
if mx is not None:
|
||||||
host = mx.group(1)
|
host = mx.group(1)
|
||||||
|
|||||||
+3
-2
@@ -1,4 +1,4 @@
|
|||||||
.TH SSH-AUDIT 1 "August 17, 2025"
|
.TH SSH-AUDIT 1 "June 14, 2026"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
\fBssh-audit\fP \- SSH server & client configuration auditor
|
\fBssh-audit\fP \- SSH server & client configuration auditor
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -149,7 +149,7 @@ The timeout, in seconds, for creating connections and reading data from the sock
|
|||||||
.TP
|
.TP
|
||||||
.B -T, \-\-targets=<hosts.txt>
|
.B -T, \-\-targets=<hosts.txt>
|
||||||
.br
|
.br
|
||||||
A file containing a list of target hosts. Each line must have one host, in the format of HOST[:PORT]. Use -p/--port to set the default port for all hosts. Use --threads to control concurrent scans.
|
A file containing a list of target hosts. Each line must have one host, in the format of HOST[:PORT] (or for UNIX sockets, use "unix://path/to/socket"). Use -p/--port to set the default port for all hosts. Use --threads to control concurrent scans.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-threads=<threads>
|
.B \-\-threads=<threads>
|
||||||
@@ -188,6 +188,7 @@ ssh-audit 127.0.0.1
|
|||||||
ssh-audit 127.0.0.1:222
|
ssh-audit 127.0.0.1:222
|
||||||
ssh-audit ::1
|
ssh-audit ::1
|
||||||
ssh-audit [::1]:222
|
ssh-audit [::1]:222
|
||||||
|
ssh-audit unix:///run/ssh-unix-local/socket
|
||||||
.fi
|
.fi
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user