python-paramiko/backport-0003-CVE-2023-48795.patch
zhangpan 30d6fa75a8 fix CVE-2023-48795
(cherry picked from commit eee395ba519760fae8c5eb1a104027c07fd5a182)
2024-01-12 09:52:41 +08:00

116 lines
4.2 KiB
Diff

From f4dedacb9040d27d9844f51c81c28e0247d3e4a3 Mon Sep 17 00:00:00 2001
From: Jeff Forcier <jeff@bitprophet.org>
Date: Sat, 16 Dec 2023 13:02:05 -0500
Subject: [PATCH] Raise new exception type when unexpected messages appear
Reference:https://github.com/paramiko/paramiko/commit/f4dedacb9040d27d9844f51c81c28e0247d3e4a3
Conflict:The changlog file is adapted for different versions. The context of the test case import module is adapted.
---
paramiko/__init__.py | 1 +
paramiko/ssh_exception.py | 9 +++++++++
paramiko/transport.py | 6 +++++-
tests/test_transport.py | 22 +++++++++++++++++++---
4 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/paramiko/__init__.py b/paramiko/__init__.py
index cbc240a..1bc91d0 100644
--- a/paramiko/__init__.py
+++ b/paramiko/__init__.py
@@ -43,6 +43,7 @@ from paramiko.ssh_exception import (
ConfigParseError,
CouldNotCanonicalize,
IncompatiblePeer,
+ MessageOrderError,
PasswordRequiredException,
ProxyCommandFailure,
SSHException,
diff --git a/paramiko/ssh_exception.py b/paramiko/ssh_exception.py
index 620ab25..8a1413b 100644
--- a/paramiko/ssh_exception.py
+++ b/paramiko/ssh_exception.py
@@ -235,3 +235,12 @@ class ConfigParseError(SSHException):
"""
pass
+
+
+class MessageOrderError(SSHException):
+ """
+ Out-of-order protocol messages were received, violating "strict kex" mode.
+ .. versionadded:: 3.4
+ """
+
+ pass
diff --git a/paramiko/transport.py b/paramiko/transport.py
index 2d6d581..eb1bcd6 100644
--- a/paramiko/transport.py
+++ b/paramiko/transport.py
@@ -110,6 +110,7 @@ from paramiko.ssh_exception import (
BadAuthenticationType,
ChannelException,
IncompatiblePeer,
+ MessageOrderError,
ProxyCommandFailure,
)
from paramiko.util import retry_on_signal, ClosingContextManager, clamp_value
@@ -2129,7 +2130,10 @@ class Transport(threading.Thread, ClosingContextManager):
continue
if len(self._expected_packet) > 0:
if ptype not in self._expected_packet:
- raise SSHException(
+ exc_class = SSHException
+ if self.agreed_on_strict_kex:
+ exc_class = MessageOrderError
+ raise exc_class(
"Expecting packet from {!r}, got {:d}".format(
self._expected_packet, ptype
)
diff --git a/tests/test_transport.py b/tests/test_transport.py
index c8cd498..19023eb 100644
--- a/tests/test_transport.py
+++ b/tests/test_transport.py
@@ -42,6 +42,7 @@ from paramiko import (
SSHException,
AuthenticationException,
IncompatiblePeer,
+ MessageOrderError,
SecurityOptions,
ServerInterface,
Transport,
@@ -64,7 +65,7 @@ from paramiko.message import Message
from .util import needs_builtin, _support, requires_sha1_signing, slow
from .loop import LoopSocket
-from pytest import skip, mark
+from pytest import skip, mark, raises
LONG_BANNER = """\
@@ -1504,5 +1505,20 @@ class TestStrictKex:
def test_sequence_numbers_reset_on_newkeys(self):
skip()
- def test_error_raised_on_out_of_order_handshakes(self):
- skip()
+ def test_MessageOrderError_raised_on_out_of_order_messages(self):
+ with raises(MessageOrderError):
+ with server() as (tc, _):
+ # A bit artificial as it's outside kexinit/handshake, but much
+ # easier to trigger and still in line with behavior under test
+ tc._expect_packet(MSG_KEXINIT)
+ tc.open_session()
+
+ def test_SSHException_raised_on_out_of_order_messages_when_not_strict(self):
+ # This is kind of dumb (either situation is still fatal!) but whatever,
+ # may as well be strict with our new strict flag...
+ with raises(SSHException) as info: # would be true either way, but
+ with server(client_init=dict(strict_kex=False),
+ ) as (tc, _):
+ tc._expect_packet(MSG_KEXINIT)
+ tc.open_session()
+ assert info.type is SSHException # NOT MessageOrderError!
--
2.33.0