1

I'm writing a web app using python flask and python3, and would like to use the metasploit API. When writing code with python2, everything works as it should (as the lib was written for python2). However, when attempting to use it in python 3, i'm given this error:

File "/usr/local/lib/python3.6/dist-packages/msfrpc.py", line 64, in login
    raise self.MsfAuthError("MsfRPC: Authentication failed")
msfrpc.MsfAuthError: 'MsfRPC: Authentication failed'

The only difference in the msfrpc.py file between the python2 and python 3 versions is that the py2 version includes "httplib" and uses "httplib.HTTPSConnection" to connect to the msgrpc service, and the py3 version includes "http.client" and uses "http.client.HTTPConnection" to connect to the service.

Anyone know why this error is happening?

Here is the source code for msfrpc.py: import msgpack import http.client

class Msfrpc:
  class MsfError(Exception):
    def __init__(self,msg):
      self.msg = msg
    def __str__(self):
      return repr(self.msg)

  class MsfAuthError(MsfError):
    def __init__(self,msg):
      self.msg = msg

  def __init__(self,opts=[]):
    self.host = opts.get('host') or "127.0.0.1"
    self.port = opts.get('port') or 55552
    self.uri = opts.get('uri') or "/api/"
    self.ssl = opts.get('ssl') or False
    self.authenticated = False
    self.token = False
    self.headers = {"Content-type" : "binary/message-pack" }
    if self.ssl:
      self.client = http.client.HTTPConnection(self.host,self.port)
    else:
      self.client = http.client.HTTPConnection(self.host,self.port)

  def encode(self,data):
    return msgpack.packb(data)
  def decode(self,data):
    return msgpack.unpackb(data)

  def call(self,meth,opts = []):
    if meth != "auth.login":
      if not self.authenticated:
        raise self.MsfAuthError("MsfRPC: Not Authenticated")

    if meth != "auth.login":
      opts.insert(0,self.token)

    opts.insert(0,meth)
    params = self.encode(opts)
    self.client.request("POST",self.uri,params,self.headers)
    resp = self.client.getresponse()
    return self.decode(resp.read()) 

  def login(self,user,password):
    ret = self.call('auth.login',[user,password])
    if ret.get('result') == 'success':
        self.authenticated = True
        self.token = ret.get('token')
        return True
    else:
        raise self.MsfAuthError("MsfRPC: Authentication failed")
juddev
  • 11
  • 1

1 Answers1

0

I'm not sure if I should bring this question back from the dead, but I had the same question a bit ago and I figured out the problem/solution so I'll post it here:

Python msfrpc works with python2, throws authentication error with python 3

The problem was that msfrpc was originally written in Python 2, and therefore the prefix of 'b' in the msgpack RPC responses from the Metasploit host was ignored but it is required in Python 3 to indicate that the literal should become a bytes literal instead of a Unicode string type.

For some more info, here's a link to a post that helped me figure it out: https://timothybramlett.com/Strings_Bytes_and_Unicode_in_Python_2_and_3.html

The corrected code I posted in the link above works fine (you just have to put a "b" in front of the strings returned from the server to tell Python that the 0's and 1's in the responses are bits/bytes and not Unicode code points), but really a better solution is to use the msfrpc module written by Dan McInerney which in addition to "indicating bytes", instead of 'http.client' uses the 'requests' package.

https://github.com/DanMcInerney/msfrpc

vdud3
  • 1
  • 3