Skip to content

Commit

Permalink
Add tracking of session renegotiation successs count and test
Browse files Browse the repository at this point in the history
  • Loading branch information
mxsasha committed Oct 8, 2024
1 parent f262aa8 commit 4655a00
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 8 deletions.
23 changes: 16 additions & 7 deletions sslyze/plugins/session_renegotiation_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,26 @@ class SessionRenegotiationScanResult(ScanCommandResult):
Attributes:
accepts_client_renegotiation: True if the server honors client-initiated renegotiation attempts.
supports_secure_renegotiation: True if the server supports secure renegotiation.
client_renegotiations_success_count: the number of successful client-initiated renegotiation attempts.
"""

supports_secure_renegotiation: bool
is_vulnerable_to_client_renegotiation_dos: bool
client_renegotiations_success_count: int


class SessionRenegotiationScanResultAsJson(BaseModelWithOrmModeAndForbid):
supports_secure_renegotiation: bool
is_vulnerable_to_client_renegotiation_dos: bool
client_renegotiations_success_count: int


class SessionRenegotiationScanAttemptAsJson(ScanCommandAttemptAsJson):
result: Optional[SessionRenegotiationScanResultAsJson]


class _ScanJobResultEnum(Enum):
IS_VULNERABLE_TO_CLIENT_RENEG_DOS = 1
CLIENT_RENEG_RESULT = 1
SUPPORTS_SECURE_RENEG = 2


Expand Down Expand Up @@ -87,7 +90,9 @@ def result_to_console_output(cls, result: SessionRenegotiationScanResult) -> Lis
return result_txt


class SessionRenegotiationImplementation(ScanCommandImplementation[SessionRenegotiationScanResult, None]):
class SessionRenegotiationImplementation(
ScanCommandImplementation[SessionRenegotiationScanResult, SessionRenegotiationExtraArgument]
):
"""Test a server for insecure TLS renegotiation and client-initiated renegotiation."""

cli_connector_cls = _SessionRenegotiationCliConnector
Expand Down Expand Up @@ -118,11 +123,13 @@ def result_for_completed_scan_jobs(
result_enum, value = job.get_result()
results_dict[result_enum] = value

is_vulnerable_to_client_renegotiation_dos, client_renegotiations_success_count = results_dict[
_ScanJobResultEnum.CLIENT_RENEG_RESULT
]
return SessionRenegotiationScanResult(
is_vulnerable_to_client_renegotiation_dos=results_dict[
_ScanJobResultEnum.IS_VULNERABLE_TO_CLIENT_RENEG_DOS
],
is_vulnerable_to_client_renegotiation_dos=is_vulnerable_to_client_renegotiation_dos,
supports_secure_renegotiation=results_dict[_ScanJobResultEnum.SUPPORTS_SECURE_RENEG],
client_renegotiations_success_count=client_renegotiations_success_count,
)


Expand Down Expand Up @@ -163,9 +170,10 @@ def _test_secure_renegotiation(server_info: ServerConnectivityInfo) -> Tuple[_Sc

def _test_client_renegotiation(
server_info: ServerConnectivityInfo, client_renegotiation_attempts: int
) -> Tuple[_ScanJobResultEnum, bool]:
) -> Tuple[_ScanJobResultEnum, Tuple[bool, int]]:
"""Check whether the server honors session renegotiation requests."""
# Try with TLS 1.2 even if the server supports TLS 1.3 or higher as there is no reneg with TLS 1.3
client_renegotiations_success_count = 0
if server_info.tls_probing_result.highest_tls_version_supported.value >= TlsVersionEnum.TLS_1_3.value:
tls_version_to_use = TlsVersionEnum.TLS_1_2
downgraded_from_tls_1_3 = True
Expand Down Expand Up @@ -198,6 +206,7 @@ def _test_client_renegotiation(
# https://github.com/nabla-c0d3/sslyze/issues/473
for i in range(client_renegotiation_attempts):
ssl_connection.ssl_client.do_renegotiate()
client_renegotiations_success_count += 1
accepts_client_renegotiation = True

# Errors caused by a server rejecting the renegotiation
Expand Down Expand Up @@ -246,4 +255,4 @@ def _test_client_renegotiation(
finally:
ssl_connection.close()

return _ScanJobResultEnum.IS_VULNERABLE_TO_CLIENT_RENEG_DOS, accepts_client_renegotiation
return _ScanJobResultEnum.CLIENT_RENEG_RESULT, (accepts_client_renegotiation, client_renegotiations_success_count)
12 changes: 11 additions & 1 deletion tests/plugins_tests/test_session_renegotiation_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
SessionRenegotiationImplementation,
SessionRenegotiationScanResult,
SessionRenegotiationScanResultAsJson,
SessionRenegotiationExtraArgument,
)

from sslyze.server_setting import (
Expand Down Expand Up @@ -40,17 +41,26 @@ def test_renegotiation_good(self) -> None:
@can_only_run_on_linux_64
def test_renegotiation_is_vulnerable_to_client_renegotiation_dos(self) -> None:
# Given a server that is vulnerable to client renegotiation DOS
expected_renegotiations_success_count = 3

with LegacyOpenSslServer() as server:
server_location = ServerNetworkLocation(
hostname=server.hostname, ip_address=server.ip_address, port=server.port
)
extra_arg = SessionRenegotiationExtraArgument(
client_renegotiation_attempts=expected_renegotiations_success_count
)
server_info = check_connectivity_to_server_and_return_info(server_location)

# When testing for insecure reneg, it succeeds
result: SessionRenegotiationScanResult = SessionRenegotiationImplementation.scan_server(server_info)
result: SessionRenegotiationScanResult = SessionRenegotiationImplementation.scan_server(
server_info,
extra_arguments=extra_arg,
)

# And the server is reported as vulnerable
assert result.is_vulnerable_to_client_renegotiation_dos
assert result.client_renegotiations_success_count == expected_renegotiations_success_count

# And a CLI output can be generated
assert SessionRenegotiationImplementation.cli_connector_cls.result_to_console_output(result)
Expand Down

0 comments on commit 4655a00

Please sign in to comment.