mirror of
https://github.com/jtesta/ssh-audit.git
synced 2024-11-22 10:31:41 +01:00
Now handles exceptions during server KEX parsing more gracefully.
This commit is contained in:
parent
32ed9242af
commit
aa21df29e7
@ -177,6 +177,7 @@ For convenience, a web front-end on top of the command-line tool is available at
|
|||||||
## ChangeLog
|
## ChangeLog
|
||||||
### v2.5.0-dev (???)
|
### v2.5.0-dev (???)
|
||||||
- Fixed crash when running host key tests.
|
- Fixed crash when running host key tests.
|
||||||
|
- Handles server connection failures more gracefully.
|
||||||
- Now prints JSON with indents when `-jj` is used (useful for debugging).
|
- Now prints JSON with indents when `-jj` is used (useful for debugging).
|
||||||
- Added MD5 fingerprints to verbose output.
|
- Added MD5 fingerprints to verbose output.
|
||||||
- Added `-d`/`--debug` option for getting debugging output; credit [Adam Russell](https://github.com/thecliguy).
|
- Added `-d`/`--debug` option for getting debugging output; credit [Adam Russell](https://github.com/thecliguy).
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
from typing import Dict, List, Set, Sequence, Tuple, Iterable # noqa: F401
|
from typing import Dict, List, Set, Sequence, Tuple, Iterable # noqa: F401
|
||||||
from typing import Callable, Optional, Union, Any # noqa: F401
|
from typing import Callable, Optional, Union, Any # noqa: F401
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
|
||||||
from ssh_audit.kexdh import KexGroupExchange_SHA1, KexGroupExchange_SHA256
|
from ssh_audit.kexdh import KexGroupExchange_SHA1, KexGroupExchange_SHA256
|
||||||
from ssh_audit.ssh2_kexdb import SSH2_KexDB
|
from ssh_audit.ssh2_kexdb import SSH2_KexDB
|
||||||
from ssh_audit.ssh2_kex import SSH2_Kex
|
from ssh_audit.ssh2_kex import SSH2_Kex
|
||||||
@ -58,9 +60,13 @@ class GEXTest:
|
|||||||
# server's own values.
|
# server's own values.
|
||||||
s.send_kexinit(key_exchanges=[gex_alg], hostkeys=kex.key_algorithms, ciphers=kex.server.encryption, macs=kex.server.mac, compressions=kex.server.compression, languages=kex.server.languages)
|
s.send_kexinit(key_exchanges=[gex_alg], hostkeys=kex.key_algorithms, ciphers=kex.server.encryption, macs=kex.server.mac, compressions=kex.server.compression, languages=kex.server.languages)
|
||||||
|
|
||||||
|
try:
|
||||||
# Parse the server's KEX.
|
# Parse the server's KEX.
|
||||||
_, payload = s.read_packet(2)
|
_, payload = s.read_packet(2)
|
||||||
SSH2_Kex.parse(payload)
|
SSH2_Kex.parse(payload)
|
||||||
|
except Exception:
|
||||||
|
out.v("Failed to parse server's kex. Stack trace:\n%s" % str(traceback.format_exc()), write_now=True)
|
||||||
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
from typing import Dict, List, Set, Sequence, Tuple, Iterable # noqa: F401
|
from typing import Dict, List, Set, Sequence, Tuple, Iterable # noqa: F401
|
||||||
from typing import Callable, Optional, Union, Any # noqa: F401
|
from typing import Callable, Optional, Union, Any # noqa: F401
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
|
||||||
from ssh_audit.kexdh import KexDH, KexGroup1, KexGroup14_SHA1, KexGroup14_SHA256, KexCurve25519_SHA256, KexGroup16_SHA512, KexGroup18_SHA512, KexGroupExchange_SHA1, KexGroupExchange_SHA256, KexNISTP256, KexNISTP384, KexNISTP521
|
from ssh_audit.kexdh import KexDH, KexGroup1, KexGroup14_SHA1, KexGroup14_SHA256, KexCurve25519_SHA256, KexGroup16_SHA512, KexGroup18_SHA512, KexGroupExchange_SHA1, KexGroupExchange_SHA256, KexNISTP256, KexNISTP384, KexNISTP521
|
||||||
from ssh_audit.ssh2_kex import SSH2_Kex
|
from ssh_audit.ssh2_kex import SSH2_Kex
|
||||||
from ssh_audit.ssh2_kexdb import SSH2_KexDB
|
from ssh_audit.ssh2_kexdb import SSH2_KexDB
|
||||||
@ -123,10 +125,13 @@ class HostKeyTest:
|
|||||||
# Send our KEX using the specified group-exchange and most of the server's own values.
|
# Send our KEX using the specified group-exchange and most of the server's own values.
|
||||||
s.send_kexinit(key_exchanges=[kex_str], hostkeys=[host_key_type], ciphers=server_kex.server.encryption, macs=server_kex.server.mac, compressions=server_kex.server.compression, languages=server_kex.server.languages)
|
s.send_kexinit(key_exchanges=[kex_str], hostkeys=[host_key_type], ciphers=server_kex.server.encryption, macs=server_kex.server.mac, compressions=server_kex.server.compression, languages=server_kex.server.languages)
|
||||||
|
|
||||||
|
try:
|
||||||
# Parse the server's KEX.
|
# Parse the server's KEX.
|
||||||
_, payload = s.read_packet()
|
_, payload = s.read_packet()
|
||||||
SSH2_Kex.parse(payload)
|
SSH2_Kex.parse(payload)
|
||||||
|
except Exception:
|
||||||
|
out.v("Failed to parse server's kex. Stack trace:\n%s" % str(traceback.format_exc()), write_now=True)
|
||||||
|
return
|
||||||
|
|
||||||
# Do the initial DH exchange. The server responds back
|
# Do the initial DH exchange. The server responds back
|
||||||
# with the host key and its length. Bingo. We also get back the host key fingerprint.
|
# with the host key and its length. Bingo. We also get back the host key fingerprint.
|
||||||
|
@ -895,7 +895,12 @@ def audit(out: OutputBuffer, aconf: AuditConf, sshv: Optional[int] = None, print
|
|||||||
if sshv == 1:
|
if sshv == 1:
|
||||||
program_retval = output(out, aconf, banner, header, pkm=SSH1_PublicKeyMessage.parse(payload))
|
program_retval = output(out, aconf, banner, header, pkm=SSH1_PublicKeyMessage.parse(payload))
|
||||||
elif sshv == 2:
|
elif sshv == 2:
|
||||||
|
try:
|
||||||
kex = SSH2_Kex.parse(payload)
|
kex = SSH2_Kex.parse(payload)
|
||||||
|
except Exception:
|
||||||
|
out.fail("Failed to parse server's kex. Stack trace:\n%s" % str(traceback.format_exc()))
|
||||||
|
return exitcodes.CONNECTION_ERROR
|
||||||
|
|
||||||
if aconf.client_audit is False:
|
if aconf.client_audit is False:
|
||||||
HostKeyTest.run(out, s, kex)
|
HostKeyTest.run(out, s, kex)
|
||||||
GEXTest.run(out, s, kex)
|
GEXTest.run(out, s, kex)
|
||||||
|
Loading…
Reference in New Issue
Block a user