Changed SSH Channel to use SSHClient interface

This commit is contained in:
Caleb Stewart 2021-06-13 02:32:37 -04:00
parent f74510afb6
commit e9ee01cd30
2 changed files with 41 additions and 50 deletions

View File

@ -22,6 +22,13 @@ from pwncat.commands import connect
from pwncat.platform import PlatformError
def existing_file(path):
path = os.path.expanduser(path)
if os.path.isfile(path):
return path
raise NotADirectoryError(path)
def main():
# Default log-level is "INFO"
@ -45,7 +52,7 @@ def main():
parser.add_argument(
"--identity",
"-i",
type=argparse.FileType("r"),
type=existing_file,
default=None,
help="Private key for SSH authentication",
)

View File

@ -40,60 +40,44 @@ class Ssh(Channel):
password = prompt("Password: ", is_password=True)
try:
# Connect to the remote host's ssh server
sock = socket.create_connection((host, port))
except Exception as exc:
raise ChannelError(str(exc))
client = paramiko.client.SSHClient()
client.set_missing_host_key_policy(paramiko.client.AutoAddPolicy)
# Create a paramiko SSH transport layer around the socket
t = paramiko.Transport(sock)
try:
t.start_client()
except paramiko.SSHException:
sock.close()
raise ChannelError("ssh negotiation failed")
if identity is not None:
try:
# Load the private key for the user
if isinstance(identity, str):
key = paramiko.RSAKey.from_private_key_file(
os.path.expanduser(identity)
)
else:
key = paramiko.RSAKey.from_private_key(identity)
except:
password = prompt("RSA Private Key Passphrase: ", is_password=True)
try:
key = paramiko.RSAKey.from_private_key_file(identity, password)
except:
raise ChannelError("invalid private key or passphrase")
client.connect(
hostname=host,
port=port,
username=user,
password=password,
key_filename=os.path.expanduser(identity),
allow_agent=True,
look_for_keys=False,
)
except paramiko.ssh_exception.PasswordRequiredException:
passphrase = prompt("RSA Private Key Passphrase: ", is_password=True)
client.connect(
hostname=host,
port=port,
username=user,
password=password,
key_filename=os.path.expanduser(identity),
allow_agent=True,
look_for_keys=False,
passphrase=passphrase,
)
# Attempt authentication
try:
t.auth_publickey(user, key)
except paramiko.ssh_exception.AuthenticationException as exc:
raise ChannelError(str(exc))
else:
try:
t.auth_password(user, password)
except paramiko.ssh_exception.AuthenticationException as exc:
raise ChannelError(str(exc))
columns, rows = os.get_terminal_size(0)
shell = client.invoke_shell(width=columns, height=rows)
shell.setblocking(0)
if not t.is_authenticated():
t.close()
sock.close()
raise ChannelError("authentication failed")
self.client = shell
self.address = (host, port)
self._connected = True
# Open an interactive session
chan = t.open_session()
chan.get_pty()
chan.invoke_shell()
chan.setblocking(0)
self.client = chan
self.address = (host, port)
self._connected = True
except paramiko.ssh_exception.AuthenticationException as exc:
raise ChannelError(f"ssh authentication failed: {str(exc)}") from exc
except (paramiko.ssh_exception.SSHException, socket.error) as exc:
raise ChannelError(f"ssh connection failed: {str(exc)}") from exc
@property
def connected(self):