lanjelot / patator

Patator is a multi-purpose brute-forcer, with a modular design and a flexible usage.
GNU General Public License v2.0
3.57k stars 782 forks source link

Adding proxy to SSH_login module #17

Open SingularBunny opened 9 years ago

SingularBunny commented 9 years ago

There's some useful addition that allow to use proxy in SSH login process.

try:
  import socks #importing SocksiPy library that allow use proxy (http://socksipy.sourceforge.net)
except ImportError:
  notfound.append('socksipy')

#Modified SSH_login class
class SSH_login:
  '''Brute-force SSH'''

  usage_hints = (
    """%prog host=10.0.0.1 user=root password=FILE0 0=passwords.txt -x ignore:mesg='Authentication failed.'""",
    )

  available_options = (
    ('host', 'target host'),
    ('port', 'target port [22]'),
    ('user', 'usernames to test'),
    ('password', 'passwords to test'),
    ('auth_type', 'type of password authentication to use [password|keyboard-interactive|auto]'),
    ('keyfile', 'file with RSA, DSA or ECDSA private key to test'),
    #Proxy options
    ('proxy_type', 'type of the proxy server [SOCKS4|SOCKS5|HTTP]'),
    ('proxy_addr', 'IP address or DNS name of the proxy server'),
    ('proxy_port', 'port of the proxy server [1080 for socks|8080 for http]'),
    ('proxy_rdns', 'boolean flag than modifies the behavior regarding DNS resolving (if True, DNS resolving will be \
    preformed remotely (Socks4a, Socks5, HTTP) [True]'),
    ('proxy_username', 'for Socks5 servers this allows simple username / password authentication, for Socks4 servers, \
    this parameter will be sent as the userid, ignored if an HTTP server is being used'),
    ('proxy_password', 'parameter is valid only for Socks5 servers and specifies the respective password for the \
    username provided')
    )
  available_options += TCP_Cache.available_options

  Response = Response_Base

  # connect method take some addition attributes for proxying
  def connect(self, host, port, user, proxy_type=None, proxy_addr=None, proxy_port=None, proxy_rdns=True,
              proxy_username=None, proxy_password=None):

    # Replace paramiko socket with socksipy object if proxy is defined.
    if proxy_type and proxy_addr is not None:
        socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS4 if proxy_type.upper() == 'SOCKS4' else socks.PROXY_TYPE_SOCKS5
                              if proxy_type.upper() == 'SOCKS5' else socks.PROXY_TYPE_HTTP, proxy_addr, int(proxy_port),
                              proxy_rdns, proxy_username, proxy_password)
        paramiko.client.socket.socket = socks.socksocket

    fp = paramiko.Transport('%s:%s' % (host, int(port)))
    fp.start_client()

    return TCP_Connection(fp, fp.remote_version)

  def execute(self, host, port='22', user=None, password=None, auth_type='password', keyfile=None, persistent='1',
              **proxy_params): #Proxy parameters sent thorough execute() method in **kwargs

    with Timing() as timing:
      fp, banner = self.bind(host, port, user, **proxy_params)
    try:
      if user is not None:

        if keyfile is not None:
          key = load_keyfile(keyfile)

        with Timing() as timing:

          if keyfile is not None:
            fp.auth_publickey(user, key)

          elif password is not None:
            if auth_type == 'password':
              fp.auth_password(user, password, fallback=False)

            elif auth_type == 'keyboard-interactive':
              fp.auth_interactive(user, lambda a,b,c: [password] if len(c) == 1 else [])

            elif auth_type == 'auto':
              fp.auth_password(user, password, fallback=True)

            else:
              raise NotImplementedError("Incorrect auth_type '%s'" % auth_type)

      logger.debug('No error')
      code, mesg = '0', banner

      self.reset()

    except paramiko.AuthenticationException as e:
      logger.debug('AuthenticationException: %s' % e)
      code, mesg = '1', str(e)

    if persistent == '0':
      self.reset()

    return self.Response(code, mesg, timing)
SingularBunny commented 9 years ago

Or without monkeypatch:

   def connect(self, host, port, user, proxy_type=None, proxy_addr=None, proxy_port=None, proxy_rdns=True,
                proxy_username=None, proxy_password=None):

        # Replace paramiko socket with socksipy object if proxy is defined.
        if proxy_type and proxy_addr is not None:
            sock = socks.socksocket()
            sock.set_proxy(socks.PROXY_TYPE_SOCKS4 if proxy_type.upper() == 'SOCKS4' else socks.PROXY_TYPE_SOCKS5
            if proxy_type.upper() == 'SOCKS5' else socks.PROXY_TYPE_HTTP, proxy_addr,
                           int(proxy_port), proxy_rdns, proxy_username, proxy_password)
            sock.connect((host, int(port)))
        else:
            sock = '%s:%s' % (host, int(port))
        fp = paramiko.Transport(sock)
        fp.start_client()

        return patator.TCP_Connection(fp, fp.remote_version)

New version of socksipy with bugfixes and additions: https://github.com/Anorov/PySocks