草庐IT

Fastjson 代码执行 CVE-2022-25845

蚁景科技 2023-03-28 原文

漏洞简介

  Fastjson 代码执行漏洞,该漏洞允许攻击者绕过 Fastjson 中的"AutoTypeCheck"机制并实现远程代码执行

  影响版本:1.2.80及以下版本,即<= 1.2.80

漏洞复现

  我们利用 idea 创建 maven 项目 搭建漏洞环境,在 pom 文件中添加

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>fastjson</artifactId>
   <version>1.2.82</version>
</dependency>

  创建文件夹 com.example.fastjson

  在下面添加两个 java 文件

package com.example.fastjson;

import java.io.IOException;

public class Poc extends Exception {
   public void setName(String str) {
       try {
           Runtime.getRuntime().exec(str);
      } catch (IOException e) {
           e.printStackTrace();
      }
  }
}

  

package com.example.fastjson;
import com.alibaba.fastjson.JSON;

public class PocDemo {
   public static void main(String[] args) {
       String json = "{\"@type\":\"java.lang.Exception\",\"@type\":\"com.example.fastjson.Poc\",\"name\":\"calc\"}";
       JSON.parse(json);
  }
}

  运行 PocDemo

【----帮助网安学习,以下所有学习资料免费领!加vx:yj009991,备注 “博客园” 获取!】

 ① 网安学习成长路径思维导图
 ② 60+网安经典常用工具包
 ③ 100+SRC漏洞分析报告
 ④ 150+网安攻防实战技术电子书
 ⑤ 最权威CISSP 认证考试指南+题库
 ⑥ 超1800页CTF实战技巧手册
 ⑦ 最新网安大厂面试题合集(含答案)
 ⑧ APP客户端安全检测指南(安卓+IOS)

漏洞分析

AutoType

  我们知道在 fastjson 1.2.25 后设定了 autoType 只有打开 autoType之后,fastjson 是基于内置黑名单来实现安全的,如此可能会造成安全风险,就是绕过黑名单

  不开启时,是基于白名单进行防护的,这个漏洞的产生就是未开启 autoType 时产生的。

  但是未开启 autoType 时是基于白名单,是很难实现代码执行的,所以我们就需要想办法 Bypass AutoType 默认禁用策略,可以实现调用任意类

  开启 autoType 后,最终调用的是 config.checkAutoType

  com.alibaba.fastjson.parser.ParserConfig#checkAutoType(java.lang.String, java.lang.Class<?>, int)

  其中声明了各种被黑名单列入的类,是通过十六进制来记录各种类,可以在 fastjson-blacklist,看到具体类的名称

Throwable

  我们注意到在 com.alibaba.fastjson.parser.deserializer.ThrowableDeserializer#deserialze 中也同样调用了 checkAutoType

  同时我们可以发现在 com.alibaba.fastjson.parser.ParserConfig#getDeserializer(java.lang.Class<?>, java.lang.reflect.Type) 会检测目标类中是否属于Throwable 的扩展,之后就会调用 ThrowableDeserializer.deserialize()

  所以初步得出结论,如果目标类属于 Throwable 的扩展类,就可以实现打开autoType的类似操作,去调用任何类

  为了验证这个猜测,我们修改一下文件

package com.example.fastjson;

import java.io.IOException;

public class Poc extends Error {
   public void setName(String str) {
       try {
           Runtime.getRuntime().exec(str);
      } catch (IOException e) {
           e.printStackTrace();
      }
  }
}

  依然可以利用成功

  继续关注函数 com.alibaba.fastjson.parser.ParserConfig#getDeserializer(java.lang.Class<?>, java.lang.reflect.Type) 会调用 createException 去创建反序列化函数

  com.alibaba.fastjson.parser.deserializer.ThrowableDeserializer#createException

  最后还是在函数 com.alibaba.fastjson.parser.ParserConfig#getDeserializer(java.lang.Class<?>, java.lang.reflect.Type) 中实现了代码执行

  如此整个漏洞就分析完成了

漏洞修复

  官方提供了以下四种修复方式

  ● 升级到最新版本1.2.83

  ● safeMode加固

  ● 升级到fastjson v2

  ● noneautotype版本

 

总结反思

  整个漏洞的分析花了很多时间,根据参考文章 CVE-2022-25845 – Analyzing the Fastjson “Auto Type Bypass” RCE vulnerability 来来回回加断点调试了很久。对这个漏洞做一个自己的总结。在默认未开启 AutoType 时,Fastjson 是基于白名单的获取外部类,通过 搜索checkAutoType 发现ThrowableDeserializer#deserialze 中的调用,当然也不止这一处,只是这处能进一步的利用,通过满足类属于 Throwable 的扩展类就可以触发,最后实现代码执行。但是这个代码在实际场景中的利用要求较为苛刻,首先满足类是 Throwable 的扩展类,同时其中必须有危险的 set 方法。

  更多靶场实验练习、网安学习资料,请点击这里>>

 

有关Fastjson 代码执行 CVE-2022-25845的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  4. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  5. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  6. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  7. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  8. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  9. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  10. ruby - 检查是否通过 require 执行或导入了 Ruby 程序 - 2

    如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby​​文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否

随机推荐