Writing a secure RMI server-client application

2019-02-18 19:46发布

问题:

I'm writing a server-client application where communication is done over the internet and I have several questions and concerns regarding security. I have done some research and found some posts here useful, but I would like more information. Some related questions I read were:

Secure authentication of client over RMI

java rmi authentication & security. exportObject makes it public?

Is communication in java rmi secure?

I have 3 parts to consider:

  1. Information exchanged between the client and the server.
  2. Authentication of the client.
  3. Exploiting a running RMI server (hacking etc.).

What I know:

  1. RMI over SSL. Using SSL sockets instead of the default socket would encrypt all information passed between the client and the server. This includes the objects exchange and method calls.
  2. Authentication using username/password combination over SSL before RMI connection has been established. To my understanding there was supposed to be a way to authenticate inside the RMI connection but it was voted down.
  3. Not too sure what can or needs to be done here. I do know that you can't just write your own client and ask to connect to the server since you need an ObjectID and the remote interfaces. However, is it not possible to decompile the classes \ interfaces you need since they are sent in RMI anyway? I also saw this Youtube video [http://www.youtube.com/watch?v=otjllNaBxiw] while researching and it got me worried with how easy it is, although I don't know if the server was not setup correctly.

All in all, are there other security issues I need to consider in RMI over the internet? Am I missing a solution I need to look at? Is what I already know wrong?

回答1:

Information exchanged between the client and the server.

RMI over SSL.

Authentication of the client.

Authentication of the client is done by SSL. You mean authorisation, which is 'relatively' easy. Define your own RMIServerSocketFactory that returns an ServerSocket override whose implAccept() method wraps the socket in an SSLSocket, to which you add a handshake listener and set needClientAuth to true on it (and clientMode to false). Your handshake listener should then get and check the client certificate from the SSLSession, to see if the identity it authenticates is authorised, and simply close the socket if non-authorised.

Authorising the server, in the client, is on the other hand baroquely complex. You really need the JERI API in Jini to do it properly.

Exploiting a running RMI server (hacking etc.).

I won't go so far as to say it's impossible, but it's extremely difficult, and there are several strong lines of defence. You need the ObjectID, which is random, and can be made securely random, and you need the classes. Classes and interfaces aren't sent in RMI unless you specifically enable it, and they are sent by a side channel that you can secure arbitrarily strongly, for example with two-way-authenticated HTTPS. So you can't get those. Then you need to get yourself authorised, which basically requires compromising the server. And if that's possible, anything is.