使用 RMI 编写安全的 Java 代码
这似乎是一个非常广泛的问题,但我们将不胜感激。
我有一个用 java 编写的客户端/服务器解决方案,它使用 Cajo 项目(使用 RMI)。考虑到将在服务器和客户端之间传输的敏感数据,我只想尝试使我的解决方案尽可能安全。
到目前为止,我的想法是使我的所有类成为“最终”类,并为服务器中的所有类抛出“不可序列化”异常(RMI 注册表中绑定的对象以及实际需要的任何对象除外)当然要转移)。
有人能想到其他想法吗?
我知道有人可能会编写恶意客户端 - 这并不难,因为您可以使用反射找出远程对象的 API。但是,我可以做些什么来保护恶意客户端访问服务器中不应该访问的类/对象吗?
非常感谢
更新: 感谢大家提供的有用提示,很抱歉花了这么长时间才回复您。我目前的思路是建立一个安全的系统:
- 在客户端和服务器之间使用 OpenVPN。这意味着您需要访问物理客户端才能获得访问权限。 (注意,由于以下两点,VPN实际上将在服务器和办公室LAN之间。我觉得这足够安全)
- 使用用户名和密码(可能使用JBOSS)在服务器和客户端之间进行身份验证。这意味着要在服务器上完成任何操作,攻击者都需要用户名和密码。
- 为所有对象引发“不可序列化”异常,但实际应该通过网络发送的对象除外。这会阻止敏感对象通过网络发送。
这听起来公平吗?如果我遗漏了什么,请纠正我。
进一步更新:看来我试图防止的事情似乎有些混乱。我试图防止的是有人“入侵”服务器。例如,基本上利用服务器转储/删除其整个数据库。
谢谢
This may seem like a very broad question, but any help is appreciated.
I have a client/server solution written in java which uses the Cajo project (which uses RMI). I just want to try and make my solution as secure as possible, given the sensitive data that will be transferred between server and client.
So far, my ideas are to make all my classes "final" as well as throw a "non-serializable" exception for all my classes in the server (except for the object bound in the RMI registry, and any objects that actually do need to be transferred of course).
Can anyone think of any other ideas?
I know that someone could write a malicious client - this isn't hard to do as you can find out the remote object's API using reflection. However is there anything I can do to protect a malicious client access classes/objects within the server that they are not supposed to access?
Many Thanks
Update:
Thanks everyone for the helpful tips, and sorry it took so long to get back to yous. My current train of thought is this for make a secure system:
- Use OpenVPN between the clients and the server. This means that you need access to the physical client to gain access. (N.B. Due to the 2 points below, the VPN will actually be between the server and the office LAN. I feel that this is secure enough)
- Use usernames and password (maybe using JBOSS) for authentication between server and client. This means that for anything to get done on the server, an attacker would need the username and password.
- Throw a "Non-serizable" exception for all objects, except the ones that are actually supposed to be sent over the network. This stops sensitive objects from being sent over the network.
Does that sound fair? Please correct me if I'm missing anything.
Further Update: It appears there seems to be some confusion over what I'm trying to prevent against. What I'm trying to prevent, is someone from "hacking" the server. So basically exploiting the server to dump/drop its entire database, for example.
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
保护通过 RMI 与潜在受损系统连接的系统非常困难。首先要做的是使用 java.rmi.server.useCodebaseOnly 系统属性禁用 RMI 的动态代码加载功能 - 不再有移动代码(通过此通道)。正如 RMI 人员 Stuart Marks 所指出的,该属性现在默认情况下是安全的,符合 Oracle 策略。
Protecting a system that connects with potentially compromised systems over RMI is very difficult. The first thing to do is to disable the dynamic code loading feature of RMI using the
java.rmi.server.useCodebaseOnly
system property - no more mobile code (via this channel). As RMI man Stuart Marks notes, this property is now secure by default, in line with Oracle policy.Cajo 是否只允许您调用导出对象上的方法?如果是这样,只需导出安全远程调用的对象即可。否则,如果您希望主机安全,则必须使用沙箱 。另请参阅此。
您将需要 SSL 来防止网络流量的嗅探/修改。
Does Cajo only let you invoke methods on exported objects? If so, simply only export safe-to-be-invoked-remotely objects. Otherwise you are forced to use the sandbox if you want the hosts to be secure. Also see this.
You will need SSL to prevent sniffing/modification of network traffic.
我将使用自定义套接字工厂来加密所有 RMI 数据。例如,使用 SSL 将防止查看数据、修改数据和重放攻击。
本教程介绍如何创建自定义 RMI 套接字工厂,以及基于 SSL 的 RMI 的一般讨论。
这可能看起来需要大量工作,但如果您确实必须向授权者隐藏敏感数据,那么将对象设为 Final 将根本无法提供任何真正的安全性 - 敏感数据仍然可以读。
编辑:这几乎是一个没有实际意义的问题,因为OP在下面的评论中提到正在使用VPN。
I would use a custom socket factory to encrypt all the RMI data. E.g. Using SSL will prevent viewing the data, modifying it, and replay attacks.
This tutorial describes how to create a custom RMI socket factory, and a general discussion of RMI over SSL.
It might seem like a lot of work, but if you really must hide sensitive data from anauthorized eyes, then making objects final will simply not provide any real security - the sensitive data can still be read.
EDIT: This is all pretty much a moot point, since the OP mentioned in comments below that a VPN is being used.
您提到您正在使用 VPN,因此恶意客户端要连接到您的服务器,就必须破坏您的 VPN,或者在可以合法访问您的 VPN 的计算机上安装流氓软件。
一旦完成此操作,就没有简单的方法可以区分流氓客户端和授权软件。您可以向客户端软件的每个用户提供额外的凭据以进行额外的身份验证,但如果客户端计算机受到攻击,这些凭据可能会受到损害。更强大的身份验证方案是向每个用户发送一个计算访问代码的小“小部件”。恶意客户端将无法访问此内容,并且它不能单独受到软件的影响,因为它在物理上与客户端计算机是分开的。将其与每个用户的用户名/密码相结合将阻止一个用户窃取另一用户的小部件。
根据您想要的安全程度以及您准备投入多少精力,这可能是多余的。如果您主要关心的是防范来自流氓客户端与使用该软件的普通用户的自动攻击,您可以通过在登录时提供验证码来实现“我是人类”身份验证。
You mention that you are using VPN, so for a malicious client to connect to your server, they would have to comprimise your VPN, or install rogue software on a machine with legitimate access to your VPN.
Once this is done, then there is no easy way to distinguish a rogue client from your authorized software. You could proide additional credentials to each user of your client software for additional authentication, but these can be comprimised if the client machine is comprimised. A stronger authentication scheme is to send each user a small "widget" that computes access codes. An rogue client will not have access to this, and it cannot be comprimised by software alone since it is physically separate from the client machine. Combining this with a username/password for each user will defeat one user stealing another user's widget.
Depending upon how secure you want it and how much effort you are prepared to invest, this may be overkill. If your primary concern is guarding against an automated attack from a rogue client vs a regular user using the software, you could implement "I'm a human" authentication by presenting a capcha at login.