1.Fastjson 1.2.24反序列化漏洞深度分析
2.JSON简介及在.NET中如何使用
3.element-plus源码与二次开发:package.json解析
4.如何在JavaScript中循环遍历JSON响应
5.UMI3源码解析系列之构建原理
Fastjson 1.2.24反序列化漏洞深度分析
FastJson是次解阿里巴巴推出的一款开源JSON解析库,能够实现Java对象与JSON字符串之间的析源转换。近年来,码次FastJson漏洞频出,视频本文将深入探讨年出现的解析1.2.反序列化漏洞,并分析其中的源码fkvmp 源码细节问题。
关于Fastjson 1.2.反序列化漏洞,次解已有许多分析。析源本文将重点分析以下问题:1、码次parseObject(String text)、视频parse(String text)和parseObject(String text,解析 Class clazz)三个方法的区别;2、使用TemplatesImpl攻击调用链路时,源码为何需要构造_tfactory和_name字段;3、次解_outputProperties与其getter方法getOutputProperties()名字不完全一致如何解决。析源此外,码次本文将模拟寻找漏洞利用链的思路,从执行点向上寻找入口,还原出挖掘TemplatesImpl利用链的完整过程。
关于parse(String text)、parseObject(String text)和parseObject(String text, Class clazz)三个方法,我们进行了测试。在FastJsonTest类中,变量及其setter/getter关系如下表所示。接下来,我们分别使用三种方式将JSON字符串反序列化成Java对象。
首先,我们运行Object obj = JSON.parse(jsonstr);这种方式。药品内部溯源码结果显示,setT1()、setT2()、getT4()和setT5()被调用,JSON.parse(jsonstr)最终返回FastJsonTest类的对象。接着,我们运行Object obj = JSON.parseObject(jsonstr, FastJsonTest.class);。结果与JSON.parse(jsonstr);方式相同,setT1()、setT2()、getT4()、setT5()被调用,JSON.parse(jsonstr)最终返回FastJsonTest类的对象。最后,我们运行Object obj = JSON.parseObject(jsonstr);。这次结果与前面两次大不相同,FastJsonTest类中的所有getter和setter都被调用,并且JSON.parseObject(jsonstr);返回一个JSONObject对象。
通过上述运行结果,我们发现三个问题:1、使用JSON.parse(jsonstr);与JSON.parseObject(jsonstr, FastJsonTest.class);两种方式执行后的返回结果完全相同,且FastJsonTest类中getter和setter方法调用情况也完全一致,那么parse(jsonstr)与parseObject(jsonstr, FastJsonTest.class)有何关联呢?2、使用JSON.parse(jsonstr);与JSON.parseObject(jsonstr, FastJsonTest.class);两种方式时,被调用的getter和setter方法分别为setT1()、setT2()、酷睿源码运营getT5()和getT4()。FastJsonTest类中一共有五个getter方法,分别为getT1()、getT2()、getT3()、getT4()、getT5(),为什么仅仅getT4被调用了呢?3、JSON.parseObject(jsonstr);为什么返回值为JSONObject类对象,且将FastJsonTest类中的所有getter和setter都被调用了?
关于JSON.parse(jsonstr);与JSON.parseObject(jsonstr, FastJsonTest.class);两种方式执行后的返回结果完全相同,且FastJsonTest类中getter和setter方法调用情况也完全一致,这是因为无论使用哪种方式解析json字符串,程序最终都会调用位于com/alibaba/fastjson/util/JavaBeanInfo.java中的JavaBeanInfo.build()方法来获取并保存目标Java类中的成员变量及其对应的setter和getter。
使用JSON.parse(jsonstr);与JSON.parseObject(jsonstr, FastJsonTest.class);两种方式时,被调用的getter和setter方法分别为setT1()、setT2()、getT5()和getT4(),这是因为JavaBeanInfo.build()方法中,程序会创建一个fieldList数组来存放后续将要处理的目标类的setter方法和某些特定条件的getter方法。只有getT4()这一个getter满足调用条件并被加入fieldList数组中。
JSON.parseObject(jsonstr);返回值为JSONObject类对象,且将FastJsonTest类中的所有getter和setter都被调用了,这是因为parseObject(String text)实际上是在parse()的基础上又执行了一次JSON.toJSON()。JSON.toJSON()方法会将目标类中所有getter方法记录下来,随后通过反射依次调用目标类中所有的getter方法。
总结:上文例子中,黑马疫情项目源码JSON.parse(jsonstr)与JSON.parseObject(jsonstr, FastJsonTest.class)可以认为是完全一样的,而parseObject(String text)是在二者的基础上又执行了一次JSON.toJSON()。
针对Fastjson 1.2.反序列化漏洞的利用方式有很多,本文仅对比较巧妙的TemplatesImpl攻击调用链路进行举例。后续文章将会对Fastjson历史漏洞进行详细的分析,希望大家喜欢。
JSON简介及在.NET中如何使用
JSON,全称为JavaScript Object Notation,是一种轻量级的数据交换格式,特别适合文本形式的数据传输,因其简洁易读、机器解析方便而广泛应用在各类应用程序间的数据交换和通信中。
JSON的数据结构主要包括两种:一是键值对的集合(类似于对象或数据结构),二是值的有序列表(即数组)。键值对是JSON的基本单元,格式如Key-Value对。复杂的JSON数据可以通过嵌套的方式构建,例如,一个JSON对象可以包含其他对象或数组,形成层次分明的数据结构。
尽管JSON有着诸多优势,但它也有其局限性,如缺乏数据验证机制,对数据类型的严格控制较弱。在.NET开发中,C#提供了多种处理JSON的好看的个人源码库,如System.Text.Json、Newtonsoft.Json、JavaScriptSerializer和DataContractJsonSerializer。以Newtonsoft.Json为例,可以通过NuGet包管理器或直接引用DLL文件的方式集成到项目中,用于数据的序列化和反序列化操作。
本文以Newtonsoft.Json为例,展示了在.NET中如何轻松地使用JSON。无论是数据的转换还是处理,都有相应的类库支持。通过这个案例,希望读者能对.NET中JSON的使用有个初步了解。后续还将深入探讨.NET中JSON的更多用法和相关类库的细节,敬请期待。
element-plus源码与二次开发:package.json解析
element-plus使用pnpm的workspace来搭建monorepo工程,允许在单一码仓库中集中管理大量互相依赖的包,同时确保发布时的独立性。pnpm-workspace.yaml文件在根目录声明内部可引用的包,执行pnpm i后,会在node_modules中创建软连接,无需手动link。
element-plus组件库将vue声明在peerDependencies中,避免在主项目安装组件库时额外安装vue。通过czg包定义规范,执行提交commit命令,确保遵循git规范。使用play子包进行简单的开发调试,引入本地组件库。通过gen命令快速创建新组件,使用模板生成组件基础模板。生成版本号文件命令用于在构建时提供rollup的banner参数,部署前更新版本号命令从环境变量获取TAG_VERSION和GIT_HEAD,写入到三个包的package.json中的version和gitHead字段。
清理dist目录命令使用pnpm run -r --parallel,以并行方式执行所有子包的命令,删除根目录下的dist目录,并执行所有子包的clean命令。构建文档和组件库的关键步骤包括使用rollup执行构建,通过@esbuild-kit/cjs-loader将esm和ts实时转换为CommonJS。生成类型声明文件和代码提示文件,复制源样式文件、编译为css、压缩,并输出到特定目录。启动组件库文档docs项目基于vitepress,构建组件文档,本地测试构建出的生产环境docs,生成多语言文件和CROWDIN_TOKEN。
执行各包的stub命令,使用unbuild打包工具,基于rollup,支持typescript,支持生成commonjs和esmodule和类型声明,无需额外配置。prepare Husky钩子脚本确保自动执行预定义命令,执行pnpm i后,自动执行pnpm stub,编译internal下的三个包入口。
通过上述详细解析,我们可以清晰了解到element-plus源码与二次开发中的核心功能与流程,从构建结构到构建流程,再到二次开发工具的运用,展示了其高效、灵活的特点。
如何在JavaScript中循环遍历JSON响应
从远程服务器获取数据时,服务器的响应通常为JSON格式。在本文中,我将演示如何使用JavaScript解析服务器的响应,以便访问所需的数据。该过程通常包括两个步骤:将数据解码为本机结构(例如数组或对象),然后使用JavaScript的内置方法遍历该数据结构。
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于ECMAScript(W3C制定的JS规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
数据可以通过两种方式存储在JSON中:从Web服务器接收数据时,数据始终是字符串,这意味着将其转换为可以使用的数据结构是必要工作。如果您想了解有关JSON如何工作的更多信息,可以访问JSON网站。
二、从远程API获取接口
使用XMLHttpRequest API返回的数据为:服务器返回了一个字符串。我们需要先将其解析为JavaScript对象,然后才能遍历其属性。我们可以使用JSON.parse()做到这一点。使用Fetch API尽管上面使用XMLHttpRequest对象的方法效果很好,但在复杂的场景下它就会变得非常笨拙。我们使用浏览器新提供的api,它是window对象上定义的方法fetch,你可以使用该方法执行请求。此方法返回一个Promise,可用于检索请求的响应。
Fetch API返回响应流。这不是JSON,因此JSON.parse()需要尝试使用它的response.json()函数而不是对其进行调用。这将返回一个Promise,该Promise会将响应的正文文本解析为JSON的结果进行解析。
三、多种方式遍历数据
值的有序列表(也称为数组)也是有效的JSON,让我们研究如何处理此类响应。对于这个示例,我们将使用GitHub的REST API来获取用户存储库的列表:
如您所见,API返回了一个对象数组。要访问每个单独的对象,我们可以使用常规forEach方法。另外,您当然可以使用上面讨论的任何方法来遍历对象的所有属性,并将它们记录到控制台。
结论在这篇文章中,我们研究了什么是JSON。我已经演示了如何将服务器的JSON响应解析为本机数据结构(例如数组或对象),以及如何遍历这种结构以访问其中包含的数据。我们大部分web服务与服务器的交互都是围绕这个这个展开,希望这篇文章对您有所帮助。
UMI3源码解析系列之构建原理
基于前面umi插件机制的原理可以了解到,umi是一个插件化的企业级前端框架,它配备了完善的插件体系,这也使得umi具有很好的可扩展性。umi的全部功能都是由插件完成的,构建功能同样是以插件的形式完成的。下面将从以下两个方面来了解umi的构建原理。UMI命令注册想了解umi命令的注册流程,咱们就从umi生成的项目入手。
从umi初始化的项目package.json文件看,umi执行dev命令,实际执行的是start:dev,而start:dev最终执行的是umidev。
"scripts":{ "dev":"npmrunstart:dev","start:dev":"cross-envREACT_APP_ENV=devMOCK=noneUMI_ENV=devumidev"}根据这里的umi命令,我们找到node_modules里的umi文件夹,看下umi文件夹下的package.json文件:
"name":"umi","bin":{ "umi":"bin/umi.js"}可以看到,这里就是定义umi命令的地方,而umi命令执行的脚本就在bin/umi.js里。接下来咱们看看bin/umi.js都做了什么。
#!/usr/bin/envnoderequire('v8-compile-cache');constresolveCwd=require('@umijs/deps/compiled/resolve-cwd');const{ name,bin}=require('../package.json');constlocalCLI=resolveCwd.silent(`${ name}/${ bin['umi']}`);if(!process.env.USE_GLOBAL_UMI&&localCLI&&localCLI!==__filename){ constdebug=require('@umijs/utils').createDebug('umi:cli');debug('Usinglocalinstallofumi');require(localCLI);}else{ require('../lib/cli');}判断当前是否执行的是本地脚手架,若是,则引入本地脚手架文件,否则引入lib/cli。在这里,我们未开启本地脚手架指令,所以是引用的lib/cli。
//获取进程的版本号constv=process.version;//通过yParser工具对命令行参数进行处理,此处是将version和help进行了简写constargs=yParser(process.argv.slice(2),{ alias:{ version:['v'],help:['h'],},boolean:['version'],});//若参数中有version值,并且args._[0]为空,此时将version字段赋值给args._[0]if(args.version&&!args._[0]){ args._[0]='version';constlocal=existsSync(join(__dirname,'../.local'))?chalk.cyan('@local'):'';console.log(`umi@${ require('../package.json').version}${ local}`);//若参数中无version值,并且args._[0]为空,此时将help字段复制给args._[0]}elseif(!args._[0]){ args._[0]='help';}处理完version和help后,紧接着会执行一段自执行代码:
(async()=>{ try{ //读取args._中第一个参数值switch(args._[0]){ case'dev'://若当前运行环境是dev,则调用Node.js的核心模块child_process的fork方法衍生一个新的Node.js进程。scriptPath表示要在子进程中运行的模块,这里引用的是forkedDev.ts文件。constchild=fork({ scriptPath:require.resolve('./forkedDev'),});//ref:///api/process/signal_events.html///post/