转自5年前的我的文章,希望还有用,struts 今天又爆安全漏洞了,坑爹啊
====================== 5年前====================
Struts2官方已经发布了多次漏洞补丁,但根源在于OGNL能调用静态办法,所以彻底解决漏洞的办法是底层禁止OGNL调用一些特定的java类,如System,Runtime类
我们底层入手,调用OGNLRuntime静态方法,设置我们自己的MethodAccessor类,能禁止OGNL在表达式中调用Runtime,System等类。这已经验证通过。
如下图从左到右,是action的参数赋值过程,为了堵住漏洞,通常是在ParameterInteceptor做过滤,但几年来,都有漏洞,如果我们在OGNLRuntime那做过滤,因为这是调用java类方法最底层的方法,所以很保险
我们目前推荐在原有过滤的基础上,增加一个patch包以对底层调用过滤,随后,公司内部已经布一个ongl_patch.jar,基本上引入后,在项目的servlet/struts/spring 任何一个框架的listener里调用里面的方法初始化一下,就可以了
其实质就是做如下初始化:
OgnlRuntime.setMethodAccessor(OgnlTest.class, new NoMethodAccessor());
OgnlRuntime.setMethodAccessor(Runtime.class, new NoMethodAccessor());
OgnlRuntime.setMethodAccessor(System.class, new NoMethodAccessor());
OgnlRuntime.setMethodAccessor(ProcessBuilder.class,
new NoMethodAccessor());
OgnlRuntime
.setMethodAccessor(OgnlRuntime.class, new NoMethodAccessor());
NoMethodAccessor实现了OGNL的 MethodAccessor,
如下:
public class NoMethodAccessor implements MethodAccessor {
public NoMethodAccessor() {
int i = 1;
}
@Override
public Object callStaticMethod(Map context, Class targetClass,
String methodName, Object[] args) throws MethodFailedException {
throw new MethodFailedException("do not run", "123");
}
@Override
public Object callMethod(Map context, Object target, String methodName,
Object[] args) throws MethodFailedException {
// TODO Auto-generated method stub
throw new MethodFailedException("do not run", "123");
}
}
======================
上面的初始化·可以在系统启动的地方使用,实际上,beetl的安全管理器就来自于这个想法,所以,如果你访问beetl的在线体验, 你可以调用@java.util.Collections 下的所有方法,但你不能调用@java.lang.Runtime......