9 Commits

Author SHA1 Message Date
Daniel Thamdrup 8d08570ef5 Merge 31fa0577bd into f326d58068 2024-01-29 21:46:30 -07:00
Joe Testa f326d58068 Disable color when the NO_COLOR environment variable is set. (#234) 2024-01-28 18:17:49 -05:00
Joe Testa b72f6a420f Added note regarding general OpenSSH policies failing against platforms with back-ported features. (#236) 2024-01-28 17:37:21 -05:00
Daniel Thamdrup 31fa0577bd use chainguard image as base
Signed-off-by: Daniel Thamdrup <dallemon@protonmail.com>
2024-01-25 00:04:53 +01:00
Joe Testa fe65b5df8a Added missing dev tag to Change Log: v3.2.0 -> v3.2.0-dev 2023-12-21 15:34:38 -05:00
Joe Testa 44393c56b3 Expanded filter of CBC ciphers to flag for the Terrapin vulnerability. 2023-12-21 15:30:43 -05:00
Ville Skyttä 164356e776 Spelling fixes (#233) 2023-12-21 08:58:12 -05:00
Joe Testa c8e075ad13 Bumped version number to v3.2.0-dev. 2023-12-20 15:41:03 -05:00
Joe Testa eebeac99a0 Updated packaging instructions and Docker build steps. 2023-12-20 15:40:01 -05:00
9 changed files with 49 additions and 32 deletions
+8 -16
View File
@@ -1,21 +1,13 @@
FROM python:3-slim #syntax=docker/dockerfile:1.6.0
FROM scratch AS tmp
WORKDIR /
# Update the image to remediate any vulnerabilities.
RUN apt clean && apt update && apt -y dist-upgrade && apt clean && rm -rf /var/lib/apt/lists/*
# Remove suid & sgid bits from all files.
RUN find / -xdev -perm /6000 -exec chmod ug-s {} \; 2> /dev/null || true
# Copy the ssh-audit code. # Copy the ssh-audit code.
COPY ssh-audit.py . COPY ssh-audit.py /home/nonroot/
COPY src/ . COPY src/ /home/nonroot/
FROM cgr.dev/chainguard/python:latest AS runtime
# Copy files collected in tmp container
COPY --from=tmp --chown=nonroot:nonroot /home/nonroot/ /home/nonroot/
# Allow listening on 2222/tcp for client auditing. # Allow listening on 2222/tcp for client auditing.
EXPOSE 2222 EXPOSE 2222
# Drop root privileges. ENTRYPOINT ["python3", "/home/nonroot/ssh-audit.py"]
USER nobody:nogroup
ENTRYPOINT ["python3", "/ssh-audit.py"]
+13 -2
View File
@@ -4,10 +4,21 @@ ifeq ($(VERSION),)
endif endif
all: all:
docker build -t positronsecurity/ssh-audit:${VERSION} . docker buildx create --name multiarch --use || exit 0
docker buildx build \
--platform linux/amd64,linux/arm64,linux/arm/v7 \
--tag positronsecurity/ssh-audit:${VERSION} \
--tag positronsecurity/ssh-audit:latest \
.
docker buildx build \
--tag positronsecurity/ssh-audit:${VERSION} \
--tag positronsecurity/ssh-audit:latest \
--load \
--builder=multiarch \
.
upload: upload:
docker login docker login -u positronsecurity
docker buildx build \ docker buildx build \
--platform linux/amd64,linux/arm64,linux/arm/v7 \ --platform linux/amd64,linux/arm64,linux/arm/v7 \
--tag positronsecurity/ssh-audit:${VERSION} \ --tag positronsecurity/ssh-audit:${VERSION} \
+8 -5
View File
@@ -2,7 +2,7 @@
An executable can only be made on a Windows host because the PyInstaller tool (https://www.pyinstaller.org/) does not support cross-compilation. An executable can only be made on a Windows host because the PyInstaller tool (https://www.pyinstaller.org/) does not support cross-compilation.
1.) Install Python v3.11.x from https://www.python.org/. To make life easier, check the option to add Python to the PATH environment variable. 1.) Install Python v3.x from https://www.python.org/. To make life easier, check the option to add Python to the PATH environment variable.
2.) Install Cygwin (https://www.cygwin.com/). 2.) Install Cygwin (https://www.cygwin.com/).
@@ -15,7 +15,7 @@ An executable can only be made on a Windows host because the PyInstaller tool (h
# PyPI # PyPI
To create package and upload to test server: To create package and upload to test server (hint: use username '\_\_token\_\_' and API token for test.pypi.org):
``` ```
$ sudo apt install python3-virtualenv python3.10-venv $ sudo apt install python3-virtualenv python3.10-venv
@@ -31,7 +31,7 @@ To download from test server and verify:
$ pip3 install --index-url https://test.pypi.org/simple ssh-audit $ pip3 install --index-url https://test.pypi.org/simple ssh-audit
``` ```
To upload to production server (hint: use username '\_\_token\_\_' and API token): To upload to production server (hint: use username '\_\_token\_\_' and API token for production pypi.org):
``` ```
$ make -f Makefile.pypi uploadprod $ make -f Makefile.pypi uploadprod
@@ -61,19 +61,22 @@ Upload the snap with:
$ snapcraft export-login ~/snap_creds.txt $ snapcraft export-login ~/snap_creds.txt
$ export SNAPCRAFT_STORE_CREDENTIALS=$(cat ~/snap_creds.txt) $ export SNAPCRAFT_STORE_CREDENTIALS=$(cat ~/snap_creds.txt)
$ snapcraft upload --release=beta ssh-audit_*.snap $ snapcraft upload --release=beta ssh-audit_*.snap
$ snapcraft upload --release=stable ssh-audit_*.snap $ snapcraft status ssh-audit # Note the revision number of the beta channel.
$ snapcraft release ssh-audit X stable # Fill in with the revision number.
``` ```
# Docker # Docker
Ensure that the buildx plugin is available by following the installation instructions available at: https://docs.docker.com/engine/install/ubuntu/
Build a local image with: Build a local image with:
``` ```
$ make -f Makefile.docker $ make -f Makefile.docker
``` ```
Create a multi-architecture build and upload it to Dockerhub with: Create a multi-architecture build and upload it to Dockerhub with (hint: use the API token as the password):
``` ```
$ make -f Makefile.docker upload $ make -f Makefile.docker upload
+4
View File
@@ -178,6 +178,10 @@ For convenience, a web front-end on top of the command-line tool is available at
## ChangeLog ## ChangeLog
### v3.2.0-dev (???)
- Expanded filter of CBC ciphers to flag for the Terrapin vulnerability. It now includes more rarely found ciphers.
- Color output is disabled if the `NO_COLOR` environment variable is set (see https://no-color.org/).
### v3.1.0 (2023-12-20) ### v3.1.0 (2023-12-20)
- Added test for the Terrapin message prefix truncation vulnerability ([CVE-2023-48795](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-48795)). - Added test for the Terrapin message prefix truncation vulnerability ([CVE-2023-48795](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-48795)).
- Dropped support for Python 3.7 (EOL was reached in June 2023). - Dropped support for Python 3.7 (EOL was reached in June 2023).
+1 -1
View File
@@ -22,7 +22,7 @@
THE SOFTWARE. THE SOFTWARE.
""" """
# The version to display. # The version to display.
VERSION = 'v3.1.0' VERSION = 'v3.2.0-dev'
# SSH software to impersonate # SSH software to impersonate
SSH_HEADER = 'SSH-{0}-OpenSSH_8.2' SSH_HEADER = 'SSH-{0}-OpenSSH_8.2'
+2 -2
View File
@@ -80,7 +80,7 @@ class KexDH: # pragma: nocover
# contains the host key, among other things. Function returns the host # contains the host key, among other things. Function returns the host
# key blob (from which the fingerprint can be calculated). # key blob (from which the fingerprint can be calculated).
def recv_reply(self, s: 'SSH_Socket', parse_host_key_size: bool = True) -> Optional[bytes]: def recv_reply(self, s: 'SSH_Socket', parse_host_key_size: bool = True) -> Optional[bytes]:
# Reset the CA info, in case it was set from a prior invokation. # Reset the CA info, in case it was set from a prior invocation.
self.__hostkey_type = '' self.__hostkey_type = ''
self.__hostkey_e = 0 # pylint: disable=unused-private-member self.__hostkey_e = 0 # pylint: disable=unused-private-member
self.__hostkey_n = 0 # pylint: disable=unused-private-member self.__hostkey_n = 0 # pylint: disable=unused-private-member
@@ -100,7 +100,7 @@ class KexDH: # pragma: nocover
# A connection error occurred. We can't parse anything, so just # A connection error occurred. We can't parse anything, so just
# return. The host key modulus (and perhaps certificate modulus) # return. The host key modulus (and perhaps certificate modulus)
# will remain at length 0. # will remain at length 0.
self.out.d("KexDH.recv_reply(): received packge_type == -1.") self.out.d("KexDH.recv_reply(): received package_type == -1.")
return None return None
# Get the host key blob, F, and signature. # Get the host key blob, F, and signature.
+10 -3
View File
@@ -106,7 +106,8 @@ def usage(uout: OutputBuffer, err: Optional[str] = None) -> None:
uout.info(' --lookup=<alg1,alg2,...> looks up an algorithm(s) without\n connecting to a server') uout.info(' --lookup=<alg1,alg2,...> looks up an algorithm(s) without\n connecting to a server')
uout.info(' -M, --make-policy=<policy.txt> creates a policy based on the target server\n (i.e.: the target server has the ideal\n configuration that other servers should\n adhere to)') uout.info(' -M, --make-policy=<policy.txt> creates a policy based on the target server\n (i.e.: the target server has the ideal\n configuration that other servers should\n adhere to)')
uout.info(' -m, --manual print the man page (Windows only)') uout.info(' -m, --manual print the man page (Windows only)')
uout.info(' -n, --no-colors disable colors') uout.info(' -n, --no-colors disable colors (automatic when the NO_COLOR')
uout.info(' environment variable is set)')
uout.info(' -p, --port=<port> port to connect') uout.info(' -p, --port=<port> port to connect')
uout.info(' -P, --policy=<policy.txt> run a policy test using the specified policy') uout.info(' -P, --policy=<policy.txt> run a policy test using the specified policy')
uout.info(' -t, --timeout=<secs> timeout (in seconds) for connection and reading\n (default: 5)') uout.info(' -t, --timeout=<secs> timeout (in seconds) for connection and reading\n (default: 5)')
@@ -491,7 +492,7 @@ def post_process_findings(banner: Optional[Banner], algs: Algorithms, client_aud
if algs.ssh2kex is not None: if algs.ssh2kex is not None:
ciphers_supported = algs.ssh2kex.client.encryption if client_audit else algs.ssh2kex.server.encryption ciphers_supported = algs.ssh2kex.client.encryption if client_audit else algs.ssh2kex.server.encryption
for cipher in ciphers_supported: for cipher in ciphers_supported:
if cipher.endswith("-cbc"): if cipher.endswith("-cbc") or cipher.endswith("-cbc@openssh.org") or cipher.endswith("-cbc@ssh.com") or cipher == "rijndael-cbc@lysator.liu.se":
ret.append(cipher) ret.append(cipher)
return ret return ret
@@ -501,7 +502,7 @@ def post_process_findings(banner: Optional[Banner], algs: Algorithms, client_aud
ret = [] ret = []
for cipher in db["enc"]: for cipher in db["enc"]:
if cipher.endswith("-cbc") and cipher not in _get_cbc_ciphers_enabled(algs): if (cipher.endswith("-cbc") or cipher.endswith("-cbc@openssh.org") or cipher.endswith("-cbc@ssh.com") or cipher == "rijndael-cbc@lysator.liu.se") and cipher not in _get_cbc_ciphers_enabled(algs):
ret.append(cipher) ret.append(cipher)
return ret return ret
@@ -814,6 +815,7 @@ def list_policies(out: OutputBuffer) -> None:
out.fail("Error: no built-in policies found!") out.fail("Error: no built-in policies found!")
else: else:
out.info("\nHint: Use -P and provide the full name of a policy to run a policy scan with.\n") out.info("\nHint: Use -P and provide the full name of a policy to run a policy scan with.\n")
out.info("Note: the general OpenSSH policies apply to the official releases only. OS distributions may back-port changes that cause failures (for example, Debian 11 back-ported the strict KEX mode into their package of OpenSSH v8.4, whereas it was only officially added to OpenSSH v9.6 and later). In these cases, consider creating a custom policy (-M option).\n")
out.write() out.write()
@@ -857,6 +859,11 @@ def process_commandline(out: OutputBuffer, args: List[str], usage_cb: Callable[.
aconf = AuditConf() aconf = AuditConf()
enable_colors = not any(i in args for i in ['--no-colors', '-n']) enable_colors = not any(i in args for i in ['--no-colors', '-n'])
# Disable colors if the NO_COLOR environment variable is set.
if "NO_COLOR" in os.environ:
enable_colors = False
aconf.colors = enable_colors aconf.colors = enable_colors
out.use_colors = enable_colors out.use_colors = enable_colors
+1 -1
View File
@@ -122,7 +122,7 @@ class VersionVulnerabilityDB: # pylint: disable=too-few-public-methods
['2.1', '4.1p1', 1, 'CVE-2005-2798', 5.0, 'leak data about authentication credentials'], ['2.1', '4.1p1', 1, 'CVE-2005-2798', 5.0, 'leak data about authentication credentials'],
['3.5', '3.5p1', 1, 'CVE-2004-2760', 6.8, 'leak data through different connection states'], ['3.5', '3.5p1', 1, 'CVE-2004-2760', 6.8, 'leak data through different connection states'],
['2.3', '3.7.1p2', 1, 'CVE-2004-2069', 5.0, 'cause DoS via large number of connections (slot exhaustion)'], ['2.3', '3.7.1p2', 1, 'CVE-2004-2069', 5.0, 'cause DoS via large number of connections (slot exhaustion)'],
['3.0', '3.4p1', 1, 'CVE-2004-0175', 4.3, 'leak data through directoy traversal'], ['3.0', '3.4p1', 1, 'CVE-2004-0175', 4.3, 'leak data through directory traversal'],
['1.2', '3.9p1', 1, 'CVE-2003-1562', 7.6, 'leak data about authentication credentials'], ['1.2', '3.9p1', 1, 'CVE-2003-1562', 7.6, 'leak data about authentication credentials'],
['3.1p1', '3.7.1p1', 1, 'CVE-2003-0787', 7.5, 'privilege escalation via modifying stack'], ['3.1p1', '3.7.1p1', 1, 'CVE-2003-0787', 7.5, 'privilege escalation via modifying stack'],
['3.1p1', '3.7.1p1', 1, 'CVE-2003-0786', 10.0, 'privilege escalation via bypassing authentication'], ['3.1p1', '3.7.1p1', 1, 'CVE-2003-0786', 10.0, 'privilege escalation via bypassing authentication'],
+2 -2
View File
@@ -1,4 +1,4 @@
.TH SSH-AUDIT 1 "March 13, 2022" .TH SSH-AUDIT 1 "January 28, 2024"
.SH NAME .SH NAME
\fBssh-audit\fP \- SSH server & client configuration auditor \fBssh-audit\fP \- SSH server & client configuration auditor
.SH SYNOPSIS .SH SYNOPSIS
@@ -114,7 +114,7 @@ Creates a policy based on the target server. Useful when other servers should b
.TP .TP
.B -n, \-\-no-colors .B -n, \-\-no-colors
.br .br
Disable color output. Disable color output. Automatically set when the NO_COLOR environment variable is set.
.TP .TP
.B -p, \-\-port=<port> .B -p, \-\-port=<port>