SSH Module exception: "q must be exactly 160, 224, or 256 bits long" when authenticated with privatekey
Describe the bug when connecting with a publickey paramiko may trigger an exception. It seems that it try to parse a key as DSA when it fail to use it as RSA. The exception is not catched by netexec
To Reproduce netexec ssh host -u user --key-file private.key -p ''
[18:01:30] ERROR q must be exactly 160, 224, or 256 bits long ssh.py:238
╭──────────────────────────────────────────────────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────────────────────────────────────────────────╮
│ /home/user/.local/lib/python3.10/site-packages/nxc/protocols/ssh.py:192 in plaintext_login │
│ │
│ 189 │ │ │ if self.args.key_file or private_key: │
│ 190 │ │ │ │ self.logger.debug(f"Logging {self.host} with username: {username}, │
│ keyfile: {self.args.key_file}") │
│ 191 │ │ │ │ │
│ ❱ 192 │ │ │ │ self.conn.connect( │
│ 193 │ │ │ │ │ self.host, │
│ 194 │ │ │ │ │ port=self.port, │
│ 195 │ │ │ │ │ username=username, │
│ │
│ /home/user/.local/lib/python3.10/site-packages/paramiko/client.py:485 in connect │
│ │
│ 482 │ │ else: │
│ 483 │ │ │ key_filenames = key_filename │
│ 484 │ │ │
│ ❱ 485 │ │ self._auth( │
│ 486 │ │ │ username, │
│ 487 │ │ │ password, │
│ 488 │ │ │ pkey, │
│ │
│ /home/user/.local/lib/python3.10/site-packages/paramiko/client.py:734 in _auth │
│ │
│ 731 │ │ │ │ │ │ │ key_filename, pkey_class, passphrase │
│ 732 │ │ │ │ │ │ ) │
│ 733 │ │ │ │ │ │ allowed_types = set( │
│ ❱ 734 │ │ │ │ │ │ │ self._transport.auth_publickey(username, key) │
│ 735 │ │ │ │ │ │ ) │
│ 736 │ │ │ │ │ │ two_factor = allowed_types & two_factor_types │
│ 737 │ │ │ │ │ │ if not two_factor: │
│ │
│ /home/user/.local/lib/python3.10/site-packages/paramiko/transport.py:1674 in auth_publickey │
│ │
│ 1671 │ │ if event is not None: │
│ 1672 │ │ │ # caller wants to wait for event themselves │
│ 1673 │ │ │ return [] │
│ ❱ 1674 │ │ return self.auth_handler.wait_for_response(my_event) │
│ 1675 │ │
│ 1676 │ def auth_interactive(self, username, handler, submethods=""): │
│ 1677 │ │ """ │
│ │
│ /home/user/.local/lib/python3.10/site-packages/paramiko/auth_handler.py:248 in wait_for_response │
│ │
│ 245 │ │ │ │ │ e = AuthenticationException( │
│ 246 │ │ │ │ │ │ "Authentication failed: transport shut down or saw EOF" │
│ 247 │ │ │ │ │ ) │
│ ❱ 248 │ │ │ │ raise e │
│ 249 │ │ │ if event.is_set(): │
│ 250 │ │ │ │ break │
│ 251 │ │ │ if max_ts is not None and max_ts <= time.time(): │
│ │
│ /home/user/.local/lib/python3.10/site-packages/paramiko/transport.py:2220 in run │
│ │
│ 2217 │ │ │ │ │ │ and ptype in self.auth_handler._handler_table │
│ 2218 │ │ │ │ │ ): │
│ 2219 │ │ │ │ │ │ handler = self.auth_handler._handler_table[ptype] │
│ ❱ 2220 │ │ │ │ │ │ handler(m) │
│ 2221 │ │ │ │ │ │ if len(self._expected_packet) > 0: │
│ 2222 │ │ │ │ │ │ │ continue │
│ 2223 │ │ │ │ │ else: │
│ │
│ /home/user/.local/lib/python3.10/site-packages/paramiko/auth_handler.py:404 in _parse_service_accept │
│ │
│ 401 │ │ │ │ │ self.username, │
│ 402 │ │ │ │ │ algorithm, │
│ 403 │ │ │ │ ) │
│ ❱ 404 │ │ │ │ sig = self.private_key.sign_ssh_data(blob, algorithm) │
│ 405 │ │ │ │ m.add_string(sig) │
│ 406 │ │ │ elif self.auth_method == "keyboard-interactive": │
│ 407 │ │ │ │ m.add_string("") │
│ │
│ /home/user/.local/lib/python3.10/site-packages/paramiko/dsskey.py:112 in sign_ssh_data │
│ │
│ 109 │ │ return self.x is not None │
│ 110 │ │
│ 111 │ def sign_ssh_data(self, data, algorithm=None): │
│ ❱ 112 │ │ key = dsa.DSAPrivateNumbers( │
│ 113 │ │ │ x=self.x, │
│ 114 │ │ │ public_numbers=dsa.DSAPublicNumbers( │
│ 115 │ │ │ │ y=self.y, │
│ │
│ /home/user/.local/lib/python3.10/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py:242 in private_key │
│ │
│ 239 │ │ │ backend as ossl, │
│ 240 │ │ ) │
│ 241 │ │ │
│ ❱ 242 │ │ return ossl.load_dsa_private_numbers(self) │
│ 243 │ │
│ 244 │ def __eq__(self, other: object) -> bool: │
│ 245 │ │ if not isinstance(other, DSAPrivateNumbers): │
│ │
│ /home/user/.local/lib/python3.10/site-packages/cryptography/hazmat/backends/openssl/backend.py:876 in load_dsa_private_numbers │
│ │
│ 873 │ def load_dsa_private_numbers( │
│ 874 │ │ self, numbers: dsa.DSAPrivateNumbers │
│ 875 │ ) -> dsa.DSAPrivateKey: │
│ ❱ 876 │ │ dsa._check_dsa_private_numbers(numbers) │
│ 877 │ │ parameter_numbers = numbers.public_numbers.parameter_numbers │
│ 878 │ │ │
│ 879 │ │ dsa_cdata = self._lib.DSA_new() │
│ │
│ /home/user/.local/lib/python3.10/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py:283 in _check_dsa_private_numbers │
│ │
│ 280 │
│ 281 def _check_dsa_private_numbers(numbers: DSAPrivateNumbers) -> None: │
│ 282 │ parameters = numbers.public_numbers.parameter_numbers │
│ ❱ 283 │ _check_dsa_parameters(parameters) │
│ 284 │ if numbers.x <= 0 or numbers.x >= parameters.q: │
│ 285 │ │ raise ValueError("x must be > 0 and < q.") │
│ 286 │
│ │
│ /home/user/.local/lib/python3.10/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py:275 in _check_dsa_parameters │
│ │
│ 272 │ │ │ "p must be exactly 1024, 2048, 3072, or 4096 bits long" │
│ 273 │ │ ) │
│ 274 │ if parameters.q.bit_length() not in [160, 224, 256]: │
│ ❱ 275 │ │ raise ValueError("q must be exactly 160, 224, or 256 bits long") │
│ 276 │ │
│ 277 │ if not (1 < parameters.g < parameters.p): │
│ 278 │ │ raise ValueError("g, p don't satisfy 1 < g < p.") │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
ValueError: q must be exactly 160, 224, or 256 bits long
...
Expected behavior Exception catched and a warning/or error displayed
Screenshots
Duplicates: https://github.com/byt3bl33d3r/CrackMapExec/issues/454 https://github.com/paramiko/paramiko/issues/2048 https://github.com/fabric/fabric/issues/2182 https://github.com/fabric/fabric/issues/2140 https://github.com/paramiko/paramiko/issues/387
Some of my test scripts were hitting this issue. To work around, I had to first run this:
ssh-copy-id root@