From b65ef8b730178bed7eb4c12590a9ef22f4a31d75 Mon Sep 17 00:00:00 2001 From: Mari Wahl Date: Wed, 17 Dec 2014 18:16:52 -0500 Subject: [PATCH] paramiko readme typos, reverse ssh tunneling script --- Network_and_802.11/paramiko/README.md | 14 +- Network_and_802.11/paramiko/rforward.py | 167 ++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 7 deletions(-) create mode 100644 Network_and_802.11/paramiko/rforward.py diff --git a/Network_and_802.11/paramiko/README.md b/Network_and_802.11/paramiko/README.md index e7fb9b3..a4dc279 100644 --- a/Network_and_802.11/paramiko/README.md +++ b/Network_and_802.11/paramiko/README.md @@ -2,7 +2,7 @@ **Paramiko** is awesome!!! It uses my dear [PyCrypto](https://www.dlitz.net/software/pycrypto/) to give us access to the [SSH2 protocol](http://en.wikipedia.org/wiki/SSH2), and it has a flexible and easy to use API. -You are going to see it with your own eyes: in this post we will write code for SSH clients and servers, reverse shells and tunnel connections, and it will be smooth and fun. +You are going to see it with your own eyes: in this post we will see code for SSH clients and servers, reverse shells, and tunnel connections, and it will be smooth and fun! Shall we start? @@ -178,10 +178,10 @@ class Server(paramiko.ServerInterface): Now, let's take a look at the **main** function, which does the following: 1. Creates a socket object to bind the host and port, so it can listen for incoming connections. -2. Once a connection is established (the client tried to connect to the server and the socket accepted the connection), it creates a **paramiko** Transport object for this socket. +2. Once a connection is established (the client tried to connect to the server and the socket accepted the connection), it creates a **paramiko** Transport object for this socket (in paramiko there are two main communication methods: *transport*, which makes and maintains the encrypted connection, and *channel*, which is like a sock for sending/receiving data over the encrypted session).- 3. The program instantiates a **Server** object and starts the paramiko session with it. -4. Authentication is attempted. -4. Once the authentication is successful, the server starts a loop where it will keep getting input commands from the user and issuing it in the client. This is our reversed shell! +4. Authentication is attempted. If it is successful, we get a **ClientConnected** message. +5. The server starts a loop where it will keep getting input commands from the user and issuing it in the client. This is our reversed shell! ```python import paramiko @@ -361,12 +361,12 @@ Enter command: **Awesomesauce!** + Ah, by the way, all these scripts work not only in Linux but in Windows and Mac as well (so next time you are in a lame Windows machine, no need to install [Putty](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html) anymore =p ). ------ - - +--- ## Further References: +- [Paramikos reverse SSH tunneling](https://github.com/paramiko/paramiko/blob/master/demos/rforward.py). - [Black Hat Python](http://www.nostarch.com/blackhatpython). - [My Gray hat repo](https://github.com/bt3gl/My-Gray-Hacker-Resources). diff --git a/Network_and_802.11/paramiko/rforward.py b/Network_and_802.11/paramiko/rforward.py new file mode 100644 index 0000000..ae70670 --- /dev/null +++ b/Network_and_802.11/paramiko/rforward.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python + +# Copyright (C) 2008 Robey Pointer +# +# This file is part of paramiko. +# +# Paramiko is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 2.1 of the License, or (at your option) +# any later version. +# +# Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Paramiko; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +""" +Sample script showing how to do remote port forwarding over paramiko. + +This script connects to the requested SSH server and sets up remote port +forwarding (the openssh -R option) from a remote port through a tunneled +connection to a destination reachable from the local machine. +""" + +import getpass +import os +import socket +import select +import sys +import threading +from optparse import OptionParser + +import paramiko + +SSH_PORT = 22 +DEFAULT_PORT = 4000 + +g_verbose = True + + +def handler(chan, host, port): + sock = socket.socket() + try: + sock.connect((host, port)) + except Exception as e: + verbose('Forwarding request to %s:%d failed: %r' % (host, port, e)) + return + + verbose('Connected! Tunnel open %r -> %r -> %r' % (chan.origin_addr, + chan.getpeername(), (host, port))) + while True: + r, w, x = select.select([sock, chan], [], []) + if sock in r: + data = sock.recv(1024) + if len(data) == 0: + break + chan.send(data) + if chan in r: + data = chan.recv(1024) + if len(data) == 0: + break + sock.send(data) + chan.close() + sock.close() + verbose('Tunnel closed from %r' % (chan.origin_addr,)) + + +def reverse_forward_tunnel(server_port, remote_host, remote_port, transport): + transport.request_port_forward('', server_port) + while True: + chan = transport.accept(1000) + if chan is None: + continue + thr = threading.Thread(target=handler, args=(chan, remote_host, remote_port)) + thr.setDaemon(True) + thr.start() + + +def verbose(s): + if g_verbose: + print(s) + + +HELP = """\ +Set up a reverse forwarding tunnel across an SSH server, using paramiko. A +port on the SSH server (given with -p) is forwarded across an SSH session +back to the local machine, and out to a remote site reachable from this +network. This is similar to the openssh -R option. +""" + + +def get_host_port(spec, default_port): + "parse 'hostname:22' into a host and port, with the port optional" + args = (spec.split(':', 1) + [default_port])[:2] + args[1] = int(args[1]) + return args[0], args[1] + + +def parse_options(): + global g_verbose + + parser = OptionParser(usage='usage: %prog [options] [:]', + version='%prog 1.0', description=HELP) + parser.add_option('-q', '--quiet', action='store_false', dest='verbose', default=True, + help='squelch all informational output') + parser.add_option('-p', '--remote-port', action='store', type='int', dest='port', + default=DEFAULT_PORT, + help='port on server to forward (default: %d)' % DEFAULT_PORT) + parser.add_option('-u', '--user', action='store', type='string', dest='user', + default=getpass.getuser(), + help='username for SSH authentication (default: %s)' % getpass.getuser()) + parser.add_option('-K', '--key', action='store', type='string', dest='keyfile', + default=None, + help='private key file to use for SSH authentication') + parser.add_option('', '--no-key', action='store_false', dest='look_for_keys', default=True, + help='don\'t look for or use a private key file') + parser.add_option('-P', '--password', action='store_true', dest='readpass', default=False, + help='read password (for key or password auth) from stdin') + parser.add_option('-r', '--remote', action='store', type='string', dest='remote', default=None, metavar='host:port', + help='remote host and port to forward to') + options, args = parser.parse_args() + + if len(args) != 1: + parser.error('Incorrect number of arguments.') + if options.remote is None: + parser.error('Remote address required (-r).') + + g_verbose = options.verbose + server_host, server_port = get_host_port(args[0], SSH_PORT) + remote_host, remote_port = get_host_port(options.remote, SSH_PORT) + return options, (server_host, server_port), (remote_host, remote_port) + + +def main(): + options, server, remote = parse_options() + + password = None + if options.readpass: + password = getpass.getpass('Enter SSH password: ') + + client = paramiko.SSHClient() + client.load_system_host_keys() + client.set_missing_host_key_policy(paramiko.WarningPolicy()) + + verbose('Connecting to ssh host %s:%d ...' % (server[0], server[1])) + try: + client.connect(server[0], server[1], username=options.user, key_filename=options.keyfile, + look_for_keys=options.look_for_keys, password=password) + except Exception as e: + print('*** Failed to connect to %s:%d: %r' % (server[0], server[1], e)) + sys.exit(1) + + verbose('Now forwarding remote port %d to %s:%d ...' % (options.port, remote[0], remote[1])) + + try: + reverse_forward_tunnel(options.port, remote[0], remote[1], client.get_transport()) + except KeyboardInterrupt: + print('C-c: Port forwarding stopped.') + sys.exit(0) + + +if __name__ == '__main__': + main()