Compare commits

...

3 Commits

Author SHA1 Message Date
Joe Testa 8124c8e443 Added aes128-ocb@libassh.org cipher. 2024-04-18 21:09:02 -04:00
Joe Testa b9f569fdf8 Added warnings for Windows platform. 2024-04-18 20:51:14 -04:00
Joe Testa 9126ae7d9c Improved DHEat statistics output. 2024-04-18 20:01:28 -04:00
3 changed files with 31 additions and 18 deletions

View File

@ -227,6 +227,7 @@ For convenience, a web front-end on top of the command-line tool is available at
- Custom policies now support the `allow_algorithm_subset_and_reordering` directive to allow targets to pass with a subset and/or re-ordered list of host keys, kex, ciphers, and MACs. This allows for the creation of a baseline policy where targets can optionally implement stricter controls; partial credit [yannik1015](https://github.com/yannik1015).
- Custom policies now support the `allow_larger_keys` directive to allow targets to pass with larger host keys, CA keys, and Diffie-Hellman keys. This allows for the creation of a baseline policy where targets can optionally implement stricter controls; partial credit [Damian Szuberski](https://github.com/szubersk).
- Added 1 new key exchange algorithm: `gss-nistp384-sha384-*`.
- Added 1 new cipher: `aes128-ocb@libassh.org`.
### 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)).

View File

@ -28,6 +28,7 @@ import random
import select
import socket
import struct
import sys
import time
import traceback
@ -317,6 +318,11 @@ class DHEat:
socket_list.remove(s)
if sys.platform == "win32":
DHEat.YELLOWB = "\033[1;93m"
DHEat.CLEAR = "\033[0m"
print("\n%sUnfortunately, this feature is not currently functional under Windows.%s This should get fixed in a future release. See: <https://github.com/jtesta/ssh-audit/issues/261>" % (DHEat.YELLOWB, DHEat.CLEAR))
return ""
spinner = ["-", "\\", "|", "/"]
spinner_index = 0
@ -654,34 +660,36 @@ class DHEat:
# Print extensive statistics on what just happened.
seconds_running = time.time() - self.start_timer
print("\n\n")
print(" %s %sSTATISTICS%s %s" % (self.BAR_CHART, self.WHITEB, self.CLEAR, self.CHART_UPWARDS))
print(" %s----------%s" % (self.WHITEB, self.CLEAR))
print(" %s %sSTATISTICS%s %s" % (self.BAR_CHART, self.WHITEB, self.CLEAR, self.CHART_UPWARDS))
print(" %s----------%s" % (self.WHITEB, self.CLEAR))
print()
print(" Run time: %s%.1f seconds%s" % (self.WHITEB, seconds_running, self.CLEAR))
print(" Run time: %s%.1f seconds%s" % (self.WHITEB, seconds_running, self.CLEAR))
print()
print(" Attempted TCP connections: %s%.1f/sec, %u total%s" % (self.WHITEB, self.num_attempted_tcp_connections / seconds_running, self.num_attempted_tcp_connections, self.CLEAR))
print(" Successful TCP connections: %s%.1f/sec, %u total%s" % (self.WHITEB, self.num_successful_tcp_connections / seconds_running, self.num_successful_tcp_connections, self.CLEAR))
print(" Attempted TCP connections: %s%.1f/sec, %u total%s" % (self.WHITEB, self.num_attempted_tcp_connections / seconds_running, self.num_attempted_tcp_connections, self.CLEAR))
print(" Successful TCP connections: %s%.1f/sec, %u total%s" % (self.WHITEB, self.num_successful_tcp_connections / seconds_running, self.num_successful_tcp_connections, self.CLEAR))
print()
print(" Bytes written: %s%s/sec, %s total%s" % (self.WHITEB, DHEat.add_byte_units(self.num_bytes_written / seconds_running), DHEat.add_byte_units(self.num_bytes_written), self.CLEAR))
print(" Bytes written: %s%s/sec, %s total%s" % (self.WHITEB, DHEat.add_byte_units(self.num_bytes_written / seconds_running), DHEat.add_byte_units(self.num_bytes_written), self.CLEAR))
print()
print(" Successful DH KEX replies: %s%.1f/sec, %u total%s" % (self.WHITEB, self.num_successful_dh_kex / seconds_running, self.num_successful_dh_kex, self.CLEAR))
print(" Unexpected DH KEX replies: %s%.1f/sec, %u total%s" % (self.WHITEB, self.num_failed_dh_kex / seconds_running, self.num_failed_dh_kex, self.CLEAR))
print()
print("OpenSSH-throttled connections: %s%.1f/sec, %u total%s" % (self.WHITEB, self.num_openssh_throttled_connections / seconds_running, self.num_openssh_throttled_connections, self.CLEAR))
print(" Connection timeouts: %s%.1f/sec, %u total%s (timeout setting: %.1f sec)" % (self.WHITEB, self.num_connect_timeouts / seconds_running, self.num_connect_timeouts, self.CLEAR, self.connect_timeout))
print(" Read timeouts: %s%.1f/sec, %u total%s (timeout setting: %.1f sec)" % (self.WHITEB, self.num_read_timeouts / seconds_running, self.num_read_timeouts, self.CLEAR, self.read_timeout))
print(" Socket exceptions: %s%.1f/sec, %u total%s" % (self.WHITEB, self.num_socket_exceptions / seconds_running, self.num_socket_exceptions, self.CLEAR))
print(" Successful DH KEX replies: %s%.1f/sec, %u total%s" % (self.WHITEB, self.num_successful_dh_kex / seconds_running, self.num_successful_dh_kex, self.CLEAR))
print(" Unexpected DH KEX replies: %s%.1f/sec, %u total%s" % (self.WHITEB, self.num_failed_dh_kex / seconds_running, self.num_failed_dh_kex, self.CLEAR))
print("\"Exceeded MaxStartups\" replies*: %s%.1f/sec, %u total%s" % (self.WHITEB, self.num_openssh_throttled_connections / seconds_running, self.num_openssh_throttled_connections, self.CLEAR))
print()
print(" Connection timeouts: %s%.1f/sec, %u total%s (timeout setting: %.1f sec)" % (self.WHITEB, self.num_connect_timeouts / seconds_running, self.num_connect_timeouts, self.CLEAR, self.connect_timeout))
print(" Read timeouts: %s%.1f/sec, %u total%s (timeout setting: %.1f sec)" % (self.WHITEB, self.num_read_timeouts / seconds_running, self.num_read_timeouts, self.CLEAR, self.read_timeout))
print(" Socket exceptions: %s%.1f/sec, %u total%s" % (self.WHITEB, self.num_socket_exceptions / seconds_running, self.num_socket_exceptions, self.CLEAR))
print()
if seconds_running < 3.0:
print("Total run time was under 3 seconds; try running it for longer to get more accurate analysis.")
if seconds_running < 5.0:
print("%sTotal run time was under 5 seconds; try running it for longer to get more accurate analysis.%s" % (DHEat.YELLOWB, DHEat.CLEAR))
elif self.num_successful_tcp_connections / seconds_running < DHEat.MAX_SAFE_RATE:
print("Because the number of successful TCP connections per second (%.1f) is less than %.1f, it appears that the target is using rate limiting to prevent CPU exaustion." % (self.num_successful_tcp_connections / seconds_running, DHEat.MAX_SAFE_RATE))
print("Because the number of successful TCP connections per second (%.1f) is less than %.1f, it appears that the target %sis using rate limiting%s to prevent CPU exaustion." % (self.num_successful_tcp_connections / seconds_running, DHEat.MAX_SAFE_RATE, DHEat.GREENB, DHEat.CLEAR))
else:
print("Because the number of successful TCP connections per second (%.1f) is greater than %.1f, it appears that the target is %sNOT%s using rate limiting to prevent CPU exaustion." % (self.num_successful_tcp_connections / seconds_running, DHEat.MAX_SAFE_RATE, DHEat.REDB, DHEat.CLEAR))
print("Because the number of successful TCP connections per second (%.1f) is greater than %.1f, it appears that the target %sis NOT using rate limiting%s to prevent CPU exaustion." % (self.num_successful_tcp_connections / seconds_running, DHEat.MAX_SAFE_RATE, DHEat.REDB, DHEat.CLEAR))
print()
print()
print(" * OpenSSH has a throttling mechanism (controlled by the MaxStartups directive) to prevent too many pre-authentication connections from overwhelming the server. When triggered, the server will probabilistically return \"Exceeded MaxStartups\" instead of the usual SSH banner, then terminate the connection. In order to maximize the DoS effectiveness, this metric should be greater than zero, though the ideal rate of rejections depends on the target server's CPU resources.")
print()
def _run(self) -> bool:
@ -689,6 +697,9 @@ class DHEat:
self.output()
if sys.platform == "win32":
self.output("%sWARNING:%s this feature has not been thoroughly tested on Windows. It may perform worse than on UNIX OSes." % (self.YELLOWB, self.CLEAR))
self.output("Running DHEat test against %s[%s]:%u%s with %s%u%s concurrent sockets..." % (self.WHITEB, self.target, self.port, self.CLEAR, self.WHITEB, self.concurrent_connections, self.CLEAR))
# If the user didn't specify an exact kex algorithm to test, check our prioritized list against what the server supports. Larger p-values (such as group18: 8192-bits) cause the most strain on the server.

View File

@ -1,7 +1,7 @@
"""
The MIT License (MIT)
Copyright (C) 2017-2023 Joe Testa (jtesta@positronsecurity.com)
Copyright (C) 2017-2024 Joe Testa (jtesta@positronsecurity.com)
Copyright (C) 2017 Andris Raugulis (moo@arthepsy.eu)
Permission is hereby granted, free of charge, to any person obtaining a copy
@ -297,6 +297,7 @@ class SSH2_KexDB: # pylint: disable=too-few-public-methods
'aes128-ctr': [['3.7,d0.52,l10.4.1']],
'aes128-gcm': [[]],
'aes128-gcm@openssh.com': [['6.2']],
'aes128-ocb@libassh.org': [[], [], [WARN_CIPHER_MODE]],
'aes192-cbc': [['2.3.0,l10.2', '6.6', None], [], [WARN_CIPHER_MODE]],
'aes192-ctr': [['3.7,l10.4.1']],
'aes192-gcm@openssh.com': [[], [], [], [INFO_NEVER_IMPLEMENTED_IN_OPENSSH]],