如何在反序列化之前验证对象

Tec*_*oob 7 java validation serialization deserialization fortify

在我的代码中,我从一个从JMS队列接收的ObjectMessage对象调用getObject()方法.Fortify报告抱怨这个带有错误名称的getObject()方法Dynamic Code Evaluation: Unsafe Deserialization.基本上它说,我不应该在不验证对象流内容的情况下反序列化不受信任的数据.下面是代码.我应该如何以及用什么方法来摆脱这个Fortify报告错误.

if (message instanceof ObjectMessage) {
    ObjectMessage objMessage = (ObjectMessage) message;
    Object objReportMessage = objMessage.getObject();
....
Run Code Online (Sandbox Code Playgroud)

以下是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;
...
}
Run Code Online (Sandbox Code Playgroud)

示例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);
Run Code Online (Sandbox Code Playgroud)

建议 如果可能,请不要在不验证对象流内容的情况下反序列化不受信任的数据.为了验证被反序列化的类,应该使用先行反序列化模式.对象流将首先包含类描述元数据,然后包含其成员字段的序列化字节.Java序列化过程允许开发人员读取类描述并决定是继续对象的反序列化还是中止它.为了做到这一点,有必要继承java.io.ObjectInputStream并提供resolveClass(ObjectStreamClass desc)方法的自定义实现,其中类验证和验证应于2016年9月29日,下午5:09版权所有2015 Hewlett Packard Enterprise Development LP 13发生.现有的前瞻模式实现可以很容易地使用,例如Apache Commons IO(org.apache.commons.io.serialization.ValidatingObjectInputStream).始终使用严格的白名单方法仅对预期类型进行反序列化.建议不要使用黑名单方法,因为攻击者可以使用许多可用的小工具来绕过黑名单.此外,请记住,虽然一些实现代码执行的类是公知的,但可能还有其他未知或未公开的类,因此白名单方法始终是首选.应审核白名单中允许的任何类,以确保反序列化是安全的.为避免拒绝服务攻击,建议您覆盖resolveObject(Object obj)方法,以计算反序列化的对象数,并在超过阈值时中止反序列化.当反序列化发生在库或框架中时(例如,当使用JMX,RMI,JMS,HTTP Invokers时),上述建议没有用,因为它超出了开发人员的控制范围.在这些情况下,您可能希望确保这些协议符合以下要求: - 未公开公开. - 使用身份验证. - 使用完整性检查. - 使用加密.此外,每次应用程序从ObjectInputStream执行反序列化时,HPE Security Fortify Runtime都会提供安全控制,从而保护应用程序代码以及库和框架代码免受此类攻击.

wre*_*ang 8

如果您查看建议中的提示部分,则表明即使实现了先行的ObjectInputStream,也会报告该问题.因此,即使你能够解决问题,你也无法摆脱这一发现.

但是,看起来您的代码使用JMS和JMS,您不能控制反序列化.您复制和粘贴的建议可以识别这一点:

当反序列化发生在库或框架中时(例如,当使用JMX,RMI,JMS,HTTP Invokers时),上述建议没有用,因为它超出了开发人员的控制范围.在这些情况下,您可能希望确保这些协议满足以下要求:

  • 没有公开曝光.
  • 使用身份验证
  • 使用完整性检查.
  • 使用加密.

因此,您真正的解决方法是确保遵循这四个要点.您必须对您的连接进行研究,并根据您的要求和限制进行研究,这可能是不可能的.


小智 5

看一下ValidatingObjectInputStream.基本上,您将允许反序列化的类列入白名单(您应该根据您提供的信息了解这些类).然后验证器将检查元数据到序列化数据并拒绝任何不在白名单中的类.