在我的代码中,我从一个从JMS队列接收的ObjectMessage对象调用getObject()方法。 Fortify报告抱怨这个getObject()方法,错误名称如此Dynamic Code Evaluation: Unsafe Deserialization
。
基本上它说,我不应该在不验证对象流内容的情况下反序列化不受信任的数据。下面是代码。
我应该如何以及用什么方法来摆脱这个Fortify报告错误。
if (message instanceof ObjectMessage) {
ObjectMessage objMessage = (ObjectMessage) message;
Object objReportMessage = objMessage.getObject();
....
这是Fortify报告的问题以及建议。然后它将此错误指向上面的代码objMessage.getObject();
动态代码评估:不安全的反序列化(1期)
抽象 在运行时反序列化用户控制的对象流可以允许攻击者在其上执行任意代码 服务器,滥用应用程序逻辑或导致拒绝服务。
解释 Java序列化将对象图转换为包含对象本身和对象的字节流 必要的元数据,以从字节流重建它们。开发人员可以创建自定义代码来帮助 在反序列化Java对象的过程中,它们甚至可以替换反序列化的对象 不同的对象或代理。定制的反序列化过程发生在对象期间 在将对象返回到应用程序并转换为预期类型之前进行重建。到...的时候 开发人员尝试强制执行期望的类型,代码可能已经执行。 自定义反序列化例程在可序列化类中定义,这些类需要存在于 运行时类路径并且不能被攻击者注入,因此这些攻击的可利用性取决于 应用程序环境中可用的类。不幸的是,常见的第三方类甚至 可以滥用JDK类来耗尽JVM资源,部署恶意文件或运行任意代码。 某些协议在传输层的后台使用Java序列化。 RMI和JMX是 这些协议的例子。
示例1 :以下是可公开公开的RMI接口示例,其中包含方法 一个或多个参数。远程调用这些方法时,参数将在反序列中反序列化 服务器允许攻击者注入恶意对象图。
public interface MyService extends java.rmi.Remote {
public Object doSomething (Object arg0) throws RemoteException;
public Object doSomethingElse (Object arg0, Object arg1) throws
RemoteException;
...
}
示例2 :JMX MBean还使用Java序列化来传输调用参数。在下面的例子中, MyManagedBean类方法将向客户端公开。
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("com.example:type=MyManagedBean");
MyManagedBean mbean = new MyManagedBean();
mbs.registerMBean(mbean, name);
建议 如果可能,请不要在不验证对象流内容的情况下反序列化不受信任的数据。为了 验证要反序列化的类,应该使用前瞻反序列化模式。 对象流将首先包含类描述元数据,然后包含它们的序列化字节 成员字段。 Java序列化过程允许开发人员阅读类描述并做出决定 是继续对象的反序列化还是中止它。为了做到这一点,有必要 子类java.io.ObjectInputStream并提供自定义的实现 resolveClass(ObjectStreamClass desc)方法,其中类验证和验证应该 2016年9月29日,下午5:09 版权所有2015 Hewlett Packard 企业发展LP 13 发生。 现有的前瞻模式实现可以很容易地使用,例如Apache Commons IO(org.apache.commons.io.serialization.ValidatingObjectInputStream)。 始终使用严格的白名单方法仅对预期类型进行反序列化。黑名单方法不是 建议攻击者可以使用许多可用的小工具来绕过黑名单。另外,请记住 虽然一些实现代码执行的类是公知的,但可能还有其他类 未知或未公开,因此白名单方法始终是首选。白名单中允许的任何类别 应该进行审核以确保反序列化是安全的。 为避免拒绝服务攻击,建议您覆盖resolveObject(Object obj)方法,以计算反序列化的对象数量,并在何时中止反序列化 超过了一个门槛。 反序列化发生在库或框架中时(例如,当使用JMX,RMI,JMS,HTTP Invokers时) 上述建议没有用,因为它超出了开发人员的控制范围。在这种情况下,你可以 希望确保这些协议满足以下要求: - 不公开曝光。 - 使用身份验证。 - 使用完整性检查。 - 使用加密。 此外,HPE Security Fortify Runtime还提供每次执行时都要执行的安全控制 应用程序从ObjectInputStream执行反序列化,但保护应用程序代码 还有来自此类攻击的库和框架代码。
答案 0 :(得分:6)
如果您查看建议中的提示部分,则表明即使实现了先行的ObjectInputStream,也会报告该问题。因此,即使你能够解决问题,你也无法摆脱这一发现。
但是,看起来您的代码正在使用JMS和JMS,您无法控制反序列化。您可以通过复制和粘贴的建议识别这一点:
当反序列化发生在库或框架中时(例如,当使用JMX,RMI,JMS,HTTP Invokers时),上述建议没有用,因为它超出了开发人员的控制范围。在这些情况下,您可能希望确保这些协议满足以下要求:
- 不公开曝光。
- 使用身份验证。
- 使用完整性检查。
- 使用加密。
因此,您真正的解决方法是确保遵循这四个要点。您必须研究您的连接,并根据您的要求和限制,这可能是不可能的。
答案 1 :(得分:5)
看看ValidatingObjectInputStream。基本上,您将允许反序列化的类列入白名单(您应该根据您提供的信息了解这些类)。然后,验证器将检查序列化数据的元数据,并拒绝任何不在白名单中的类。
答案 2 :(得分:2)
万一有人访问此旧帖子,我可以通过从ObjectMessage切换到TextMessage并仅发送JSON而不是序列化的对象来解决此问题。
This post was very informative
//Sender
ObjectMapper mapper = new ObjectMapper();
TextMessage message = session.createTextMessage(mapper.writeValueAsString(foo));
messageBus.send(message);
//Receiver
ObjectMapper mapper = new ObjectMapper();
try {
Foobar foo= mapper.readValue(textMessage.getText(), new TypeReference<Foobar>(){});
dataHandlerProcess(foo);
} catch (IOException e) {
logger.error("Could not parse Foobar JSON ",e );
return;
}