使用 xstream 进行恶意对象注入
我可以安全地使用 XStream 处理来自系统外部的 XML 吗? 使用 xstream 处理“潜在恶意 XML”时的最佳实践是什么?
比方说,我的代码中有一个类,如下所示:
package hazard;
class Dangerous {
public Dangerous() {
AtomicBomb.getInstance().nuke();
}
}
恶意用户可能会提交一个 XML 文件,例如:
<hazard.Dangerous/>
并使 XStream 调用 nuke() 方法。
这个例子非常理论化。正如所指出的,我不希望构造函数做这种事情。但我可以确定类路径中可用的任何库中的构造函数都没有此类问题(例如,分配一些资源,例如文件描述符)。
关键是发送 XML 文件允许攻击者创建任意对象。一种更现实的方法可能是使用某个类而不是另一个类。
public class Foo<T implements Bar> {
private T t;
// Getters/setters ...
}
public interface Bar {
public void bar();
}
public class Bar1 implements Bar {
// ...
}
public class Bar2 implements Bar {
// ...
}
使用(恶意)XML 输入:
<foo>
<!-- I expect bar1 -->
<package.Bar2/>
</foo>
现在使用 Java 代码:
Bar<Foo1> bar = (Bar<Foo1>) xstream.fromXML(xml);
// I expect to have a bar1 but I have a bar2.
bar.getT().foo();
乍一看,解决方案是提供一个自定义 Mapper(该工作在 realClass() 方法中完成)。
Can I safely use XStream to process XML coming from outside of my system ?
What's the best practice when dealing with "potentially malicious XML" using xstream ?
Let's say, I have a class somewhere in my code like this :
package hazard;
class Dangerous {
public Dangerous() {
AtomicBomb.getInstance().nuke();
}
}
A malicious user, might submit a XML file such as :
<hazard.Dangerous/>
and make XStream calls the nuke() method.
This example is quite theoretical. As was pointed out, I do not expect constructor to do this kind of things. But can I be certain that no constructor in any lib available in the classpath is free from such issues (for example, allocate some ressource like a file descriptor).
The point is that sending a XML file allows an attacker to create arbitrary objects. A more realistic approach might be using some class instead of another one.
public class Foo<T implements Bar> {
private T t;
// Getters/setters ...
}
public interface Bar {
public void bar();
}
public class Bar1 implements Bar {
// ...
}
public class Bar2 implements Bar {
// ...
}
With the (malicious) XML input :
<foo>
<!-- I expect bar1 -->
<package.Bar2/>
</foo>
Now with the Java code :
Bar<Foo1> bar = (Bar<Foo1>) xstream.fromXML(xml);
// I expect to have a bar1 but I have a bar2.
bar.getT().foo();
At first glance, the solution is to provide a custom Mapper (the job being done in the realClass() method).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
永远不要允许 xstream(或任何其他序列化框架)编组除干净、纯 javabean(getter 和 setter)之外的任何内容。
更新:
您提到的有关使用映射器的理论应该有效,尽管它需要您构建一定数量的脚手架和自定义配置。另一种方式是利用XStream的特性来指定一个专用的类加载器来解析类。您将尝试将所有应该允许由 xstream 编组的类放入单独的 JAR 中(将其视为域模块)。然后创建一个干净的类加载器,仅加载该 JAR 并将其分配给 xstream。这样,xstream 将不知道其范围之外的任何类,从而无法反序列化您不希望它执行的任何内容。
尝试类似的东西
Never ever allow xstream (or any other serialization framework) to marshal anything but clean, pure javabeans (getters and setters).
UPDATE:
Your mentioned theory about using a Mapper should work, although it will require some amount of scaffolding and custom config being built by you. Another way is to use the feature of XStream to specify a dedicated classloader for resolving classes. What you would try is to put all classes that SHOULD be allowed to be marshalled by xstream in a separate JAR (think of it as a domain module). Then create a clean classloader that only loads that JAR and assign it to xstream. That way, xstream will not know of any classes outside of it's scope, failing to deserialize anything you don't want it to.
Try something like
如果您的开发团队中有人调用
DangerousClass()
怎么办? XStream 将保留该对象,如果您正在读取该对象并且 XML 已更改,您最多将收到 ClassCastException。尝试改变你的类的结构,然后使用XStream读入,你会得到错误。如果保留将在数据库查询中使用的参数,请确保使用准备好的语句。如果您将可能损坏系统的代码放入对象构造函数中,那就是错误的编码实践。使用构造函数来初始化值,而不是调用代码,这就是方法的用途。
如果编码正确,就不应该存在与 XStream 相关的安全风险。
What if someone on your development team calls
DangerousClass()
? XStream is going to persist the object, if you are reading this in and the XML has changed, you will receive at best a ClassCastException.Try changing the structure of your class and then read in using XStream, you will get errors. If you persist parameters which will be used in a DB query, make sure you use prepared statements. If you put code in an objects constructor that could damage a system, that is your bad coding practice. Use your constructor for initializing values, not calling code, that is what methods are for.
If you code properly there should be no security risks associated with XStream.