Skip to content

Commit 29bf071

Browse files
committed
Add ssh -L / ssh.connect_remote() workaround when AllowTcpForwarding is disabled
Use a netcat process on the remote to connect to the specified host:port and tunnel the traffic using normal `ssh.process` I/O. This was inspired by the "Circumventing Disabled SSH Port-Forwarding with a Multiplexer" article by @guysv in the Paged Out! zine no. 5. It allows to use `gdb.debug(arg, ssh=ssh)` to debug processes on pwn.college.
1 parent 3eb690b commit 29bf071

File tree

1 file changed

+19
-0
lines changed

1 file changed

+19
-0
lines changed

pwnlib/tubes/ssh.py

+19
Original file line numberDiff line numberDiff line change
@@ -441,14 +441,32 @@ def __init__(self, parent, host, port, *a, **kw):
441441
# keep the parent from being garbage collected in some cases
442442
self.parent = parent
443443

444+
# keep reference to tunnel process to avoid garbage collection
445+
self.tunnel = None
446+
444447
self.host = parent.host
445448
self.rhost = host
446449
self.rport = port
447450

451+
import paramiko.ssh_exception
448452
msg = 'Connecting to %s:%d via SSH to %s' % (self.rhost, self.rport, self.host)
449453
with self.waitfor(msg) as h:
450454
try:
451455
self.sock = parent.transport.open_channel('direct-tcpip', (host, port), ('127.0.0.1', 0))
456+
except paramiko.ssh_exception.ChannelException as e:
457+
# Workaround AllowTcpForwarding no in sshd_config
458+
if e.args != (1, 'Administratively prohibited'):
459+
self.exception(str(e))
460+
461+
self.debug('Failed to open channel, trying to connect to remote port manually using netcat.')
462+
if parent.which('nc'):
463+
ncat = 'nc'
464+
elif parent.which('ncat'):
465+
ncat = 'ncat'
466+
else:
467+
self.exception('Could not find ncat or nc on remote. Cannot connect to remote port.')
468+
self.tunnel = parent.process([ncat, host, str(port)])
469+
self.sock = self.tunnel.sock
452470
except Exception as e:
453471
self.exception(str(e))
454472
raise
@@ -949,6 +967,7 @@ def process(self, argv=None, executable=None, tty=True, cwd=None, env=None, igno
949967
self.upload_data(script, tmpfile)
950968
return tmpfile
951969

970+
executable = executable or argv[0]
952971
if self.isEnabledFor(logging.DEBUG):
953972
execve_repr = "execve(%r, %s, %s)" % (executable,
954973
argv,

0 commit comments

Comments
 (0)